|
@@ -223,7 +223,7 @@ impl Game {
|
|
if piece_type == KING && (from as i32 - to as i32).abs() == 2 {
|
|
if piece_type == KING && (from as i32 - to as i32).abs() == 2 {
|
|
let left = from < to;
|
|
let left = from < to;
|
|
//println!("OMG castling!");
|
|
//println!("OMG castling!");
|
|
- return Ok(Move::Castling{ side, left });
|
|
|
|
|
|
+ return Ok(Move::Castling{ mov: SimpleMove { from, to }, side, left });
|
|
}
|
|
}
|
|
|
|
|
|
// pawn capture
|
|
// pawn capture
|
|
@@ -613,147 +613,149 @@ impl Game {
|
|
let side = self.turn;
|
|
let side = self.turn;
|
|
let others = self.get_all_side(!side);
|
|
let others = self.get_all_side(!side);
|
|
|
|
|
|
- match mov {
|
|
|
|
- Move::Default{ mov, pc } => {
|
|
|
|
- let pt = pc.piece_type();
|
|
|
|
|
|
+ if !mov.is_null() {
|
|
|
|
+ match mov {
|
|
|
|
+ Move::Default{ mov, pc } => {
|
|
|
|
+ let pt = pc.piece_type();
|
|
|
|
|
|
- if pt == KING {
|
|
|
|
- // invalidate castling rights
|
|
|
|
- self.castling_rights[if side == BLACK { 2 } else { 0 }] = false;
|
|
|
|
- self.castling_rights[if side == BLACK { 3 } else { 1 }] = false;
|
|
|
|
- }
|
|
|
|
|
|
+ if pt == KING {
|
|
|
|
+ // invalidate castling rights
|
|
|
|
+ self.castling_rights[if side == BLACK { 2 } else { 0 }] = false;
|
|
|
|
+ self.castling_rights[if side == BLACK { 3 } else { 1 }] = false;
|
|
|
|
+ }
|
|
|
|
|
|
- // invalidate castling rights
|
|
|
|
- if mov.from == square_from_indices(7, 0) || mov.to == square_from_indices(7, 0) {
|
|
|
|
- self.castling_rights[0] = false;
|
|
|
|
- }
|
|
|
|
- if mov.from == square_from_indices(0, 0) || mov.to == square_from_indices(0, 0) {
|
|
|
|
- self.castling_rights[1] = false;
|
|
|
|
- }
|
|
|
|
- if mov.from == square_from_indices(7, 7) || mov.to == square_from_indices(7, 7) {
|
|
|
|
- self.castling_rights[2] = false;
|
|
|
|
- }
|
|
|
|
- if mov.from == square_from_indices(0, 7) || mov.to == square_from_indices(0, 7) {
|
|
|
|
- self.castling_rights[3] = false;
|
|
|
|
- }
|
|
|
|
|
|
+ // invalidate castling rights
|
|
|
|
+ if mov.from == square_from_indices(7, 0) || mov.to == square_from_indices(7, 0) {
|
|
|
|
+ self.castling_rights[0] = false;
|
|
|
|
+ }
|
|
|
|
+ if mov.from == square_from_indices(0, 0) || mov.to == square_from_indices(0, 0) {
|
|
|
|
+ self.castling_rights[1] = false;
|
|
|
|
+ }
|
|
|
|
+ if mov.from == square_from_indices(7, 7) || mov.to == square_from_indices(7, 7) {
|
|
|
|
+ self.castling_rights[2] = false;
|
|
|
|
+ }
|
|
|
|
+ if mov.from == square_from_indices(0, 7) || mov.to == square_from_indices(0, 7) {
|
|
|
|
+ self.castling_rights[3] = false;
|
|
|
|
+ }
|
|
|
|
|
|
- // if it is a capture
|
|
|
|
- if from_square(mov.to) & others != 0 {
|
|
|
|
- let (other_piece, other_side) = self.get_square(mov.to);
|
|
|
|
|
|
+ // if it is a capture
|
|
|
|
+ if from_square(mov.to) & others != 0 {
|
|
|
|
+ let (other_piece, other_side) = self.get_square(mov.to);
|
|
|
|
|
|
- // update zobrist
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hup = zt.piece_hash(other_piece, other_side, mov.to);
|
|
|
|
- *zv ^= hup;
|
|
|
|
|
|
+ // update zobrist
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(other_piece, other_side, mov.to);
|
|
|
|
+ *zv ^= hup;
|
|
|
|
+ }
|
|
|
|
+ *self.get_piece_mut(other_piece, other_side) &= !from_square(mov.to);
|
|
}
|
|
}
|
|
- *self.get_piece_mut(other_piece, other_side) &= !from_square(mov.to);
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
|
|
- // reset en passant and then check if possible
|
|
|
|
- self.en_passant = None;
|
|
|
|
- if pt == PAWN {
|
|
|
|
- let row1 = indices_from_square(mov.from).1;
|
|
|
|
- let row2 = indices_from_square(mov.to).1;
|
|
|
|
- // check for double push
|
|
|
|
- if i32::abs(row1 as i32 - row2 as i32) >= 2 {
|
|
|
|
- let opponent_pawns = self.get_piece(PAWN, !side);
|
|
|
|
- let target_bb = from_square(mov.to);
|
|
|
|
- if (west_one(target_bb) | east_one(target_bb)) & opponent_pawns != 0 {
|
|
|
|
- self.en_passant = Some(indices_from_square(mov.to).0);
|
|
|
|
|
|
+ // reset en passant and then check if possible
|
|
|
|
+ self.en_passant = None;
|
|
|
|
+ if pt == PAWN {
|
|
|
|
+ let row1 = indices_from_square(mov.from).1;
|
|
|
|
+ let row2 = indices_from_square(mov.to).1;
|
|
|
|
+ // check for double push
|
|
|
|
+ if i32::abs(row1 as i32 - row2 as i32) >= 2 {
|
|
|
|
+ let opponent_pawns = self.get_piece(PAWN, !side);
|
|
|
|
+ let target_bb = from_square(mov.to);
|
|
|
|
+ if (west_one(target_bb) | east_one(target_bb)) & opponent_pawns != 0 {
|
|
|
|
+ self.en_passant = Some(indices_from_square(mov.to).0);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- let moved_piece = mov.apply_to(self.get_piece(pt, side));
|
|
|
|
- self.set_piece(pt, side, moved_piece);
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hup = zt.piece_hash(pt, side, mov.from) ^ zt.piece_hash(pt, side, mov.to);
|
|
|
|
- *zv ^= hup;
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- Move::Castling { side, left } => {
|
|
|
|
- // invalidate future castling rights
|
|
|
|
- self.castling_rights[if side == BLACK { 2 } else { 0 }] = false;
|
|
|
|
- self.castling_rights[if side == BLACK { 3 } else { 1 }] = false;
|
|
|
|
-
|
|
|
|
- let king = self.get_piece(KING, side);
|
|
|
|
- let rook = if left {
|
|
|
|
- self.get_piece(ROOK, side) & (king << 4)
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- self.get_piece(ROOK, side) & (king >> 3)
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- let new_king = if left { king << 2 } else { king >> 2 };
|
|
|
|
- let new_rook = if left { rook >> 3 } else { rook << 2 };
|
|
|
|
-
|
|
|
|
- self.set_piece(KING, side, new_king);
|
|
|
|
- *self.get_piece_mut(ROOK, side) &= !rook;
|
|
|
|
- *self.get_piece_mut(ROOK, side) |= new_rook;
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hupk = zt.piece_hash(KING, side, square(king)) ^ zt.piece_hash(KING, side, square(new_king));
|
|
|
|
- let hup = zt.piece_hash(ROOK, side, square(rook)) ^ zt.piece_hash(ROOK, side, square(new_rook));
|
|
|
|
- *zv ^= hup ^ hupk;
|
|
|
|
- }
|
|
|
|
|
|
+ let moved_piece = mov.apply_to(self.get_piece(pt, side));
|
|
|
|
+ self.set_piece(pt, side, moved_piece);
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(pt, side, mov.from) ^ zt.piece_hash(pt, side, mov.to);
|
|
|
|
+ *zv ^= hup;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ Move::Castling { mov:_, side, left } => {
|
|
|
|
+ // invalidate future castling rights
|
|
|
|
+ self.castling_rights[if side == BLACK { 2 } else { 0 }] = false;
|
|
|
|
+ self.castling_rights[if side == BLACK { 3 } else { 1 }] = false;
|
|
|
|
|
|
- self.en_passant = None;
|
|
|
|
- },
|
|
|
|
- Move::EnPassant { mov, beaten } => {
|
|
|
|
- if let Some(_ep) = self.en_passant {
|
|
|
|
- *self.get_piece_mut(PAWN, side) &= !from_square(mov.from);
|
|
|
|
- *self.get_piece_mut(PAWN, side) |= from_square(mov.to);
|
|
|
|
- *self.get_piece_mut(PAWN, !side) &= !from_square(beaten);
|
|
|
|
|
|
+ let king = self.get_piece(KING, side);
|
|
|
|
+ let rook = if left {
|
|
|
|
+ self.get_piece(ROOK, side) & (king << 4)
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ self.get_piece(ROOK, side) & (king >> 3)
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ let new_king = if left { king << 2 } else { king >> 2 };
|
|
|
|
+ let new_rook = if left { rook >> 3 } else { rook << 2 };
|
|
|
|
|
|
|
|
+ self.set_piece(KING, side, new_king);
|
|
|
|
+ *self.get_piece_mut(ROOK, side) &= !rook;
|
|
|
|
+ *self.get_piece_mut(ROOK, side) |= new_rook;
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
- let hup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(PAWN, side, mov.to);
|
|
|
|
- let hupo = zt.piece_hash(PAWN, !side, beaten);
|
|
|
|
- *zv ^= hup ^ hupo;
|
|
|
|
|
|
+ let hupk = zt.piece_hash(KING, side, square(king)) ^ zt.piece_hash(KING, side, square(new_king));
|
|
|
|
+ let hup = zt.piece_hash(ROOK, side, square(rook)) ^ zt.piece_hash(ROOK, side, square(new_rook));
|
|
|
|
+ *zv ^= hup ^ hupk;
|
|
}
|
|
}
|
|
|
|
|
|
self.en_passant = None;
|
|
self.en_passant = None;
|
|
- }
|
|
|
|
- else {
|
|
|
|
- info!("internal en passant error");
|
|
|
|
- panic!("internal en passant error");
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- Move::Promotion { mov, pc } => {
|
|
|
|
- let promote_to = pc.piece_type();
|
|
|
|
- let captured = pc.capture_type();
|
|
|
|
- //if from_square(mov.to) & others != 0 {
|
|
|
|
- if let Some(pt) = captured {
|
|
|
|
- *self.get_piece_mut(pt, !side) &= !from_square(mov.to);
|
|
|
|
|
|
+ },
|
|
|
|
+ Move::EnPassant { mov, beaten } => {
|
|
|
|
+ if let Some(_ep) = self.en_passant {
|
|
|
|
+ *self.get_piece_mut(PAWN, side) &= !from_square(mov.from);
|
|
|
|
+ *self.get_piece_mut(PAWN, side) |= from_square(mov.to);
|
|
|
|
+ *self.get_piece_mut(PAWN, !side) &= !from_square(beaten);
|
|
|
|
+
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(PAWN, side, mov.to);
|
|
|
|
+ let hupo = zt.piece_hash(PAWN, !side, beaten);
|
|
|
|
+ *zv ^= hup ^ hupo;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ self.en_passant = None;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ info!("internal en passant error");
|
|
|
|
+ panic!("internal en passant error");
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ Move::Promotion { mov, pc } => {
|
|
|
|
+ let promote_to = pc.piece_type();
|
|
|
|
+ let captured = pc.capture_type();
|
|
|
|
+ //if from_square(mov.to) & others != 0 {
|
|
|
|
+ if let Some(pt) = captured {
|
|
|
|
+ *self.get_piece_mut(pt, !side) &= !from_square(mov.to);
|
|
|
|
+
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(pt, !side, mov.to);
|
|
|
|
+ *zv ^= hup;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ *self.get_piece_mut(PAWN, side) &= !from_square(mov.from);
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
- let hup = zt.piece_hash(pt, !side, mov.to);
|
|
|
|
|
|
+ let hup = zt.piece_hash(PAWN, side, mov.from);
|
|
*zv ^= hup;
|
|
*zv ^= hup;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- *self.get_piece_mut(PAWN, side) &= !from_square(mov.from);
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hup = zt.piece_hash(PAWN, side, mov.from);
|
|
|
|
- *zv ^= hup;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- match promote_to {
|
|
|
|
- QUEEN => { *self.queens_mut(side) |= from_square(mov.to); }
|
|
|
|
- ROOK => { *self.rooks_mut(side) |= from_square(mov.to); }
|
|
|
|
- BISHOP => { *self.bishops_mut(side) |= from_square(mov.to); }
|
|
|
|
- KNIGHT => { *self.knights_mut(side) |= from_square(mov.to); }
|
|
|
|
- _ => {
|
|
|
|
- info!("internal error");
|
|
|
|
|
|
+ match promote_to {
|
|
|
|
+ QUEEN => { *self.queens_mut(side) |= from_square(mov.to); }
|
|
|
|
+ ROOK => { *self.rooks_mut(side) |= from_square(mov.to); }
|
|
|
|
+ BISHOP => { *self.bishops_mut(side) |= from_square(mov.to); }
|
|
|
|
+ KNIGHT => { *self.knights_mut(side) |= from_square(mov.to); }
|
|
|
|
+ _ => {
|
|
|
|
+ info!("internal error");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hup = zt.piece_hash(promote_to, side, mov.to);
|
|
|
|
- *zv ^= hup;
|
|
|
|
- }
|
|
|
|
- self.en_passant = None;
|
|
|
|
- },
|
|
|
|
- Move::Nullmove => {}
|
|
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(promote_to, side, mov.to);
|
|
|
|
+ *zv ^= hup;
|
|
|
|
+ }
|
|
|
|
+ self.en_passant = None;
|
|
|
|
+ },
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
if self.turn == BLACK {
|
|
if self.turn == BLACK {
|
|
self.turn_number += 1;
|
|
self.turn_number += 1;
|
|
}
|
|
}
|
|
@@ -787,6 +789,7 @@ impl Game {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
pub fn undo_move(&mut self, umov: MoveUndo) {
|
|
pub fn undo_move(&mut self, umov: MoveUndo) {
|
|
|
|
|
|
/*if !self.is_zobrist_correct() {
|
|
/*if !self.is_zobrist_correct() {
|
|
@@ -810,96 +813,98 @@ impl Game {
|
|
|
|
|
|
// the side that played the turn that is to be reverted
|
|
// the side that played the turn that is to be reverted
|
|
let side = !self.turn;
|
|
let side = !self.turn;
|
|
- match mov {
|
|
|
|
- Move::Default{ mov, pc } => {
|
|
|
|
- let piece_type = pc.piece_type();
|
|
|
|
- let captured = pc.capture_type();
|
|
|
|
|
|
|
|
- let moved_piece_bb = self.get_piece_mut(piece_type, side);
|
|
|
|
- *moved_piece_bb &= !from_square(mov.to);
|
|
|
|
- *moved_piece_bb |= from_square(mov.from);
|
|
|
|
|
|
+ if !mov.is_null() {
|
|
|
|
+ match mov {
|
|
|
|
+ Move::Default{ mov, pc } => {
|
|
|
|
+ let piece_type = pc.piece_type();
|
|
|
|
+ let captured = pc.capture_type();
|
|
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hup = zt.piece_hash(piece_type, side, mov.from) ^ zt.piece_hash(piece_type, side, mov.to);
|
|
|
|
- *zv ^= hup;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if let Some(pt) = captured {
|
|
|
|
- *self.get_piece_mut(pt, !side) |= from_square(mov.to);
|
|
|
|
|
|
+ let moved_piece_bb = self.get_piece_mut(piece_type, side);
|
|
|
|
+ *moved_piece_bb &= !from_square(mov.to);
|
|
|
|
+ *moved_piece_bb |= from_square(mov.from);
|
|
|
|
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
- let hup = zt.piece_hash(pt, !side, mov.to);
|
|
|
|
|
|
+ let hup = zt.piece_hash(piece_type, side, mov.from) ^ zt.piece_hash(piece_type, side, mov.to);
|
|
*zv ^= hup;
|
|
*zv ^= hup;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- },
|
|
|
|
- Move::Castling { side, left } => {
|
|
|
|
- let king = self.get_piece(KING, side);
|
|
|
|
|
|
|
|
- let rook = if left {
|
|
|
|
- self.get_piece(ROOK, side) & (king >> 1)
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- self.get_piece(ROOK, side) & (king << 1)
|
|
|
|
- };
|
|
|
|
|
|
+ if let Some(pt) = captured {
|
|
|
|
+ *self.get_piece_mut(pt, !side) |= from_square(mov.to);
|
|
|
|
|
|
- let old_king = if left { king >> 2 } else { king << 2 };
|
|
|
|
- let old_rook = if left { rook << 3 } else { rook >> 2 };
|
|
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(pt, !side, mov.to);
|
|
|
|
+ *zv ^= hup;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ Move::Castling { mov: _, side, left } => {
|
|
|
|
+ let king = self.get_piece(KING, side);
|
|
|
|
|
|
- self.set_piece(KING, side, old_king);
|
|
|
|
- *self.get_piece_mut(ROOK, side) &= !rook;
|
|
|
|
- *self.get_piece_mut(ROOK, side) |= old_rook;
|
|
|
|
|
|
+ let rook = if left {
|
|
|
|
+ self.get_piece(ROOK, side) & (king >> 1)
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ self.get_piece(ROOK, side) & (king << 1)
|
|
|
|
+ };
|
|
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let khup = zt.piece_hash(KING, side, square(old_king)) ^ zt.piece_hash(KING, side, square(king));
|
|
|
|
- let rhup = zt.piece_hash(ROOK, side, square(rook)) ^ zt.piece_hash(ROOK, side, square(old_rook));
|
|
|
|
- *zv ^= khup ^ rhup;
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- Move::EnPassant { mov, beaten } => {
|
|
|
|
- *self.get_piece_mut(PAWN, side) |= from_square(mov.from);
|
|
|
|
- *self.get_piece_mut(PAWN, side) &= !from_square(mov.to);
|
|
|
|
- *self.get_piece_mut(PAWN, !side) |= from_square(beaten);
|
|
|
|
-
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let phup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(PAWN, side, mov.to);
|
|
|
|
- let chup = zt.piece_hash(PAWN, !side, beaten);
|
|
|
|
- *zv ^= phup ^ chup;
|
|
|
|
- }
|
|
|
|
|
|
+ let old_king = if left { king >> 2 } else { king << 2 };
|
|
|
|
+ let old_rook = if left { rook << 3 } else { rook >> 2 };
|
|
|
|
+
|
|
|
|
+ self.set_piece(KING, side, old_king);
|
|
|
|
+ *self.get_piece_mut(ROOK, side) &= !rook;
|
|
|
|
+ *self.get_piece_mut(ROOK, side) |= old_rook;
|
|
|
|
|
|
- // should already be reverted
|
|
|
|
- //self.en_passant = Some(indices_from_square(beaten).0);
|
|
|
|
- },
|
|
|
|
- Move::Promotion { mov, pc } => {
|
|
|
|
- let promote_to = pc.piece_type();
|
|
|
|
- let captured = pc.capture_type();
|
|
|
|
-
|
|
|
|
- match promote_to {
|
|
|
|
- QUEEN => { *self.queens_mut(side) &= !from_square(mov.to); }
|
|
|
|
- ROOK => { *self.rooks_mut(side) &= !from_square(mov.to); }
|
|
|
|
- BISHOP => { *self.bishops_mut(side) &= !from_square(mov.to); }
|
|
|
|
- KNIGHT => { *self.knights_mut(side) &= !from_square(mov.to); }
|
|
|
|
- _ => {
|
|
|
|
- info!("internal error");
|
|
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let khup = zt.piece_hash(KING, side, square(old_king)) ^ zt.piece_hash(KING, side, square(king));
|
|
|
|
+ let rhup = zt.piece_hash(ROOK, side, square(rook)) ^ zt.piece_hash(ROOK, side, square(old_rook));
|
|
|
|
+ *zv ^= khup ^ rhup;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- *self.pawns_mut(side) |= from_square(mov.from);
|
|
|
|
|
|
+ },
|
|
|
|
+ Move::EnPassant { mov, beaten } => {
|
|
|
|
+ *self.get_piece_mut(PAWN, side) |= from_square(mov.from);
|
|
|
|
+ *self.get_piece_mut(PAWN, side) &= !from_square(mov.to);
|
|
|
|
+ *self.get_piece_mut(PAWN, !side) |= from_square(beaten);
|
|
|
|
|
|
- if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
- let hup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(promote_to, side, mov.to);
|
|
|
|
- *zv ^= hup;
|
|
|
|
- }
|
|
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let phup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(PAWN, side, mov.to);
|
|
|
|
+ let chup = zt.piece_hash(PAWN, !side, beaten);
|
|
|
|
+ *zv ^= phup ^ chup;
|
|
|
|
+ }
|
|
|
|
|
|
- if let Some(pt) = captured {
|
|
|
|
- *self.get_piece_mut(pt, !side) |= from_square(mov.to);
|
|
|
|
|
|
+ // should already be reverted
|
|
|
|
+ //self.en_passant = Some(indices_from_square(beaten).0);
|
|
|
|
+ },
|
|
|
|
+ Move::Promotion { mov, pc } => {
|
|
|
|
+ let promote_to = pc.piece_type();
|
|
|
|
+ let captured = pc.capture_type();
|
|
|
|
+
|
|
|
|
+ match promote_to {
|
|
|
|
+ QUEEN => { *self.queens_mut(side) &= !from_square(mov.to); }
|
|
|
|
+ ROOK => { *self.rooks_mut(side) &= !from_square(mov.to); }
|
|
|
|
+ BISHOP => { *self.bishops_mut(side) &= !from_square(mov.to); }
|
|
|
|
+ KNIGHT => { *self.knights_mut(side) &= !from_square(mov.to); }
|
|
|
|
+ _ => {
|
|
|
|
+ info!("internal error");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ *self.pawns_mut(side) |= from_square(mov.from);
|
|
|
|
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
- let hup = zt.piece_hash(pt, !side, mov.to);
|
|
|
|
|
|
+ let hup = zt.piece_hash(PAWN, side, mov.from) ^ zt.piece_hash(promote_to, side, mov.to);
|
|
*zv ^= hup;
|
|
*zv ^= hup;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- },
|
|
|
|
- Move::Nullmove => {}
|
|
|
|
|
|
+
|
|
|
|
+ if let Some(pt) = captured {
|
|
|
|
+ *self.get_piece_mut(pt, !side) |= from_square(mov.to);
|
|
|
|
+
|
|
|
|
+ if let Some((ref zt, ref mut zv)) = self.zobrist {
|
|
|
|
+ let hup = zt.piece_hash(pt, !side, mov.to);
|
|
|
|
+ *zv ^= hup;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
self.turn = side;
|
|
self.turn = side;
|