cleanup, add bench

This commit is contained in:
jackjohn7 2025-10-30 04:26:49 -05:00
parent 99e619d733
commit 10de749e1d
7 changed files with 678 additions and 8 deletions

2
.cargo/config.toml Normal file
View file

@ -0,0 +1,2 @@
[alias]
test-all = "test --workspace --all-targets"

437
Cargo.lock generated
View file

@ -2,24 +2,63 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bitflags"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "bumpalo"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "castaway"
version = "0.2.4"
@ -35,6 +74,58 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clap"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
dependencies = [
"anstyle",
"clap_lex",
]
[[package]]
name = "clap_lex"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
name = "compact_str"
version = "0.8.1"
@ -49,6 +140,64 @@ dependencies = [
"static_assertions",
]
[[package]]
name = "criterion"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"itertools",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crossterm"
version = "0.28.1"
@ -74,6 +223,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "darling"
version = "0.20.11"
@ -143,6 +298,17 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "half"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
dependencies = [
"cfg-if",
"crunchy",
"zerocopy",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
@ -210,6 +376,16 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "js-sys"
version = "0.3.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.177"
@ -246,6 +422,12 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "mio"
version = "1.0.4"
@ -264,10 +446,32 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0f887dfb09c7315d803a0ceac77f27da5c84213c9b170dc8ae88d2b6b1739a"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "oorandom"
version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
name = "othello"
version = "0.1.0"
dependencies = [
"criterion",
"ratatui",
]
@ -300,6 +504,34 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "plotters"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
[[package]]
name = "plotters-svg"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.102"
@ -339,6 +571,26 @@ dependencies = [
"unicode-width 0.2.0",
]
[[package]]
name = "rayon"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
@ -348,6 +600,35 @@ dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "rustix"
version = "0.38.44"
@ -373,12 +654,64 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
]
[[package]]
name = "signal-hook"
version = "0.3.18"
@ -460,6 +793,16 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-ident"
version = "1.0.20"
@ -495,12 +838,77 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasm-bindgen"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"
version = "0.3.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -517,6 +925,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@ -610,3 +1027,23 @@ name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "zerocopy"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -4,3 +4,4 @@ members = ["iagorithms", "othello"]
[workspace.dependencies]
neorusticus = "0.1.3"
ratatui = "0.29.0"
criterion = "0.7.0"

View file

@ -220,7 +220,6 @@ mod tests {
}
println!("\n=== All tests completed ===");
panic!();
Ok(())
}
}

View file

@ -13,3 +13,10 @@ path = "src/main.rs"
[dependencies]
ratatui.workspace = true
[dev-dependencies]
criterion.workspace = true
[[bench]]
name = "generation"
harness = false

View file

@ -0,0 +1,199 @@
use std::hint::black_box;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use othello::{board::BitBoard, game::Team};
const JONS: [&'static str; 20] = [
"///3bw/3wb",
"///////6bw",
"///////wb",
"wwwwwwww/wwwwwwww/////",
"//1b2w/1bwwww/1bwbww/1bwwww/1b3/",
"///3bw/2bbw/3b//",
"///////bww",
"////bwwwww1b///",
"www/wbw/www////",
"///3b/2bwb/3b//",
"5bw//////",
"///////wb",
"7w/6b/5b",
"w/1b/2b",
"/////5w/6w/7b",
"/////2w/1w/b",
"b/w/w/w//b//",
"////bwwwww1b///",
"///3w///",
"///////",
];
const JON_NAMES: [&str; 20] = [
"starting_position",
"near_endgame",
"corner_setup_a1",
"white_dominance",
"complex_midgame",
"after_first_move",
"edge_capture",
"long_horizontal",
"surrounded_black",
"white_surrounded",
"corner_setup_h8",
"corner_setup_h1",
"diagonal_line",
"short_diagonal",
"anti_diagonal",
"anti_diagonal_short",
"vertical_capture",
"long_horizontal_alt",
"single_piece",
"empty_board",
];
fn bench_available_black(c: &mut Criterion) {
let mut group = c.benchmark_group("available_black");
for (i, jon) in JONS.iter().enumerate() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(
BenchmarkId::new("position", JON_NAMES[i]),
&bb,
|b, board| {
b.iter(|| black_box(board.available(black_box(Team::Black))));
},
);
}
group.finish();
}
fn bench_available_white(c: &mut Criterion) {
let mut group = c.benchmark_group("available_white");
for (i, jon) in JONS.iter().enumerate() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(
BenchmarkId::new("position", JON_NAMES[i]),
&bb,
|b, board| {
b.iter(|| black_box(board.available(black_box(Team::White))));
},
);
}
group.finish();
}
fn bench_available_both_teams(c: &mut Criterion) {
let mut group = c.benchmark_group("available_both_teams");
for (i, jon) in JONS.iter().enumerate() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(
BenchmarkId::new("position", JON_NAMES[i]),
&bb,
|b, board| {
b.iter(|| {
let black_moves = black_box(board.available(Team::Black));
let white_moves = black_box(board.available(Team::White));
black_box((black_moves, white_moves))
});
},
);
}
group.finish();
}
fn bench_available_starting_only(c: &mut Criterion) {
let bb = BitBoard::default();
c.bench_function("starting_position_black", |b| {
b.iter(|| black_box(bb.available(black_box(Team::Black))));
});
c.bench_function("starting_position_white", |b| {
b.iter(|| black_box(bb.available(black_box(Team::White))));
});
}
fn bench_available_worst_case(c: &mut Criterion) {
// Positions that might be slower due to more pieces or complexity
let worst_cases = [
("complex_midgame", "//1b2w/1bwwww/1bwbww/1bwwww/1b3/"),
("white_dominance", "wwwwwwww/wwwwwwww/////"),
("long_capture", "////bwwwww1b///"),
];
let mut group = c.benchmark_group("available_worst_case");
for (name, jon) in worst_cases.iter() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(BenchmarkId::new("black", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::Black)));
});
group.bench_with_input(BenchmarkId::new("white", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::White)));
});
}
group.finish();
}
fn bench_available_best_case(c: &mut Criterion) {
// Positions that should be fast (empty board, single piece, etc.)
let best_cases = [
("empty_board", "///////"),
("single_piece", "///3w///"),
("corner_only", "///////wb"),
];
let mut group = c.benchmark_group("available_best_case");
for (name, jon) in best_cases.iter() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(BenchmarkId::new("black", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::Black)));
});
group.bench_with_input(BenchmarkId::new("white", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::White)));
});
}
group.finish();
}
fn bench_available_all_positions_sequential(c: &mut Criterion) {
let boards: Vec<BitBoard> = JONS
.iter()
.map(|jon| BitBoard::from_jon(jon).expect("Valid JON"))
.collect();
c.bench_function("all_positions_black_sequential", |b| {
b.iter(|| {
for board in &boards {
black_box(board.available(Team::Black));
}
});
});
c.bench_function("all_positions_white_sequential", |b| {
b.iter(|| {
for board in &boards {
black_box(board.available(Team::White));
}
});
});
}
criterion_group!(
benches,
bench_available_black,
bench_available_white,
bench_available_both_teams,
bench_available_starting_only,
bench_available_worst_case,
bench_available_best_case,
bench_available_all_positions_sequential,
);
criterion_main!(benches);

View file

@ -151,7 +151,21 @@ fn shift_in_direction(magnitude: i8, value: Board) -> Board {
impl BitBoard {
/// Convert from a JON (Jack Othello Notation) string into a usable board.
pub fn from_jon(fen: &str) -> Result<Self, &'static str> {
/// Format:
///
/// | Symbol or Pattern | Meaning |
/// | ------------------ | --------------------------------- |
/// | `/` | _next line_ |
/// | `[0-9]` | _jump squares_ |
/// | `[wWbB]` | _white or black disc at position_ |
///
/// Example: `///3bw/3wb///` is the JON for the starting position.
/// It means three empty ranks, three empty spaces followed by a black disc,
/// a white disc, next rank, three empty spaces followed by a white disc,
/// a black disc, and then three empty ranks. It also technically could be
/// truncated after the second `b` as `///3bw/3wb` since trailing rank is
/// optional.
pub fn from_jon(fen: &str) -> Result<Self, String> {
let mut boards: [Board; 2] = [0, 0];
let mut line: u8 = 7;
let mut rank_idx: u8 = 0;
@ -159,7 +173,7 @@ impl BitBoard {
for c in fen.chars().into_iter() {
match c.to_ascii_lowercase() {
'/' => {
line -= 1;
line = line.checked_sub(1).ok_or("Malformed JON: Too many ranks")?;
rank_idx = 0;
rank_jump = 0;
}
@ -176,17 +190,21 @@ impl BitBoard {
'0'..'9' => {
rank_jump = c
.to_digit(10u32)
.ok_or("Failed to parse integer from character")?
.ok_or("JON Parsing error: Failed to parse integer from character")?
as u8;
}
_ => {
return Err("Malformed FEN: Unexpected character encountered");
c => {
return Err(format!(
"Malformed JON: Unexpected character encountered ({})",
c
));
}
}
}
Ok(Self { boards })
}
/// Compute board with valid moves marked
/// Compute board with valid moves marked using only bitwise operations.
/// This has constant time complexity and is unbelievably fast.
pub fn available(&self, current_team: Team) -> Board {
// bitwise OR gives spots with either white OR black discs
// bitwise NEG gives the spots with neither white nor black discs
@ -370,8 +388,15 @@ mod tests {
#[test]
fn jon_works() {
let bb = BitBoard::from_jon("///3bw/3wb///").expect("Starting board should be valid");
println!("{}", bb);
assert_eq!(bb.boards, BitBoard::default().boards);
// trailing slashes are optional
let bb = BitBoard::from_jon("///3bw/3wb")
.expect("Starting board without trailing slashes should be valid");
assert_eq!(bb.boards, BitBoard::default().boards);
// test with too many slashes
assert!(BitBoard::from_jon("////////").is_err());
// test with unexpected char
assert!(BitBoard::from_jon("//c/////").is_err());
}
#[test]