@@ -13,12 +13,13 @@ const (
1313)
1414
1515func makeMove (brd * Board , move Move ) {
16- c := brd .c
17- piece := move .Piece ()
1816 from := move .From ()
1917 to := move .To ()
20- capturedPiece := move . CapturedPiece ( )
18+ updateCastleRights ( brd , from , to )
2119
20+ capturedPiece := move .CapturedPiece ()
21+ c := brd .c
22+ piece := move .Piece ()
2223 enpTarget := brd .enpTarget
2324 brd .hashKey ^= enpZobrist (enpTarget ) // XOR out old en passant target.
2425 brd .enpTarget = SQ_INVALID
@@ -37,21 +38,13 @@ func makeMove(brd *Board, move Move) {
3738 }
3839 case PAWN : // Destination square will be empty if en passant capture
3940 if enpTarget != SQ_INVALID && brd .TypeAt (to ) == EMPTY {
40- // fmt.Println(move.ToString())
41- // brd.Print()
42-
4341 brd .pawnHashKey ^= pawnZobrist (int (enpTarget ), brd .Enemy ())
4442 removePiece (brd , PAWN , int (enpTarget ), brd .Enemy ())
4543 brd .squares [enpTarget ] = EMPTY
4644 } else {
4745 brd .pawnHashKey ^= pawnZobrist (to , brd .Enemy ())
4846 removePiece (brd , PAWN , to , brd .Enemy ())
4947 }
50- case ROOK :
51- if brd .castle > 0 {
52- updateCastleRights (brd , to )
53- }
54- removePiece (brd , capturedPiece , to , brd .Enemy ())
5548 default : // any non-pawn piece is captured
5649 removePiece (brd , capturedPiece , to , brd .Enemy ())
5750 }
@@ -67,45 +60,29 @@ func makeMove(brd *Board, move Move) {
6760
6861 case KING :
6962 switch capturedPiece {
70- case ROOK :
71- if brd .castle > 0 {
72- updateCastleRights (brd , from )
73- updateCastleRights (brd , to ) //
74- }
75- removePiece (brd , capturedPiece , to , brd .Enemy ())
76- brd .halfmoveClock = 0 // All capture moves are irreversible.
7763 case EMPTY :
7864 brd .halfmoveClock += 1
79- if brd .castle > 0 {
80- updateCastleRights (brd , from )
81- if abs (to - from ) == 2 { // king is castling.
82- brd .halfmoveClock = 0
83- if c == WHITE {
84- if to == G1 {
85- relocatePiece (brd , ROOK , H1 , F1 , c )
86- } else {
87- relocatePiece (brd , ROOK , A1 , D1 , c )
88- }
65+ if abs (to - from ) == 2 { // king is castling.
66+ brd .halfmoveClock = 0
67+ if c == WHITE {
68+ if to == G1 {
69+ relocatePiece (brd , ROOK , H1 , F1 , c )
70+ } else {
71+ relocatePiece (brd , ROOK , A1 , D1 , c )
72+ }
73+ } else {
74+ if to == G8 {
75+ relocatePiece (brd , ROOK , H8 , F8 , c )
8976 } else {
90- if to == G8 {
91- relocatePiece (brd , ROOK , H8 , F8 , c )
92- } else {
93- relocatePiece (brd , ROOK , A8 , D8 , c )
94- }
77+ relocatePiece (brd , ROOK , A8 , D8 , c )
9578 }
9679 }
9780 }
9881 case PAWN :
99- if brd .castle > 0 {
100- updateCastleRights (brd , from )
101- }
10282 removePiece (brd , capturedPiece , to , brd .Enemy ())
10383 brd .pawnHashKey ^= pawnZobrist (to , brd .Enemy ())
10484 brd .halfmoveClock = 0 // All capture moves are irreversible.
10585 default :
106- if brd .castle > 0 {
107- updateCastleRights (brd , from )
108- }
10986 removePiece (brd , capturedPiece , to , brd .Enemy ())
11087 brd .halfmoveClock = 0 // All capture moves are irreversible.
11188 }
@@ -114,28 +91,15 @@ func makeMove(brd *Board, move Move) {
11491 case ROOK :
11592 switch capturedPiece {
11693 case ROOK :
117- if brd .castle > 0 {
118- updateCastleRights (brd , from )
119- updateCastleRights (brd , to )
120- }
12194 removePiece (brd , capturedPiece , to , brd .Enemy ())
12295 brd .halfmoveClock = 0 // All capture moves are irreversible.
12396 case EMPTY :
124- if brd .castle > 0 {
125- updateCastleRights (brd , from )
126- }
12797 brd .halfmoveClock += 1
12898 case PAWN :
129- if brd .castle > 0 {
130- updateCastleRights (brd , from )
131- }
13299 removePiece (brd , capturedPiece , to , brd .Enemy ())
133100 brd .halfmoveClock = 0 // All capture moves are irreversible.
134101 brd .pawnHashKey ^= pawnZobrist (to , brd .Enemy ())
135102 default :
136- if brd .castle > 0 {
137- updateCastleRights (brd , from )
138- }
139103 removePiece (brd , capturedPiece , to , brd .Enemy ())
140104 brd .halfmoveClock = 0 // All capture moves are irreversible.
141105 }
@@ -144,9 +108,6 @@ func makeMove(brd *Board, move Move) {
144108 default :
145109 switch capturedPiece {
146110 case ROOK :
147- if brd .castle > 0 {
148- updateCastleRights (brd , to ) //
149- }
150111 removePiece (brd , capturedPiece , to , brd .Enemy ())
151112 brd .halfmoveClock = 0 // All capture moves are irreversible.
152113 case EMPTY :
@@ -168,7 +129,6 @@ func makeMove(brd *Board, move Move) {
168129
169130// Castle flag, enp target, hash key, pawn hash key, and halfmove clock are all restored during search
170131func unmakeMove (brd * Board , move Move , memento * BoardMemento ) {
171-
172132 brd .c ^= 1 // flip the current side to move.
173133
174134 c := brd .c
@@ -243,44 +203,40 @@ func unmakeMove(brd *Board, move Move, memento *BoardMemento) {
243203 brd .halfmoveClock = memento .halfmoveClock
244204}
245205
246- // Whenever a king or rook moves off its initial square or is captured,
247- // update castle rights via the procedure associated with that square.
248- func updateCastleRights (brd * Board , sq int ) {
206+ // Update castling rights whenever a piece moves from or to a square associated with the
207+ // current castling rights.
208+ func updateCastleRights (brd * Board , from , to int ) {
209+ if castle := brd .castle ; castle > 0 && (sqMaskOn [from ]| sqMaskOn [to ])& castleMasks [castle ] > 0 {
210+ updateCasleRightsForSq (brd , from )
211+ updateCasleRightsForSq (brd , to )
212+ brd .hashKey ^= castleZobrist (castle )
213+ brd .hashKey ^= castleZobrist (brd .castle )
214+ }
215+ }
216+
217+ func updateCasleRightsForSq (brd * Board , sq int ) {
249218 switch sq { // if brd.castle remains unchanged, hash key will be unchanged.
250219 case A1 :
251- brd .hashKey ^= castleZobrist (brd .castle )
252220 brd .castle &= (^ uint8 (C_WQ ))
253- brd .hashKey ^= castleZobrist (brd .castle )
254221 case E1 : // white king starting position
255- brd .hashKey ^= castleZobrist (brd .castle )
256222 brd .castle &= (^ uint8 (C_WK | C_WQ ))
257- brd .hashKey ^= castleZobrist (brd .castle )
258223 case H1 :
259- brd .hashKey ^= castleZobrist (brd .castle )
260224 brd .castle &= (^ uint8 (C_WK ))
261- brd .hashKey ^= castleZobrist (brd .castle )
262225 case A8 :
263- brd .hashKey ^= castleZobrist (brd .castle )
264226 brd .castle &= (^ uint8 (C_BQ ))
265- brd .hashKey ^= castleZobrist (brd .castle )
266227 case E8 : // black king starting position
267- brd .hashKey ^= castleZobrist (brd .castle )
268228 brd .castle &= (^ uint8 (C_BK | C_BQ ))
269- brd .hashKey ^= castleZobrist (brd .castle )
270229 case H8 :
271- brd .hashKey ^= castleZobrist (brd .castle )
272230 brd .castle &= (^ uint8 (C_BK ))
273- brd . hashKey ^= castleZobrist ( brd . castle )
231+ default :
274232 }
275233}
276234
277235func removePiece (brd * Board , removedPiece Piece , sq int , e uint8 ) {
278- brd.pieces [e ][removedPiece ].Clear (sq )
279- brd .occupied [e ].Clear (sq )
280- brd .material [e ] -= int32 (removedPiece .Value () + mainPst [e ][removedPiece ][sq ])
281- brd .endgameCounter -= endgameCountValues [removedPiece ]
236+ unmakeRemovePiece (brd , removedPiece , sq , e )
282237 brd .hashKey ^= zobrist (removedPiece , sq , e ) // XOR out the captured piece
283238}
239+
284240func unmakeRemovePiece (brd * Board , removedPiece Piece , sq int , e uint8 ) {
285241 brd.pieces [e ][removedPiece ].Clear (sq )
286242 brd .occupied [e ].Clear (sq )
@@ -289,13 +245,10 @@ func unmakeRemovePiece(brd *Board, removedPiece Piece, sq int, e uint8) {
289245}
290246
291247func addPiece (brd * Board , addedPiece Piece , sq int , c uint8 ) {
292- brd.pieces [c ][addedPiece ].Add (sq )
293- brd .squares [sq ] = addedPiece
294- brd .occupied [c ].Add (sq )
295- brd .material [c ] += int32 (addedPiece .Value () + mainPst [c ][addedPiece ][sq ])
296- brd .endgameCounter += endgameCountValues [addedPiece ]
248+ unmakeAddPiece (brd , addedPiece , sq , c )
297249 brd .hashKey ^= zobrist (addedPiece , sq , c ) // XOR in key for added_piece
298250}
251+
299252func unmakeAddPiece (brd * Board , addedPiece Piece , sq int , c uint8 ) {
300253 brd.pieces [c ][addedPiece ].Add (sq )
301254 brd .squares [sq ] = addedPiece
@@ -305,15 +258,11 @@ func unmakeAddPiece(brd *Board, addedPiece Piece, sq int, c uint8) {
305258}
306259
307260func relocatePiece (brd * Board , piece Piece , from , to int , c uint8 ) {
308- fromTo := (sqMaskOn [from ] | sqMaskOn [to ])
309- brd.pieces [c ][piece ] ^= fromTo
310- brd .occupied [c ] ^= fromTo
311- brd .squares [from ] = EMPTY
312- brd .squares [to ] = piece
313- brd .material [c ] += int32 (mainPst [c ][piece ][to ] - mainPst [c ][piece ][from ])
261+ unmakeRelocatePiece (brd , piece , from , to , c )
314262 // XOR out the key for piece at from, and XOR in the key for piece at to.
315263 brd .hashKey ^= (zobrist (piece , from , c ) ^ zobrist (piece , to , c ))
316264}
265+
317266func unmakeRelocatePiece (brd * Board , piece Piece , from , to int , c uint8 ) {
318267 fromTo := (sqMaskOn [from ] | sqMaskOn [to ])
319268 brd.pieces [c ][piece ] ^= fromTo
@@ -324,14 +273,11 @@ func unmakeRelocatePiece(brd *Board, piece Piece, from, to int, c uint8) {
324273}
325274
326275func relocateKing (brd * Board , piece , capturedPiece Piece , from , to int , c uint8 ) {
327- fromTo := (sqMaskOn [from ] | sqMaskOn [to ])
328- brd.pieces [c ][piece ] ^= fromTo
329- brd .occupied [c ] ^= fromTo
330- brd .squares [from ] = EMPTY
331- brd .squares [to ] = piece
276+ unmakeRelocateKing (brd , piece , capturedPiece , from , to , c )
332277 // XOR out the key for piece at from, and XOR in the key for piece at to.
333278 brd .hashKey ^= (zobrist (piece , from , c ) ^ zobrist (piece , to , c ))
334279}
280+
335281func unmakeRelocateKing (brd * Board , piece , capturedPiece Piece , from , to int , c uint8 ) {
336282 fromTo := (sqMaskOn [from ] | sqMaskOn [to ])
337283 brd.pieces [c ][piece ] ^= fromTo
0 commit comments