From fd808ef5e046af12177d210338ff081e3ca899b1 Mon Sep 17 00:00:00 2001 From: Quinten Kock Date: Thu, 18 Jun 2020 21:19:20 +0200 Subject: [PATCH] Implement unmaking and castle rights --- Board.h | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/Board.h b/Board.h index a685923..ed0f4bc 100644 --- a/Board.h +++ b/Board.h @@ -52,7 +52,7 @@ void board_init() { struct Unmove { - byte sq_from; // 0b(1unused)(3rank)(1unused)(3file) + byte sq_from; // 0b(1kingside_castle?)(3rank)(1queenside_castle?)(3file) byte sq_to; // 0b(1promoted?)(3rank)(1ep_capture?)(3file) byte captured; // 0b(4enpassantinfo)(1color)(3piecetype) byte revmov; // 8bit integer @@ -136,9 +136,9 @@ void make(Move m) { byte piece_type = field[m.sq_from] & 0x7; if(u.captured || piece_type == W_PAWN) { - field[PTR_REVMOV]++; - } else { field[PTR_REVMOV] = 0; + } else { + field[PTR_REVMOV]++; } // Calculate the move 'amount' (unique signature for dx,dy) @@ -162,23 +162,28 @@ void make(Move m) { } // Handle castling rights + // First store the current rights in the unmove + byte our_rights = field[PTR_SIDE_AND_CASTLERIGHT] >> (1 + 2*black_moving()); + if(our_rights & 0b10) // kingside allowed + u.sq_from |= 0x80; + if(our_rights & 0b01) // queenside allowed + u.sq_from |= 0x08; // We are doing the simple way: // unset it any time a move is made from the original position. // TODO handle castle rights and unmake if(m.sq_from == 0x00) // white queenside rook field[PTR_SIDE_AND_CASTLERIGHT] &= ~0b00010; - if(m.sq_from == 0x07) // white kingside rook + else if(m.sq_from == 0x07) // white kingside rook field[PTR_SIDE_AND_CASTLERIGHT] &= ~0b00100; - if(m.sq_from == 0x04) // white king + else if(m.sq_from == 0x04) // white king field[PTR_SIDE_AND_CASTLERIGHT] &= ~0b00110; - if(m.sq_from == 0x70) // black queenside rook + else if(m.sq_from == 0x70) // black queenside rook field[PTR_SIDE_AND_CASTLERIGHT] &= ~0b01000; - if(m.sq_from == 0x77) // black kingside rook + else if(m.sq_from == 0x77) // black kingside rook field[PTR_SIDE_AND_CASTLERIGHT] &= ~0b10000; - if(m.sq_from == 0x74) // black king + else if(m.sq_from == 0x74) // black king field[PTR_SIDE_AND_CASTLERIGHT] &= ~0b11000; - // TODO: test enpassant code more than basics // handle enpassant capture @@ -233,35 +238,44 @@ void unmake() { Unmove u = read_unmove(); field[PTR_REVMOV] = u.revmov; + byte sq_from = u.sq_from & 0x77; byte sq_to = u.sq_to & 0x77; byte prom_ep_capt = u.sq_to & 0x88; if(prom_ep_capt == 0) { // regular move - field[u.sq_from] = field[sq_to]; + field[sq_from] = field[sq_to]; } else if (prom_ep_capt == 0x80) { // piece was promoted // so the source is a pawn - field[u.sq_from] = W_PAWN | (field[u.sq_to] & 0b1000); + field[sq_from] = W_PAWN | (field[sq_to] & 0b1000); } else if (prom_ep_capt == 0x08) { // we did an enpassant capture - byte ep_sq = (u.sq_to & 0x07) | (u.sq_from & 0x70); + byte ep_sq = (sq_to & 0x07) | (sq_from & 0x70); field[ep_sq] = W_PAWN | black_moving() << 3; // also undo the regular move - field[u.sq_from] = field[sq_to]; + field[sq_from] = field[sq_to]; + } + + byte castleright_offset = 3 - 2*black_moving(); + if(u.sq_from & 0x80) { + // restore king side castling rights + field[PTR_SIDE_AND_CASTLERIGHT] |= 0b10 << castleright_offset; + } + if(u.sq_from & 0x08) { + field[PTR_SIDE_AND_CASTLERIGHT] |= 0b01 << castleright_offset; } - // TODO handle castling rights int sq_diff = (int)sq_to - (int)u.sq_from; int sq_diff_abs = abs(sq_diff); - if((field[u.sq_from] & 0x7) == W_KING && sq_diff_abs == 2) { + if((field[sq_from] & 0x7) == W_KING && sq_diff_abs == 2) { // we castled byte castle_source = 0x70*!black_moving(); if(sq_diff == 2) { castle_source += 0x7; } - byte castle_target = u.sq_from + (sq_diff/2); + byte castle_target = sq_from + (sq_diff/2); // move rook back to original position field[castle_source] = field[castle_target]; // and clear where it was put