rules: castling WIP
This commit is contained in:
parent
769f7e0d94
commit
09e3700e3a
6
d6h2.txt
Normal file
6
d6h2.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
uci
|
||||
position startpos moves d2d4 b7b6 e2e4 d7d6 c1f4 f7f6 f1c4 g7g6 d4d5 b6b5 c4b5
|
||||
b8d7 g1f3 f6f5 e4f5 g6f5 d1d4 a7a6 d4d1 a6b5 f4d6 c7d6 d1d4 a8a2 a1a2 b5b4 d4b4
|
||||
f5f4 b4f4 d7f6 f4g5 f6d5 g5d5 e7e5 b1c3 e5e4 c3e4 h7h6 g2g4 h6h5 g4h5 h8h5 e4f6
|
||||
d8f6 a2a5 h5d5 a5d5 f6f3 e1g1 f3h1 g1h1 c8d7 f1e1 d7e6 d5d6 f8d6 e1e6
|
||||
go
|
|
@ -4,8 +4,6 @@ use std::sync::{Arc, atomic, mpsc};
|
|||
use std::thread;
|
||||
use std::time;
|
||||
|
||||
use rand::seq::IteratorRandom;
|
||||
|
||||
use crate::board;
|
||||
use crate::notation;
|
||||
use crate::rules;
|
||||
|
@ -103,12 +101,6 @@ pub enum Info {
|
|||
CurrentMove(board::Move),
|
||||
}
|
||||
|
||||
pub const CASTLING_WH_K: u8 = 0b00000001;
|
||||
pub const CASTLING_WH_Q: u8 = 0b00000010;
|
||||
pub const CASTLING_BL_K: u8 = 0b00000100;
|
||||
pub const CASTLING_BL_Q: u8 = 0b00001000;
|
||||
pub const CASTLING_MASK: u8 = 0b00001111;
|
||||
|
||||
/// General engine implementation.
|
||||
impl Engine {
|
||||
pub fn new() -> Engine {
|
||||
|
@ -118,7 +110,7 @@ impl Engine {
|
|||
board: board::new_empty(),
|
||||
stats: (board::BoardStats::new(), board::BoardStats::new()),
|
||||
color: board::SQ_WH,
|
||||
castling: CASTLING_MASK,
|
||||
castling: rules::CASTLING_MASK,
|
||||
en_passant: None,
|
||||
halfmove: 0,
|
||||
fullmove: 1,
|
||||
|
@ -199,10 +191,10 @@ impl Engine {
|
|||
fn set_fen_castling(&mut self, castling: &str) {
|
||||
for c in castling.chars() {
|
||||
match c {
|
||||
'K' => self.state.castling |= CASTLING_WH_K,
|
||||
'Q' => self.state.castling |= CASTLING_WH_Q,
|
||||
'k' => self.state.castling |= CASTLING_BL_K,
|
||||
'q' => self.state.castling |= CASTLING_BL_Q,
|
||||
'K' => self.state.castling |= rules::CASTLING_WH_K,
|
||||
'Q' => self.state.castling |= rules::CASTLING_WH_Q,
|
||||
'k' => self.state.castling |= rules::CASTLING_BL_K,
|
||||
'q' => self.state.castling |= rules::CASTLING_BL_Q,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -325,7 +317,6 @@ fn analyze(
|
|||
return;
|
||||
}
|
||||
|
||||
// Stupid engine! Return a random move.
|
||||
let moves = rules::get_player_legal_moves(&state.board, state.color);
|
||||
if debug {
|
||||
let state_str = format!("Current state: {:?}", state);
|
||||
|
@ -337,8 +328,6 @@ fn analyze(
|
|||
let moves_str = format!("Legal moves: {}", notation::move_list_to_string(&moves));
|
||||
tx.send(Cmd::Log(moves_str)).unwrap();
|
||||
}
|
||||
// let mut rng = rand::thread_rng();
|
||||
// let best_move = moves.iter().choose(&mut rng).and_then(|m| Some(*m));
|
||||
|
||||
let mut best_e = if board::is_white(state.color) { -999.0 } else { 999.0 };
|
||||
let mut best_move = None;
|
||||
|
|
33
src/rules.rs
33
src/rules.rs
|
@ -2,13 +2,22 @@
|
|||
|
||||
use crate::board::*;
|
||||
|
||||
pub const CASTLING_WH_K: u8 = 0b00000001;
|
||||
pub const CASTLING_WH_Q: u8 = 0b00000010;
|
||||
pub const CASTLING_BL_K: u8 = 0b00000100;
|
||||
pub const CASTLING_BL_Q: u8 = 0b00001000;
|
||||
pub const CASTLING_MASK: u8 = 0b00001111;
|
||||
|
||||
pub const START_WH_K_POS: Pos = pos("e1");
|
||||
pub const START_BL_K_POS: Pos = pos("e8");
|
||||
|
||||
/// Get a list of legal moves for all pieces of this color.
|
||||
pub fn get_player_legal_moves(board: &Board, color: u8) -> Vec<Move> {
|
||||
filter_illegal_moves(board, color, get_player_moves(board, color))
|
||||
pub fn get_player_legal_moves(board: &Board, color: u8, castling: u8) -> Vec<Move> {
|
||||
filter_illegal_moves(board, color, get_player_moves(board, color, castling))
|
||||
}
|
||||
|
||||
/// Get a list of moves for all pieces of this color.
|
||||
pub fn get_player_moves(board: &Board, color: u8) -> Vec<Move> {
|
||||
pub fn get_player_moves(board: &Board, color: u8, castling: u8) -> Vec<Move> {
|
||||
let mut moves = vec!();
|
||||
for r in 0..8 {
|
||||
for f in 0..8 {
|
||||
|
@ -17,7 +26,7 @@ pub fn get_player_moves(board: &Board, color: u8) -> Vec<Move> {
|
|||
continue
|
||||
}
|
||||
if is_color(get_square(board, &p), color) {
|
||||
moves.append(&mut get_piece_moves(board, &p));
|
||||
moves.append(&mut get_piece_moves(board, &p, castling));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,14 +34,14 @@ pub fn get_player_moves(board: &Board, color: u8) -> Vec<Move> {
|
|||
}
|
||||
|
||||
/// Get a list of moves for the piece at position `at`.
|
||||
pub fn get_piece_moves(board: &Board, at: &Pos) -> Vec<Move> {
|
||||
pub fn get_piece_moves(board: &Board, at: &Pos, castling: u8) -> Vec<Move> {
|
||||
match get_square(board, at) {
|
||||
p if is_piece(p, SQ_P) => get_pawn_moves(board, at, p),
|
||||
p if is_piece(p, SQ_B) => get_bishop_moves(board, at, p),
|
||||
p if is_piece(p, SQ_N) => get_knight_moves(board, at, p),
|
||||
p if is_piece(p, SQ_R) => get_rook_moves(board, at, p),
|
||||
p if is_piece(p, SQ_Q) => get_queen_moves(board, at, p),
|
||||
p if is_piece(p, SQ_K) => get_king_moves(board, at, p),
|
||||
p if is_piece(p, SQ_K) => get_king_moves(board, at, p, castling),
|
||||
_ => vec!(),
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +171,7 @@ fn get_queen_moves(board: &Board, at: &Pos, piece: u8) -> Vec<Move> {
|
|||
moves
|
||||
}
|
||||
|
||||
fn get_king_moves(board: &Board, at: &Pos, piece: u8) -> Vec<Move> {
|
||||
fn get_king_moves(board: &Board, at: &Pos, piece: u8, castling: u8) -> Vec<Move> {
|
||||
let (f, r) = at;
|
||||
let mut moves = vec!();
|
||||
for offset in [(-1, 1), (0, 1), (1, 1), (-1, 0), (1, 0), (-1, -1), (0, -1), (1, -1)].iter() {
|
||||
|
@ -202,14 +211,14 @@ fn move_on_enemy(piece1: u8, pos1: &Pos, piece2: u8, pos2: &Pos) -> Option<Move>
|
|||
/// Return an iterator filtering out illegal moves from given list.
|
||||
///
|
||||
/// Pass color of moving player to avoid checking it for every move.
|
||||
fn filter_illegal_moves(board: &Board, color: u8, moves: Vec<Move>) -> Vec<Move> {
|
||||
fn filter_illegal_moves(board: &Board, color: u8, castling: u8, moves: Vec<Move>) -> Vec<Move> {
|
||||
let king_p = find_king(board, color);
|
||||
moves.into_iter().filter(|m| {
|
||||
// If king moved, use its new position.
|
||||
let king_p = if m.0 == king_p { m.1 } else { king_p };
|
||||
let new_board = apply(board, m);
|
||||
// Check if the move makes the player king in check.
|
||||
if is_attacked(&new_board, &king_p) {
|
||||
if is_attacked(&new_board, &king_p, castling) {
|
||||
return false
|
||||
}
|
||||
true
|
||||
|
@ -217,9 +226,9 @@ fn filter_illegal_moves(board: &Board, color: u8, moves: Vec<Move>) -> Vec<Move>
|
|||
}
|
||||
|
||||
/// Return true if the piece at position `at` is attacked.
|
||||
fn is_attacked(board: &Board, at: &Pos) -> bool {
|
||||
fn is_attacked(board: &Board, at: &Pos, castling: u8) -> bool {
|
||||
let color = get_color(get_square(board, at));
|
||||
let enemy_moves = get_player_moves(board, opposite(color));
|
||||
let enemy_moves = get_player_moves(board, opposite(color), castling);
|
||||
for m in enemy_moves.iter() {
|
||||
if *at == m.1 {
|
||||
return true
|
||||
|
@ -236,7 +245,7 @@ mod tests {
|
|||
fn test_get_player_moves() {
|
||||
let b = new();
|
||||
// At first move, white has 16 pawn moves and 4 knight moves.
|
||||
let moves = get_player_moves(&b, SQ_WH);
|
||||
let moves = get_player_moves(&b, SQ_WH, CASTLING_MASK);
|
||||
assert_eq!(moves.len(), 20);
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue