Skip to content

Commit

Permalink
chore: Store progress
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillbobyrev committed Jul 10, 2024
1 parent 298540a commit cddb3c5
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 46 deletions.
87 changes: 87 additions & 0 deletions Cargo.lock

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

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,17 @@ shadow-rs = "0.29.0"

[dev-dependencies]
assert_cmd = "2.0.14"
criterion = { version = "0.5.1", features = ["cargo_bench_support"] }
criterion = "0.5.1"
predicates = "3.1.0"
pretty_assertions = "1.1.0"
proptest = "1.5.0"
shadow-rs = "0.29.0"
# Used for testing and comparing against a reasonable baseline for correctness.
shakmaty = "0.27.0"

[[bench]]
harness = false
name = "perft"
name = "chess"

# TODO: Test this out once the benchmarks are available and tweak specific
# values. So far, this gives around -8% on parsing FEN/EPD positions.
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

Pabi is a modern chess engine that is currently under development.

> [!WARNING]
> This engine is still very early in the development phase and is not in a
> functional state yet.
## Goals

Pabi is inspired by existing Chess and Go engines (mainly [lc0] and [KataGo]),
Expand All @@ -31,8 +35,8 @@ See [justfile](/justfile) for a complete list of frequently used commands.

## Code map

Rustdoc developer documentation is pushed at each commit to
<https://kirillbobyrev.github.io/pabi/docs/pabi/>.
For easier code navigation, see
<https://kirillbobyrev.github.io/pabi/docs/pabi/>

## [Milestones]

Expand Down
47 changes: 23 additions & 24 deletions benches/perft.rs → benches/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::fs;

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use pabi::chess::position::Position;

fn generate_moves(positions: &[Position]) {
Expand All @@ -11,19 +11,22 @@ fn generate_moves(positions: &[Position]) {
}
}

fn movegen_bench(c: &mut Criterion) {
let mut group = c.benchmark_group("Move generation");
let mut positions = vec![];
for line in fs::read_to_string(concat!(
fn load_positions() -> Vec<Position> {
fs::read_to_string(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/data/positions.fen"
))
.unwrap()
.lines()
{
positions.push(Position::try_from(line).unwrap());
}
group.throughput(criterion::Throughput::Elements(positions.len() as u64));
.map(|line| Position::try_from(line).unwrap())
.collect()
}

fn bench_movegen(c: &mut Criterion) {
let mut group = c.benchmark_group("Move generation");
let positions = load_positions();

group.throughput(Throughput::Elements(positions.len() as u64));
group.bench_with_input(
BenchmarkId::new(
"movegen_pabi",
Expand All @@ -40,31 +43,26 @@ fn movegen_bench(c: &mut Criterion) {
criterion_group! {
name = movegen;
config = Criterion::default().sample_size(100);
targets = movegen_bench
targets = bench_movegen
}

// This acts both as performance and correctness test.
fn perft_bench(c: &mut Criterion) {
fn bench_perft(c: &mut Criterion) {
let mut group = c.benchmark_group("perft");
// TODO: Add Throughput - it should be the number of nodes.
for (position, depth, nodes) in &[
// Position 1.

let test_cases = vec![
(Position::starting(), 5, 4_865_609),
(Position::starting(), 6, 119_060_324),
// Position 3.
(
Position::from_fen("8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1").unwrap(),
6,
11_030_083,
),
// Position 4.
(
Position::from_fen("r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1")
.unwrap(),
6,
706_045_033,
),
// Position 6.
(
Position::from_fen(
"r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 10",
Expand All @@ -73,7 +71,6 @@ fn perft_bench(c: &mut Criterion) {
5,
164_075_551,
),
// Other positions.
(
Position::from_fen("r1bqkbnr/pppppppp/2n5/8/3P4/8/PPP1PPPP/RNBQKBNR w KQkq - 1 2")
.unwrap(),
Expand All @@ -86,17 +83,19 @@ fn perft_bench(c: &mut Criterion) {
6,
120_142_144,
),
] {
group.throughput(criterion::Throughput::Elements(*nodes));
];

for (position, depth, nodes) in test_cases {
group.throughput(Throughput::Elements(nodes));
group.bench_with_input(
BenchmarkId::new(
"perft",
format!("position {position}, depth {depth}, nodes {nodes}"),
),
depth,
&depth,
|b, &depth| {
b.iter(|| {
assert_eq!(pabi::chess::position::perft(position, depth), *nodes);
assert_eq!(pabi::chess::position::perft(&position, depth), nodes);
});
},
);
Expand All @@ -107,7 +106,7 @@ fn perft_bench(c: &mut Criterion) {
criterion_group! {
name = perft;
config = Criterion::default().sample_size(10);
targets = perft_bench
targets = bench_perft
}

criterion_main!(movegen, perft);
25 changes: 11 additions & 14 deletions src/chess/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,21 +579,9 @@ impl fmt::Display for Piece {

bitflags::bitflags! {
/// Track the ability to [castle] each side (kingside is often referred to
/// as O-O or h-side castle, queenside -- O-O-O or a-side castle). When the
/// king moves, player loses ability to castle. When the rook moves, player
/// loses ability to castle to the side from which the rook moved.
/// as `O-O` castle, queenside -- `O-O-O`).
///
/// Castling is relatively straightforward in the Standard Chess but is
/// often misunderstood in Chess960 (also known as Fischer Random Chess). An
/// easy mnemonic is that the king and the rook end up on the same files for
/// both Standard and FRC:
///
/// - When castling h-side (short), the king ends up on [`File::G`] and the
/// rook on [`File::F`]
/// - When castling a-side (long), the king ends up on [`File::C`] and the
/// rook on [`File::D`]
///
/// The full rules are:
/// Castling is possible if the following conditions are met:
///
/// - The king and the castling rook must not have previously moved.
/// - No square from the king's initial square to its final square may be under
Expand All @@ -603,6 +591,15 @@ bitflags::bitflags! {
/// rook's initial and final squares (including the final square), must be
/// vacant except for the king and castling rook.
///
/// Castling is relatively straightforward in the Standard Chess but is
/// often misunderstood in Chess960. An easy mnemonic is that the king and
/// the rook end up on the same files for both Standard and FRC:
///
/// - When castling short (`O-O`), the king ends up on [`File::G`] and the
/// rook on [`File::F`]
/// - When castling long (`O-O-O`), the king ends up on [`File::C`] and the
/// rook on [`File::D`]
///
/// [castle]: https://www.chessprogramming.org/Castling
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CastleRights : u8 {
Expand Down
10 changes: 9 additions & 1 deletion src/chess/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ use anyhow::{bail, Context};
use super::core::{Direction, PieceKind};
use crate::chess::bitboard::{Bitboard, Pieces};
use crate::chess::core::{
CastleRights, File, Move, MoveList, Piece, Promotion, Rank, Square, BOARD_WIDTH,
CastleRights,
File,
Move,
MoveList,
Piece,
Promotion,
Rank,
Square,
BOARD_WIDTH,
};
use crate::chess::{attacks, generated, zobrist};
use crate::environment::Player;
Expand Down
3 changes: 2 additions & 1 deletion src/search/mcts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ struct Config {
/// 1. Selection: Start from root node and select the most promising child node.
/// 2. Expansion: If the selected node is not a leaf node, expand it by adding a
/// new child node.
/// 3. Simulation: Run a simulation from the child node until a result is reached.
/// 3. Simulation: Run a simulation from the child node until a result is
/// reached.
/// 4. Backpropagation: Update the nodes on the path from the root to the
/// selected node with the result.
fn search(iterations: usize) {
Expand Down
3 changes: 1 addition & 2 deletions src/search/policy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::environment::Action;

use super::tree;
use crate::environment::Action;

fn select<A: Action>(node: &tree::Node<A>) {
todo!()
Expand Down

0 comments on commit cddb3c5

Please sign in to comment.