From c4f5412cd4a86f3a8eb44cff6c9b659722e49121 Mon Sep 17 00:00:00 2001 From: dece Date: Tue, 9 Jun 2020 23:09:27 +0200 Subject: [PATCH] rules: disable castling when king/rook moves --- src/rules.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/uci.rs | 21 ++++++++++++++------- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/rules.rs b/src/rules.rs index 333618e..64a03e8 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -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) { apply_move_to_board(board, 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) { match castle { 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`. @@ -142,6 +180,7 @@ pub fn get_castle_move(castle: u8) -> Move { } } + /// 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 diff --git a/src/uci.rs b/src/uci.rs index fb51ea1..fa47622 100644 --- a/src/uci.rs +++ b/src/uci.rs @@ -175,22 +175,19 @@ impl Uci { self.setup_engine(); }, UciCmd::Debug(on) => { - let args = engine::Cmd::UciDebug(*on); - self.engine_in.as_ref().unwrap().send(args).unwrap(); + self.send_engine_command(engine::Cmd::UciDebug(*on)); } UciCmd::IsReady => if self.state == State::Ready { self.send_ready() }, UciCmd::UciNewGame => if self.state == State::Ready { /* Nothing to do. */ }, UciCmd::Position(args) => if self.state == State::Ready { - let args = engine::Cmd::UciPosition(args.to_vec()); - self.engine_in.as_ref().unwrap().send(args).unwrap(); + self.send_engine_command(engine::Cmd::UciPosition(args.to_vec())); }, UciCmd::Go(args) => if self.state == State::Ready { - let args = engine::Cmd::UciGo(args.to_vec()); - self.engine_in.as_ref().unwrap().send(args).unwrap(); + self.send_engine_command(engine::Cmd::UciGo(args.to_vec())); 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::Unknown(c) => { self.log(format!("Unknown command: {}", c)); } @@ -226,6 +223,7 @@ impl Uci { self.send("uciok"); } + /// Setup engine for UCI. fn setup_engine(&mut self) { let uci_s = self.cmd_channel.0.clone(); thread::spawn(move || { @@ -235,6 +233,15 @@ impl Uci { 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. fn send_ready(&mut self) { self.send("readyok");