Skip to content

Commit

Permalink
feat: Implement bench CLI command for OB
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillbobyrev committed Jun 22, 2024
1 parent 1991d3b commit 2dc15f6
Show file tree
Hide file tree
Showing 18 changed files with 151 additions and 272 deletions.
72 changes: 26 additions & 46 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,60 +24,40 @@ include = [

[lints.rust]
# Warn
absolute_paths_not_starting_with_crate = "warn"
let_underscore_drop = "warn"
macro_use_extern_crate = "warn"
missing_docs = "warn"
unused_extern_crates = "warn"
unused_import_braces = "warn"
unused_lifetimes = "warn"
unused_qualifications = "warn"
variant_size_differences = "warn"
# absolute_paths_not_starting_with_crate = "warn"
# let_underscore_drop = "warn"
# macro_use_extern_crate = "warn"
# missing_docs = "warn"
# unused_extern_crates = "warn"
# unused_import_braces = "warn"
# unused_lifetimes = "warn"
# unused_qualifications = "warn"
# Deny
keyword_idents = "deny"
keyword_idents_2018 = "deny"
keyword_idents_2024 = "deny"
single_use_lifetimes = "deny"
trivial_casts = "deny"
trivial_numeric_casts = "deny"
unreachable_pub = "deny"
unused_results = "deny"
# keyword_idents_2018 = "deny"
# keyword_idents_2024 = "deny"
# trivial_casts = "deny"
# trivial_numeric_casts = "deny"
# unreachable_pub = "deny"
# unused_results = "deny"

[lints.clippy]
# TODO: Gradually enable more and more warnings.
# Warn
cargo = "warn"
cognitive_complexity = "warn"
complexity = "warn"
correctness = "warn"
dbg_macro = "warn"
nursery = "warn"
pedantic = "warn"
style = "warn"
suspicious = "warn"
decimal_literal_representation = "warn"
# cargo = "warn"
# complexity = "warn"
# correctness = "warn"
# nursery = "warn"
# pedantic = "warn"
# style = "warn"
# suspicious = "warn"
# Deny
cargo_common_metadata = "deny"
doc_markdown = "deny"
equatable_if_let = "deny"
float_cmp = "deny"
float_cmp_const = "deny"
get_unwrap = "deny"
implicit_clone = "deny"
imprecise_flops = "deny"
inefficient_to_string = "deny"
linkedlist = "deny"
manual_assert = "deny"
needless_collect = "deny"
missing_transmute_annotations = { level = "allow", priority = -1 }
perf = "deny"
redundant_clone = "deny"
suboptimal_flops = "deny"
trivial_regex = "deny"
use_self = "deny"

[lints.rustdoc]
broken_intra_doc_links = "deny"
invalid_rust_codeblocks = "deny"
unescaped_backticks = "deny"
# broken_intra_doc_links = "deny"
# invalid_rust_codeblocks = "deny"
# unescaped_backticks = "deny"

[workspace]
members = ["tools"]
Expand Down
3 changes: 1 addition & 2 deletions benches/cycles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ fn perft() {
4,
422_333,
),
]
{
] {
assert_eq!(pabi::chess::position::perft(position, *depth), *nodes);
}
}
Expand Down
7 changes: 2 additions & 5 deletions benches/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,12 @@ fn perft_bench(c: &mut Criterion) {
6,
120_142_144,
),
]
{
] {
group.throughput(criterion::Throughput::Elements(*nodes));
group.bench_with_input(
BenchmarkId::new(
"perft",
format!(
"position {position}, depth {depth}, nodes {nodes}"
),
format!("position {position}, depth {depth}, nodes {nodes}"),
),
depth,
|b, &depth| {
Expand Down
4 changes: 2 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ fmt:
# Checks the code for bad formatting, errors and warnings.
lint:
cargo +nightly fmt --all -- --check
cargo +nightly clippy --all-features
cargo +nightly clippy --all-targets --all-features

# Runs the linters and tries to apply automatic fixes.
fix:
cargo +nightly fmt --all
cargo +nightly clippy --all-features --fix --allow-staged
cargo +nightly clippy --all-targets --all-features --fix --allow-staged

# Run most tests that are fast and are run by default.
test:
Expand Down
16 changes: 10 additions & 6 deletions src/chess/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ impl Move {
/// Converts the move from UCI format to the internal representation. This
/// is important for the communication between the engine and UCI server in
/// `position` command.
#[must_use]
pub fn from_uci(uci: &str) -> anyhow::Result<Self> {
Self::try_from(uci)
}
Expand All @@ -52,7 +51,6 @@ impl Move {
impl TryFrom<&str> for Move {
type Error = anyhow::Error;

#[must_use]
fn try_from(uci: &str) -> anyhow::Result<Self> {
if uci.len() < 4 || uci.len() > 5 {
bail!("UCI move should be 4 or 5 characters long, got {uci}");
Expand Down Expand Up @@ -164,15 +162,17 @@ impl Square {
}

fn next(self) -> Option<Self> {
if self as u8 == 63 {
let next = self as u8 + 1;
if next == BOARD_SIZE {
None
} else {
Some(unsafe { mem::transmute(self as u8 + 1) })
Some(unsafe { mem::transmute(next) })
}
}

/// Creates an iterator over all squares, starting from A1 (0) to H8 (63).
#[must_use] pub fn iter() -> SquareIterator {
#[must_use]
pub fn iter() -> SquareIterator {
SquareIterator {
current: Some(Self::A1),
}
Expand Down Expand Up @@ -475,7 +475,8 @@ pub struct Piece {
}

impl Piece {
#[must_use] pub const fn plane(&self) -> usize {
#[must_use]
pub const fn plane(&self) -> usize {
self.owner as usize * 6 + self.kind as usize
}
}
Expand Down Expand Up @@ -853,6 +854,9 @@ mod tests {
squares,
vec![Square::B3, Square::F5, Square::H8, Square::E4]
);

assert_eq!(Square::try_from(4u8).unwrap(), Square::E1);
assert_eq!(Square::try_from(4i8).unwrap(), Square::E1);
}

#[test]
Expand Down
56 changes: 12 additions & 44 deletions src/chess/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,7 @@ use arrayvec::ArrayVec;
use super::zobrist::RepetitionTable;
use crate::chess::bitboard::{Bitboard, Pieces};
use crate::chess::core::{
CastleRights,
File,
Move,
MoveList,
Piece,
Player,
Promotion,
Rank,
Square,
BOARD_WIDTH,
CastleRights, File, Move, MoveList, Piece, Player, Promotion, Rank, Square, BOARD_WIDTH,
};
use crate::chess::{attacks, generated, zobrist};

Expand Down Expand Up @@ -115,7 +106,8 @@ impl Position {
/// Returns Zobrist hash of the position.
// TODO: Compute hash once and incrementally update it in make_move along with
// accumulator.
#[must_use] pub fn hash(&self) -> zobrist::Key {
#[must_use]
pub fn hash(&self) -> zobrist::Key {
self.compute_hash()
}

Expand Down Expand Up @@ -556,19 +548,19 @@ impl Position {
/// Note that because position does not keep track of the 3-fold repetition
/// it is not taken into account.
#[must_use]
pub fn is_stalemate(&self) -> bool {
pub fn is_draw_on_board(&self) -> bool {
self.halfmove_clock >= 100 || (!self.in_check() && self.generate_moves().is_empty())
}

#[must_use]
pub fn is_capture(&self, next_move: &Move) -> bool {
todo!()
}
// #[must_use]
// pub fn is_capture(&self, next_move: &Move) -> bool {
// todo!()
// }

#[must_use]
pub fn gives_check(&self, next_move: &Move) -> bool {
todo!()
}
// #[must_use]
// pub fn gives_check(&self, next_move: &Move) -> bool {
// todo!()
// }

#[must_use]
pub(crate) fn at(&self, square: Square) -> Option<Piece> {
Expand Down Expand Up @@ -1101,30 +1093,6 @@ fn generate_castle_moves(
}
}

struct PositionHistory {
positions: ArrayVec<Position, 256>,
repetitions: RepetitionTable,
}

impl PositionHistory {
fn new() -> Self {
Self {
positions: ArrayVec::new(),
repetitions: RepetitionTable::new(),
}
}

fn current_position(&self) -> &Position {
self.positions.last().expect("no positions in history")
}

fn push(&mut self, position: Position) -> bool {
let hash = position.hash();
self.positions.push(position);
self.repetitions.record(hash)
}
}

#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
Expand Down
12 changes: 11 additions & 1 deletion src/chess/zobrist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,29 @@ pub(crate) struct RepetitionTable {
}

impl RepetitionTable {
/// Creates an empty repetition table.
pub(crate) fn new() -> Self {
Self {
table: HashMap::new(),
}
}

/// Removes all entries from the repetition history.
pub(crate) fn clear(&mut self) {
self.table.clear();
}

/// Checks whether the repetition table has no entries.
///
/// This is mostly used for debugging purposes.
#[must_use]
pub(crate) fn is_empty(&self) -> bool {
self.table.is_empty()
}

/// Returns true if the position has occurred 3 times.
///
/// In most tournament settings 3-fold repetition counts as a draw.
/// In the tournament setting 3-fold repetition is a draw.
#[must_use]
pub(crate) fn record(&mut self, key: Key) -> bool {
let count = self.table.entry(key).or_insert(0);
Expand Down
3 changes: 1 addition & 2 deletions src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use crate::chess::position::Position;
use crate::engine::uci::Command;
use crate::search::{find_best_move, Depth};

pub mod openbench;
mod time_manager;
mod uci;

Expand Down Expand Up @@ -174,7 +173,7 @@ impl<'a, R: BufRead, W: Write> Engine<'a, R, W> {
Player::White => (wtime, winc),
Player::Black => (btime, binc),
};
let next_move = find_best_move(&self.position, max_depth, time, self.output);
let next_move = find_best_move(self.position.clone(), max_depth, time, self.output);
writeln!(self.output, "bestmove {next_move}")?;
Ok(())
}
Expand Down
15 changes: 0 additions & 15 deletions src/engine/openbench.rs

This file was deleted.

Loading

0 comments on commit 2dc15f6

Please sign in to comment.