Skip to content

Commit

Permalink
improved draw detection
Browse files Browse the repository at this point in the history
  • Loading branch information
dede1751 committed Feb 12, 2023
1 parent 1e86737 commit 5c12f5e
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "carp"
version = "1.2.2"
version = "1.3.0"
edition = "2021"
authors = ["Andrea Sgobbi"]

Expand Down
14 changes: 7 additions & 7 deletions readme.MD
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,16 @@ and most importantly the [chess programming wiki](https://www.chessprogramming.o
Move generation is fully legal, inspired by [this article](https://www.codeproject.com/Articles/5313417/Worlds-Fastest-Bitboard-Chess-Movegenerator)
and perft(7) on startpos will achieve ~130 MNodes/s locally (a roughly 4x speedup compared to pseudolegal generation).

Version 1.2 adds much more aggressive pruning techniques, which have brought a noticeable speedup in
time to depth and reduced the branching factor greatly. Now Carp can easily push to depths 16-17 in
Newer versions added much more aggressive pruning techniques, which have brought a noticeable speedup in
time to depth and reduced the branching factor greatly. Now Carp can easily push to depths 18-20 in
blitz midgames, hitting much softer depth walls.
Version 1.3 includes many search optimizations discussed in the chess programming wiki, leading to
a massive elo increase. Currently I would estimate Carp to be ~2750 CCRL40/15 elo on 4CPU, though I
will wait until done with evaluation to submit it to competitions.

To benchmark the engine I've also added a test directory with a simple shell script running cutechess
cli. The script allows to run gauntlet tests against other engines or SPRT tests against older versions
of Carp. Engines must be manually added to the shell script.
Version 1.2.2 implemented many search optimizations described in the Chess Programming wiki which
still need proper testing and parameter tuning, although Carp seems to have gained at least ~120
elo compared to the previous version.
To accomodate for all this testing, I'm looking to make Carp OpenBench compliant and eventually
host my own instance.

The engine is quite fun to play against when limiting the depth to reasonable values, since
it is relatively dumb positionally: provided it does not see some crazy computer tactic a good
Expand Down Expand Up @@ -61,3 +59,5 @@ Of course it is still lacking many optimizations, most notably:
* Endgame tablebases
* Various other heuristics (probcut, razoring, search extensions...)
* Further improvement to evaluation/NNUE

I also want to work on OpenBench compliance to simplify testing.
25 changes: 18 additions & 7 deletions src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,28 @@ impl Position {
}

/// Draw by insufficient material (strictly for when it is impossible to mate):
/// - King vs King
/// - King vs King + Bishop
/// - King vs King + Knight
/// - King + Bishop vs King + Bishop
/// Some of the logic is taken from Tantabus
fn insufficient_material(&self) -> bool {
const WHITE_SQUARES: BitBoard = BitBoard(12273903644374837845);
const CORNERS: BitBoard = BitBoard(9295429630892703873);
const EDGES: BitBoard = BitBoard(18411139144890810879);
let kings = self.board.kings();
let knights = self.board.knights();
let bishops = self.board.bishops();

match self.board.occupancy.count_bits() {
2 => true,
3 => self.board.knights() | self.board.bishops() != EMPTY_BB, // 1 knight or 1 bishop
3 => knights | bishops != EMPTY_BB, // 1 knight or 1 bishop
4 => {
self.board.bishops().count_bits() == 2 && // opposite color bishops
(self.board.bishops() & WHITE_SQUARES).count_bits() == 1
let one_each = self.board.side_occupancy[0].count_bits() == 2;
let knight_count = knights.count_bits();
let bishop_count = bishops.count_bits();

(knight_count == 2 && kings & EDGES != EMPTY_BB) // two knights, king not on edge
|| (bishop_count == 2
&& ((bishops & WHITE_SQUARES).count_bits() != 1 // same color bishops
|| (one_each && kings & CORNERS != EMPTY_BB))) // opposite color, king not in corner
|| (one_each && kings & CORNERS != EMPTY_BB) // bishop and knight, king not in corner
}
_ => false,
}
Expand Down
21 changes: 5 additions & 16 deletions src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,21 +340,10 @@ impl<'a> Search<'a> {
// reduce depth for all moves beyond first
let reduced_depth =
if move_count >= LMR_THRESHOLD && depth >= LMR_LOWER_LIMIT && is_quiet {
let lmr_reduction = lmr_reduction(depth, move_count);
let lmr_extension =
is_check as usize + in_check as usize + pv_node as usize;

if lmr_extension >= lmr_reduction {
depth
} else {
let lmr = lmr_reduction - lmr_extension;

if depth >= lmr + 1 {
depth - lmr
} else {
1
}
}
let lmr_red = lmr_reduction(depth, move_count) as i32;
let lmr_ext = is_check as i32 + in_check as i32 + pv_node as i32;

(depth as i32 + lmr_ext - lmr_red).clamp(1, depth as i32) as usize
} else {
depth
};
Expand Down Expand Up @@ -420,7 +409,7 @@ impl<'a> Search<'a> {

let in_check = self.position.king_in_check();

// when in check, avoid aggressive pruning
// Stand pat and delta pruning avoided when in check
let mut stand_pat = 0;
if !in_check {
stand_pat = self.position.evaluate();
Expand Down
4 changes: 0 additions & 4 deletions src/square.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ pub const DOUBLE_PUSH: [[Square; FILE_COUNT]; 2] = [
[ A5, B5, C5, D5, E5, F5, G5, H5 ]
];

/// Black/White square bitboards
pub const WHITE_SQUARES: BitBoard = BitBoard(12273903644374837845);
pub const BLACK_SQUARES: BitBoard = BitBoard(6172840429334713770);

/// Print fen formatted square.
impl fmt::Display for Square {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down

0 comments on commit 5c12f5e

Please sign in to comment.