rules: disable castling when king/rook moves

This commit is contained in:
dece 2020-06-09 23:09:27 +02:00
parent a8a680b944
commit c4f5412cd4
2 changed files with 53 additions and 7 deletions

View file

@ -64,6 +64,7 @@ pub fn apply_move(board: &Board, game_state: &GameState, m: &Move) -> (Board, Ga
pub fn apply_move_to(board: &mut Board, game_state: &mut GameState, m: &Move) { pub fn apply_move_to(board: &mut Board, game_state: &mut GameState, m: &Move) {
apply_move_to_board(board, m); apply_move_to_board(board, m);
apply_move_to_state(game_state, m); apply_move_to_state(game_state, m);
// If the move is a castle, remove it from castling options.
if let Some(castle) = get_castle(m) { if let Some(castle) = get_castle(m) {
match castle { match castle {
CASTLING_WH_K | CASTLING_WH_Q => game_state.castling &= !CASTLING_WH_MASK, CASTLING_WH_K | CASTLING_WH_Q => game_state.castling &= !CASTLING_WH_MASK,
@ -71,6 +72,43 @@ pub fn apply_move_to(board: &mut Board, game_state: &mut GameState, m: &Move) {
_ => {} _ => {}
}; };
} }
// Else, check if it's either to rook or the king that moved.
else {
let piece = get_square(board, &m.1);
if is_white(piece) && game_state.castling & CASTLING_WH_MASK != 0 {
match get_type(piece) {
SQ_K => {
if m.0 == pos("e1") {
game_state.castling &= !CASTLING_WH_MASK;
}
}
SQ_R => {
if m.0 == pos("a1") {
game_state.castling &= !CASTLING_WH_Q;
} else if m.0 == pos("h1") {
game_state.castling &= !CASTLING_WH_K;
}
}
_ => {}
}
} else if is_black(piece) && game_state.castling & CASTLING_BL_MASK != 0 {
match get_type(piece) {
SQ_K => {
if m.0 == pos("e8") {
game_state.castling &= !CASTLING_BL_MASK;
}
}
SQ_R => {
if m.0 == pos("a8") {
game_state.castling &= !CASTLING_BL_Q;
} else if m.0 == pos("h8") {
game_state.castling &= !CASTLING_BL_K;
}
}
_ => {}
}
}
}
} }
/// Apply a move `m` into `board`. /// Apply a move `m` into `board`.
@ -142,6 +180,7 @@ pub fn get_castle_move(castle: u8) -> Move {
} }
} }
/// Get a list of moves for all pieces of the playing color. /// Get a list of moves for all pieces of the playing color.
/// ///
/// If `commit` is false, do not check for illegal moves. This is used /// If `commit` is false, do not check for illegal moves. This is used

View file

@ -175,22 +175,19 @@ impl Uci {
self.setup_engine(); self.setup_engine();
}, },
UciCmd::Debug(on) => { UciCmd::Debug(on) => {
let args = engine::Cmd::UciDebug(*on); self.send_engine_command(engine::Cmd::UciDebug(*on));
self.engine_in.as_ref().unwrap().send(args).unwrap();
} }
UciCmd::IsReady => if self.state == State::Ready { self.send_ready() }, UciCmd::IsReady => if self.state == State::Ready { self.send_ready() },
UciCmd::UciNewGame => if self.state == State::Ready { /* Nothing to do. */ }, UciCmd::UciNewGame => if self.state == State::Ready { /* Nothing to do. */ },
UciCmd::Position(args) => if self.state == State::Ready { UciCmd::Position(args) => if self.state == State::Ready {
let args = engine::Cmd::UciPosition(args.to_vec()); self.send_engine_command(engine::Cmd::UciPosition(args.to_vec()));
self.engine_in.as_ref().unwrap().send(args).unwrap();
}, },
UciCmd::Go(args) => if self.state == State::Ready { UciCmd::Go(args) => if self.state == State::Ready {
let args = engine::Cmd::UciGo(args.to_vec()); self.send_engine_command(engine::Cmd::UciGo(args.to_vec()));
self.engine_in.as_ref().unwrap().send(args).unwrap();
self.state = State::Working; self.state = State::Working;
} }
UciCmd::Stop => if self.state == State::Working { UciCmd::Stop => if self.state == State::Working {
self.engine_in.as_ref().unwrap().send(engine::Cmd::Stop).unwrap(); self.send_engine_command(engine::Cmd::Stop);
}, },
UciCmd::Quit => return false, UciCmd::Quit => return false,
UciCmd::Unknown(c) => { self.log(format!("Unknown command: {}", c)); } UciCmd::Unknown(c) => { self.log(format!("Unknown command: {}", c)); }
@ -226,6 +223,7 @@ impl Uci {
self.send("uciok"); self.send("uciok");
} }
/// Setup engine for UCI.
fn setup_engine(&mut self) { fn setup_engine(&mut self) {
let uci_s = self.cmd_channel.0.clone(); let uci_s = self.cmd_channel.0.clone();
thread::spawn(move || { thread::spawn(move || {
@ -235,6 +233,15 @@ impl Uci {
self.state = State::Ready; self.state = State::Ready;
} }
/// Send a command to the engine if it is has been setup, else log an error.
fn send_engine_command(&mut self, cmd: engine::Cmd) {
if let Some(tx) = self.engine_in.as_ref() {
tx.send(cmd).unwrap();
} else {
self.log("Attempt to send command to offline engine.".to_string());
}
}
/// Notify interface that it is ready. /// Notify interface that it is ready.
fn send_ready(&mut self) { fn send_ready(&mut self) {
self.send("readyok"); self.send("readyok");