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::thread;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use rand::seq::IteratorRandom;
|
|
||||||
|
|
||||||
use crate::board;
|
use crate::board;
|
||||||
use crate::notation;
|
use crate::notation;
|
||||||
use crate::rules;
|
use crate::rules;
|
||||||
|
@ -103,12 +101,6 @@ pub enum Info {
|
||||||
CurrentMove(board::Move),
|
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.
|
/// General engine implementation.
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn new() -> Engine {
|
pub fn new() -> Engine {
|
||||||
|
@ -118,7 +110,7 @@ impl Engine {
|
||||||
board: board::new_empty(),
|
board: board::new_empty(),
|
||||||
stats: (board::BoardStats::new(), board::BoardStats::new()),
|
stats: (board::BoardStats::new(), board::BoardStats::new()),
|
||||||
color: board::SQ_WH,
|
color: board::SQ_WH,
|
||||||
castling: CASTLING_MASK,
|
castling: rules::CASTLING_MASK,
|
||||||
en_passant: None,
|
en_passant: None,
|
||||||
halfmove: 0,
|
halfmove: 0,
|
||||||
fullmove: 1,
|
fullmove: 1,
|
||||||
|
@ -199,10 +191,10 @@ impl Engine {
|
||||||
fn set_fen_castling(&mut self, castling: &str) {
|
fn set_fen_castling(&mut self, castling: &str) {
|
||||||
for c in castling.chars() {
|
for c in castling.chars() {
|
||||||
match c {
|
match c {
|
||||||
'K' => self.state.castling |= CASTLING_WH_K,
|
'K' => self.state.castling |= rules::CASTLING_WH_K,
|
||||||
'Q' => self.state.castling |= CASTLING_WH_Q,
|
'Q' => self.state.castling |= rules::CASTLING_WH_Q,
|
||||||
'k' => self.state.castling |= CASTLING_BL_K,
|
'k' => self.state.castling |= rules::CASTLING_BL_K,
|
||||||
'q' => self.state.castling |= CASTLING_BL_Q,
|
'q' => self.state.castling |= rules::CASTLING_BL_Q,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,7 +317,6 @@ fn analyze(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stupid engine! Return a random move.
|
|
||||||
let moves = rules::get_player_legal_moves(&state.board, state.color);
|
let moves = rules::get_player_legal_moves(&state.board, state.color);
|
||||||
if debug {
|
if debug {
|
||||||
let state_str = format!("Current state: {:?}", state);
|
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));
|
let moves_str = format!("Legal moves: {}", notation::move_list_to_string(&moves));
|
||||||
tx.send(Cmd::Log(moves_str)).unwrap();
|
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_e = if board::is_white(state.color) { -999.0 } else { 999.0 };
|
||||||
let mut best_move = None;
|
let mut best_move = None;
|
||||||
|
|
33
src/rules.rs
33
src/rules.rs
|
@ -2,13 +2,22 @@
|
||||||
|
|
||||||
use crate::board::*;
|
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.
|
/// Get a list of legal moves for all pieces of this color.
|
||||||
pub fn get_player_legal_moves(board: &Board, color: u8) -> Vec<Move> {
|
pub fn get_player_legal_moves(board: &Board, color: u8, castling: u8) -> Vec<Move> {
|
||||||
filter_illegal_moves(board, color, get_player_moves(board, color))
|
filter_illegal_moves(board, color, get_player_moves(board, color, castling))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a list of moves for all pieces of this color.
|
/// 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!();
|
let mut moves = vec!();
|
||||||
for r in 0..8 {
|
for r in 0..8 {
|
||||||
for f in 0..8 {
|
for f in 0..8 {
|
||||||
|
@ -17,7 +26,7 @@ pub fn get_player_moves(board: &Board, color: u8) -> Vec<Move> {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if is_color(get_square(board, &p), color) {
|
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`.
|
/// 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) {
|
match get_square(board, at) {
|
||||||
p if is_piece(p, SQ_P) => get_pawn_moves(board, at, p),
|
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_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_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_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_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!(),
|
_ => vec!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +171,7 @@ fn get_queen_moves(board: &Board, at: &Pos, piece: u8) -> Vec<Move> {
|
||||||
moves
|
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 (f, r) = at;
|
||||||
let mut moves = vec!();
|
let mut moves = vec!();
|
||||||
for offset in [(-1, 1), (0, 1), (1, 1), (-1, 0), (1, 0), (-1, -1), (0, -1), (1, -1)].iter() {
|
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.
|
/// Return an iterator filtering out illegal moves from given list.
|
||||||
///
|
///
|
||||||
/// Pass color of moving player to avoid checking it for every move.
|
/// 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);
|
let king_p = find_king(board, color);
|
||||||
moves.into_iter().filter(|m| {
|
moves.into_iter().filter(|m| {
|
||||||
// If king moved, use its new position.
|
// If king moved, use its new position.
|
||||||
let king_p = if m.0 == king_p { m.1 } else { king_p };
|
let king_p = if m.0 == king_p { m.1 } else { king_p };
|
||||||
let new_board = apply(board, m);
|
let new_board = apply(board, m);
|
||||||
// Check if the move makes the player king in check.
|
// 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
|
return false
|
||||||
}
|
}
|
||||||
true
|
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.
|
/// 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 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() {
|
for m in enemy_moves.iter() {
|
||||||
if *at == m.1 {
|
if *at == m.1 {
|
||||||
return true
|
return true
|
||||||
|
@ -236,7 +245,7 @@ mod tests {
|
||||||
fn test_get_player_moves() {
|
fn test_get_player_moves() {
|
||||||
let b = new();
|
let b = new();
|
||||||
// At first move, white has 16 pawn moves and 4 knight moves.
|
// 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);
|
assert_eq!(moves.len(), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue