aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-02-27 03:41:26 +0300
committereug-vs <eugene@eug-vs.xyz>2023-02-27 03:41:26 +0300
commit5e2238ce4ae4ad7bc2d57ee45af866976211e6d3 (patch)
tree6766d57de41fd52fcc319150dc5e2ea8f2da21c1
parenta333e9285d55dad06b6507340f1c0416c9c7b6f9 (diff)
downloadchessnost-5e2238ce4ae4ad7bc2d57ee45af866976211e6d3.tar.gz
feat: add 3-fold repetition
-rw-r--r--src/board/io.rs1
-rw-r--r--src/board/mod.rs12
-rw-r--r--src/grossmeister/UCI.rs2
-rw-r--r--src/grossmeister/search.rs11
4 files changed, 19 insertions, 7 deletions
diff --git a/src/board/io.rs b/src/board/io.rs
index d27b856..15d7744 100644
--- a/src/board/io.rs
+++ b/src/board/io.rs
@@ -97,6 +97,7 @@ impl IO for Board {
castling_rights: [[true; 2]; 2], // TODO: actualy parse from FEN
ep_target: None, // TODO: parse from FEN
clock: Clock::default(),
+ positions: Vec::new(),
hash: 0,
zobrist_seed: Board::seed(),
};
diff --git a/src/board/mod.rs b/src/board/mod.rs
index 95d470a..50aa1b9 100644
--- a/src/board/mod.rs
+++ b/src/board/mod.rs
@@ -15,7 +15,7 @@ pub enum CastlingSide {
/// Chess board is an main interface to the internal game state.
/// Board defines rules of the game and manages players actions.
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
pub struct Board {
pub ply: u16,
pub piece_sets: [Bitboard; 12],
@@ -26,12 +26,16 @@ pub struct Board {
pub clock: Clock,
+ /// List of all positions to determine repetitions
+ pub positions: Vec<u64>,
+
// Computed values
pub occupancy: Bitboard,
/// Zobrist hash of the current position
pub hash: u64,
zobrist_seed: ZobristSeed,
+
pub attacks: Attacks,
}
@@ -227,6 +231,7 @@ impl Board {
self.ply += 1;
self.zobrist_toggle_color();
+ self.positions.push(self.hash);
captured_piece
}
@@ -320,6 +325,7 @@ impl Board {
self.castling_rights = previous_castling_rights;
self.hash = previous_hash;
self.ply -= 1;
+ self.positions.pop();
}
pub fn is_square_attacked(&self, square: Square, attacker_color: Color) -> bool {
@@ -388,7 +394,7 @@ mod tests {
fn make_move() {
let fen = String::from("q1b2k2/5p1p/4p1pb/pPPp4/3N4/3nPB2/P2QKnR1/1R6 w - - 0 25");
let mut board = Board::from_FEN(fen);
- let initial_board = board;
+ let initial_board = board.clone();
board.print();
let black_move = Move { source: Square::F7, target: Square::F5, kind: MoveKind::Quiet };
@@ -429,7 +435,7 @@ mod tests {
fn unmake_move() {
let fen = String::from("q1b2k2/5p1p/4p1pb/pPPp4/3N4/3nPB2/P2QKnR1/1R6 w - - 0 25");
let mut board = Board::from_FEN(fen);
- let initial_board = board;
+ let initial_board = board.clone();
let mov = Move { source: Square::D2, target: Square::A5, kind: MoveKind::Capture };
diff --git a/src/grossmeister/UCI.rs b/src/grossmeister/UCI.rs
index 034b73b..3132e72 100644
--- a/src/grossmeister/UCI.rs
+++ b/src/grossmeister/UCI.rs
@@ -59,7 +59,7 @@ impl Grossmeister {
.find(|m| {
let promo_matches = match input_move.kind {
MoveKind::Promotion(piece) => match m.kind {
- MoveKind::Promotion(another_piece) => piece == another_piece,
+ MoveKind::Promotion(another_piece) => piece.without_color() == another_piece.without_color(),
_ => false
},
_ => true,
diff --git a/src/grossmeister/search.rs b/src/grossmeister/search.rs
index 5c03887..43423e4 100644
--- a/src/grossmeister/search.rs
+++ b/src/grossmeister/search.rs
@@ -45,6 +45,11 @@ impl Grossmeister {
}
}
+ if self.board.positions.iter().filter(|p| **p == self.board.hash).count() >= 3 {
+ // Draw by repetition
+ return (0.0, principal_variation);
+ }
+
if depth_left == 0 {
return (self.quiscence(alpha, beta), principal_variation);
}
@@ -447,7 +452,7 @@ mod tests {
let fen = String::from("2kr1b1r/pp1npppp/2p1bn2/7q/5B2/2NB1Q1P/PPP1N1P1/2KR3R w - - 0 1");
let board = Board::from_FEN(fen);
let mut gm = Grossmeister::new(board);
- let (score, pv) = gm.iterative_deepening(8, Duration::from_secs(15), true);
+ let (score, pv) = gm.iterative_deepening(8);
assert_eq!(score, VALUE_WIN);
assert_eq!(pv, vec![
@@ -464,7 +469,7 @@ mod tests {
board.ply += 1; // TODO: remove me when FEN parsing includes side to move
let mut gm = Grossmeister::new(board);
- let (_, pv) = gm.iterative_deepening(6, Duration::from_secs(60), true);
+ let (_, pv) = gm.iterative_deepening(6);
assert_eq!(
pv[0],
Move { source: Square::F5, target: Square::H4, kind: MoveKind::Quiet },
@@ -478,7 +483,7 @@ mod tests {
let board = Board::from_FEN(fen);
let mut gm = Grossmeister::new(board);
- let (_, pv) = gm.iterative_deepening(5, Duration::from_secs(60), true);
+ let (_, pv) = gm.iterative_deepening(5);
assert_eq!(
pv[0],
Move { source: Square::C2, target: Square::C3, kind: MoveKind::Quiet },