@@ -2,137 +2,126 @@ import { useEffect, useState } from "react"
22import Code from "../../code"
33
44export interface BitboardStep {
5- highlightLines : number [ ] // Which lines of code to highlight (1-based)
6- board : bigint | string // Bitboard after this step (64-bit integer)
5+ highlightLines : number [ ] // Which lines of code to highlight (1-based)
6+ board : bigint | string // Bitboard after this step (64-bit integer)
77}
88
99interface BitboardVisualizerProps {
10- codeLines : string [ ] // Static array of code lines (shown left-side)
11- steps : BitboardStep [ ] // Step-by-step transitions (each step updates the board and highlights lines)
12- stepDelay ?: number // Optional delay between steps (ms), default = 2000
10+ codeLines : string [ ] // Static array of code lines (shown left-side)
11+ steps : BitboardStep [ ] // Step-by-step transitions (each step updates the board and highlights lines)
12+ stepDelay ?: number // Optional delay between steps (ms), default = 2000
1313}
1414
1515export default function BitboardVisualizer ( { codeLines, steps, stepDelay = 2000 } : BitboardVisualizerProps ) {
16- const [ currentStepIndex , setCurrentStepIndex ] = useState ( 0 )
17- const [ bitIndices , setBitIndices ] = useState < number [ ] > ( [ ] )
18-
19- // Ensure we have valid steps and a valid current step
20- const currentStep = steps && steps . length > 0 ? steps [ currentStepIndex ] : { highlightLines : [ ] , board : BigInt ( 0 ) }
21- const boardValue =
22- currentStep && typeof currentStep . board === "string" ? BigInt ( currentStep . board ) : currentStep ?. board || BigInt ( 0 )
23-
24- // Convert bitboard to binary string (padded to 64 bits)
25- const binaryString = boardValue . toString ( 2 ) . padStart ( 64 , "0" )
26- // Split binary string into groups of 8 bits with spaces between
27- const formattedBinary = binaryString . match ( / .{ 1 , 8 } / g) ?. join ( " " ) || binaryString
28-
29- // Calculate which bits are set (1)
30- useEffect ( ( ) => {
31- const indices : number [ ] = [ ]
32- const boardValueBigInt = typeof boardValue === 'string' ? BigInt ( boardValue ) : boardValue
33- for ( let i = 0 ; i < 64 ; i ++ ) {
34- if ( ( boardValueBigInt & ( BigInt ( 1 ) << BigInt ( i ) ) ) !== BigInt ( 0 ) ) {
35- indices . push ( i )
36- }
37- }
38- setBitIndices ( indices )
39- } , [ boardValue ] )
40-
41- // Auto-advance steps
42- useEffect ( ( ) => {
43- const timer = setTimeout ( ( ) => {
44- setCurrentStepIndex ( ( prevIndex ) => ( prevIndex + 1 ) % steps . length )
45- } , stepDelay )
46-
47- return ( ) => clearTimeout ( timer )
48- } , [ currentStepIndex , stepDelay , steps . length ] )
49-
50- // Check if a bit is set at a specific position
51- const isBitSet = ( position : number ) => {
52- const boardValueBigInt = typeof boardValue === 'string' ? BigInt ( boardValue ) : boardValue
53- return ( boardValueBigInt & ( BigInt ( 1 ) << BigInt ( position ) ) ) !== BigInt ( 0 )
16+ const [ currentStepIndex , setCurrentStepIndex ] = useState ( 0 )
17+ const [ bitIndices , setBitIndices ] = useState < number [ ] > ( [ ] )
18+
19+ // Ensure we have valid steps and a valid current step
20+ const currentStep = steps && steps . length > 0 ? steps [ currentStepIndex ] : { highlightLines : [ ] , board : BigInt ( 0 ) }
21+ const boardValue =
22+ currentStep && typeof currentStep . board === "string" ? BigInt ( currentStep . board ) : currentStep ?. board || BigInt ( 0 )
23+
24+ // Convert bitboard to binary string (padded to 64 bits)
25+ const binaryString = boardValue . toString ( 2 ) . padStart ( 64 , "0" )
26+ // Split binary string into groups of 8 bits with spaces between
27+ const formattedBinary = binaryString . match ( / .{ 1 , 8 } / g) ?. join ( " " ) || binaryString
28+
29+ // Calculate which bits are set (1)
30+ useEffect ( ( ) => {
31+ const indices : number [ ] = [ ]
32+ const boardValueBigInt = typeof boardValue === 'string' ? BigInt ( boardValue ) : boardValue
33+ for ( let i = 0 ; i < 64 ; i ++ ) {
34+ if ( ( boardValueBigInt & ( BigInt ( 1 ) << BigInt ( i ) ) ) !== BigInt ( 0 ) ) {
35+ indices . push ( i )
36+ }
5437 }
55-
56- // Get file letter (A-H) from column index (0-7)
57- const getFile = ( col : number ) => String . fromCharCode ( 72 - col ) // H to A (reversed)
58-
59- // Get rank number (1-8) from row index (0-7)
60- const getRank = ( row : number ) => 8 - row // 8 to 1 (reversed)
61-
62- return (
63- < div className = "visualizer-container" >
64- { /* Main content - responsive layout */ }
65- < div className = "visualizer-content" >
66- { /* Left side - Code display */ }
67- < pre >
68- < Code options = { { highlightLines : currentStep ?. highlightLines . map ( line => line - 1 ) } }
69- language = "javascript"
70- children = { codeLines . join ( "\n" ) }
71- />
72- </ pre >
73-
74- < div className = "board-container" >
75- < div className = "chessboard" >
76-
77- { /* Chessboard view */ }
78- < div className = "board-grid" >
79- { Array . from ( { length : 64 } ) . map ( ( _ , index ) => {
80- const row = Math . floor ( index / 8 )
81- const col = index % 8
82- const position = row * 8 + col
83- const isDarkSquare = ( row + col ) % 2 === 1
84- const bitValue = isBitSet ( position )
85-
86- return (
87- < div
88- key = { index }
89- className = {
90- isDarkSquare
91- ? bitValue
92- ? "square dark-square bit-set"
93- : "square dark-square"
94- : bitValue
95- ? "square light-square bit-set"
96- : "square light-square"
97- }
98- >
99- < div className = { bitValue ? "bit-overlay visible" : "bit-overlay" } />
100- < span className = "square-coord" >
101- { getFile ( col ) }
102- { getRank ( row ) }
103- </ span >
104- < span className = "square-index" > { position } </ span >
105- </ div >
106- )
107- } ) }
108- </ div >
109-
110- { /* Bitboard representations */ }
111- < div className = "bitboard-info" >
112- < div className = "info-item" >
113- < span className = "info-label" > Binary: </ span >
114- < span className = "info-value binary" > { formattedBinary } </ span >
115- </ div >
116- < div className = "info-item" >
117- < span className = "info-label" > Set bits: </ span >
118- < span className = "info-value" > { bitIndices . length > 0 ? bitIndices . join ( ", " ) : "none" } </ span >
119- </ div >
120- </ div >
121- </ div >
38+ setBitIndices ( indices )
39+ } , [ boardValue ] )
40+
41+ // Auto-advance steps
42+ useEffect ( ( ) => {
43+ const timer = setTimeout ( ( ) => {
44+ setCurrentStepIndex ( ( prevIndex ) => ( prevIndex + 1 ) % steps . length )
45+ } , stepDelay )
46+
47+ return ( ) => clearTimeout ( timer )
48+ } , [ currentStepIndex , stepDelay , steps . length ] )
49+
50+ // Check if a bit is set at a specific position
51+ const isBitSet = ( position : number ) => {
52+ const boardValueBigInt = typeof boardValue === 'string' ? BigInt ( boardValue ) : boardValue
53+ return ( boardValueBigInt & ( BigInt ( 1 ) << BigInt ( position ) ) ) !== BigInt ( 0 )
54+ }
55+
56+ // Get file letter (A-H) from column index (0-7)
57+ const getFile = ( col : number ) => String . fromCharCode ( 72 - col ) // H to A (reversed)
58+
59+ // Get rank number (1-8) from row index (0-7)
60+ const getRank = ( row : number ) => 8 - row // 8 to 1 (reversed)
61+
62+ return (
63+ < div className = "visualizer-container" >
64+ < pre >
65+ < Code options = { { highlightLines : currentStep ?. highlightLines . map ( line => line - 1 ) } }
66+ language = "javascript"
67+ children = { codeLines . join ( "\n" ) }
68+ />
69+ </ pre >
70+
71+ < div className = "board-container" >
72+ < div className = "chessboard" >
73+
74+ < div className = "board-grid" >
75+ { Array . from ( { length : 64 } ) . map ( ( _ , index ) => {
76+ const row = Math . floor ( index / 8 )
77+ const col = index % 8
78+ const position = row * 8 + col
79+ const isDarkSquare = ( row + col ) % 2 === 1
80+ const bitValue = isBitSet ( position )
81+
82+ return (
83+ < div
84+ key = { index }
85+ className = {
86+ isDarkSquare
87+ ? bitValue
88+ ? "square dark-square bit-set"
89+ : "square dark-square"
90+ : bitValue
91+ ? "square light-square bit-set"
92+ : "square light-square"
93+ }
94+ >
95+ < div className = { bitValue ? "bit-overlay visible" : "bit-overlay" } />
96+ < span className = "square-coord" >
97+ { getFile ( col ) }
98+ { getRank ( row ) }
99+ </ span >
100+ < span className = "square-index" > { position } </ span >
122101 </ div >
123- </ div >
102+ )
103+ } ) }
104+ </ div >
105+ </ div >
106+ < div className = "bitboard-info" >
107+ < div className = "info-item" >
108+ < span className = "info-label" > Binary: </ span >
109+ < span className = "info-value binary" > { formattedBinary } </ span >
110+ </ div >
111+ < div className = "info-item" >
112+ < span className = "info-label" > Set bits: </ span >
113+ < span className = "info-value" > { bitIndices . length > 0 ? bitIndices . join ( ", " ) : "none" } </ span >
114+ </ div >
115+ </ div >
116+ </ div >
124117
125- < style jsx > { `
118+ < style jsx > { `
126119 .visualizer-container {
127120 width: 100%;
128121 max-width: 1200px;
129122 margin: 0 auto;
130123 }
131124
132- .visualizer-content {
133- display: block;
134- }
135-
136125 .code-line.highlighted {
137126 background-color: #fef3c7;
138127 border-left: 4px solid #f59e0b;
@@ -205,37 +194,22 @@ export default function BitboardVisualizer({ codeLines, steps, stepDelay = 2000
205194 }
206195
207196 .bitboard-info {
197+ margin-left: auto;
198+ margin-right: auto;
199+ width: 100%;
200+ max-width: 448px;
208201 margin-top: 0.25rem;
209- margin-bottom: 0.25rem;
210- display: flex;
211- flex-direction: column;
212- gap: 0.25rem;
213202 font-family: "IBM Plex Mono", monospace;
214203 font-size: 0.875rem;
215- width: 100%;
216- max-width: 448px;
217- margin-left: auto;
218- margin-right: auto;
219204 }
220205
221206 .info-item {
222207 padding: 0.5rem;
223208 background-color: #f9fafb;
224209 border-radius: 0.25rem;
225- }
226-
227- .info-item.binary {
228- overflow-x: auto;
229- }
230-
231- .info-value {
232- white-space: normal;
233- }
234-
235- .info-value.binary {
236- overflow-x: auto;
210+ margin-bottom: 0.25rem;
237211 }
238212 ` } </ style >
239- </ div >
240- )
213+ </ div >
214+ )
241215}
0 commit comments