From 82beff91b15627c5e75c3ca9820b6aeff925d912 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Sat, 23 Mar 2019 18:39:36 -0700 Subject: [PATCH 01/10] Progress on allowing rust std toolchain use on `pleco` Signed-off-by: Stephen Fleischman --- pleco/src/core/mono_traits.rs | 2 +- pleco/src/lib.rs | 19 +++++++++++-------- pleco/src/tools/mod.rs | 1 + pleco/src/tools/tt.rs | 35 ++++++++++++++++++++++++----------- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/pleco/src/core/mono_traits.rs b/pleco/src/core/mono_traits.rs index ccdb8a6..3f8ef51 100644 --- a/pleco/src/core/mono_traits.rs +++ b/pleco/src/core/mono_traits.rs @@ -4,7 +4,7 @@ //! This modules only use is to allow for compile-time mono-morphization of //! functions / methods, where each method created can be optimized further. //! -//! We are awaiting the stabilization of `const fn` to remove these traits. +//! We are awaiting the stabilization of `const fn` and constant generics to remove these traits. use super::{Player, PieceType, GenTypes}; use super::sq::SQ; diff --git a/pleco/src/lib.rs b/pleco/src/lib.rs index 2951ccc..f651cde 100644 --- a/pleco/src/lib.rs +++ b/pleco/src/lib.rs @@ -61,14 +61,16 @@ //#![crate_type = "rlib"] -#![feature(trusted_len)] -#![feature(test)] -#![feature(integer_atomics)] -#![feature(allocator_api)] -#![feature(const_fn)] -#![feature(stdsimd)] -#![feature(const_slice_len)] -#![feature(alloc_layout_extra)] +// Unneeded I think +//#![feature(test)] +//#![feature(integer_atomics)] +//#![feature(const_fn)] +//#![feature(stdsimd)] + +// Need these for nightly +#![feature(const_slice_len)] // General Usage +#![feature(trusted_len)] // used in MoveList + #![allow(dead_code)] #[macro_use] @@ -78,6 +80,7 @@ extern crate lazy_static; extern crate num_cpus; extern crate rand; extern crate rayon; +// This requires nightly, probably should find a better way to prefetch. extern crate prefetch; extern crate mucow; diff --git a/pleco/src/tools/mod.rs b/pleco/src/tools/mod.rs index fa178c0..0b45abe 100644 --- a/pleco/src/tools/mod.rs +++ b/pleco/src/tools/mod.rs @@ -22,6 +22,7 @@ pub trait Searcher { Self: Sized; } +// https://doc.rust-lang.org/core/arch/x86_64/fn._mm_prefetch.html /// Allows an object to have it's entries pre-fetchable. pub trait PreFetchable { /// Pre-fetches a particular key. This means bringing it into the cache for faster access. diff --git a/pleco/src/tools/tt.rs b/pleco/src/tools/tt.rs index 1aff589..dd787ea 100644 --- a/pleco/src/tools/tt.rs +++ b/pleco/src/tools/tt.rs @@ -35,7 +35,7 @@ use std::ptr::NonNull; use std::mem; -use std::alloc::{Alloc, Layout, Global, handle_alloc_error}; +use std::alloc::{Layout, handle_alloc_error, self}; use std::cmp::min; use std::cell::UnsafeCell; @@ -283,7 +283,7 @@ impl TranspositionTable { /// /// This is function is unsafe to use if the TT is currently being accessed, Or any thread of /// structure contains a current reference to a `TTEntry`. Otherwise, using this function will - /// absolutely lead to Segmentation Fault. + /// absolutely lead to a Segmentation Fault. pub unsafe fn resize_round_up(&self, size: usize) { self.resize(size.next_power_of_two()); } @@ -323,7 +323,7 @@ impl TranspositionTable { /// /// This is function is unsafe to use if the TT is currently being accessed, Or any thread of /// structure contains a current reference to a `TTEntry`. Otherwise, using this function will - /// absolutely lead to Segmentation Fault. + /// absolutely lead to a Segmentation Fault. pub unsafe fn clear(&self) { let size = self.cap.get(); self.resize(*size); @@ -423,8 +423,10 @@ impl TranspositionTable { /// De-allocates the current heap. unsafe fn de_alloc(&self) { - let ptr: NonNull = mem::transmute(*self.clusters.get()); - Global.dealloc(ptr, Layout::array::(*self.cap.get()).unwrap()); + let layout = Layout::from_size_align(*self.cap.get(), 2).unwrap(); + let ptr: *mut u8 = mem::transmute(*self.clusters.get()); +// alloc::dealloc(ptr, Layout::array::(*self.cap.get()).unwrap()); + alloc::dealloc(ptr, layout); } /// Returns the % of the hash table that is full. @@ -481,12 +483,13 @@ unsafe fn cluster_first_entry(cluster: *mut Cluster) -> *mut Entry { #[inline] fn alloc_room(size: usize) -> NonNull { unsafe { - let layout = Layout::array::(size).unwrap(); - let ptr = Global.alloc_zeroed(layout); - - let new_ptr = match ptr { - Ok(ptr) => ptr.cast(), - Err(_err) => handle_alloc_error(layout), + let size = size * mem::size_of::(); + let layout = Layout::from_size_align(size, 2).unwrap(); + //let layout = Layout::array::(size).unwrap(); + let ptr: *mut u8 = alloc::alloc_zeroed(layout); + let new_ptr: NonNull = match NonNull::new(ptr) { + Some(ptr) => ptr.cast(), + _ => handle_alloc_error(layout), }; new_ptr } @@ -511,6 +514,16 @@ mod tests { // around 30 MB const THIRTY_MB: usize = 2 << 20; +// #[test] +// fn cluster_alloc_size_align() { +// for i in 0..10 { +// let size = 1 << i; +// let layout = Layout::array::(1 << i).unwrap(); +// assert_eq!(layout.align(), 2); +// assert_eq!(layout.size(), mem::size_of::() * size); +// } +// } + #[test] fn tt_alloc_realloc() { let size: usize = 8; From b6499df10ab336205060d0f3f50202b63af00de0 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 17:19:34 -0700 Subject: [PATCH 02/10] Work on allowing stable compilation of `pleco`. Signed-off-by: Stephen Fleischman --- .travis.yml | 1 - pleco/Cargo.toml | 12 ++++--- pleco/src/core/move_list.rs | 9 ++++- pleco/src/lib.rs | 8 ++--- pleco/src/tools/mod.rs | 48 +++++++++++++++++++++++++++ pleco/src/tools/tt.rs | 5 ++- pleco/tests/test.rs | 2 -- pleco_engine/src/tables/material.rs | 6 ++-- pleco_engine/src/tables/pawn_table.rs | 10 +++--- 9 files changed, 75 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index ccaa8ed..474040c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ rust: cache: - - cargo - apt # cache: diff --git a/pleco/Cargo.toml b/pleco/Cargo.toml index f4f6309..784056d 100644 --- a/pleco/Cargo.toml +++ b/pleco/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" categories = ["games","game-engines"] repository = "https://github.com/sfleischman105/Pleco" autobenches = false - +#build = "build.rs" include = [ "src/*", @@ -27,7 +27,6 @@ coveralls = { repository = "sfleischman105/Pleco", branch = "master", service = [lib] name = "pleco" -#bench = true path = "src/lib.rs" doctest = true @@ -61,15 +60,20 @@ bitflags = "1.0.4" rand = "0.6.5" rayon = "1.0.3" num_cpus = "1.10.0" -prefetch = "0.2.0" +#prefetch = "0.2.0" mucow = "0.1.0" lazy_static = "1.3.0" [features] default = [] +nightly = ["criterion/real_blackbox"] [dev-dependencies] -criterion = { version = '0.2.10', default-features = false, features=['real_blackbox'] } +#criterion = { version = '0.2.10', default-features = false, features=['real_blackbox'] } +criterion = { version = '0.2.10', default-features = false } + +#[build-dependencies] +#itertools = {version = "0.8"} [[bench]] name = "bench_main" diff --git a/pleco/src/core/move_list.rs b/pleco/src/core/move_list.rs index 181120e..bb5bd80 100644 --- a/pleco/src/core/move_list.rs +++ b/pleco/src/core/move_list.rs @@ -17,7 +17,10 @@ use std::slice; use std::ops::{Deref,DerefMut,Index,IndexMut}; -use std::iter::{Iterator,IntoIterator,FusedIterator,TrustedLen,ExactSizeIterator,FromIterator}; +use std::iter::{Iterator,IntoIterator,FusedIterator,ExactSizeIterator,FromIterator}; +#[cfg(feature = "nightly")] +use std::iter::TrustedLen; + use super::piece_move::{BitMove, ScoringMove}; pub trait MVPushable: Sized + IndexMut + Index + DerefMut { @@ -307,6 +310,7 @@ impl<'a> ExactSizeIterator for MoveIter<'a> {} impl<'a> FusedIterator for MoveIter<'a> {} +#[cfg(feature = "nightly")] unsafe impl<'a> TrustedLen for MoveIter<'a> {} // Iterator for the `MoveList`. @@ -365,6 +369,7 @@ impl ExactSizeIterator for MoveIntoIter {} impl FusedIterator for MoveIntoIter {} +#[cfg(feature = "nightly")] unsafe impl TrustedLen for MoveIntoIter {} @@ -588,6 +593,7 @@ impl<'a> ExactSizeIterator for ScoreMoveIter<'a> {} impl<'a> FusedIterator for ScoreMoveIter<'a> {} +#[cfg(feature = "nightly")] unsafe impl<'a> TrustedLen for ScoreMoveIter<'a> {} // Iterator for the `ScoringMoveList`. @@ -646,4 +652,5 @@ impl ExactSizeIterator for ScoreMoveIntoIter {} impl FusedIterator for ScoreMoveIntoIter {} +#[cfg(feature = "nightly")] unsafe impl TrustedLen for ScoreMoveIntoIter {} diff --git a/pleco/src/lib.rs b/pleco/src/lib.rs index f651cde..5230567 100644 --- a/pleco/src/lib.rs +++ b/pleco/src/lib.rs @@ -67,9 +67,9 @@ //#![feature(const_fn)] //#![feature(stdsimd)] -// Need these for nightly -#![feature(const_slice_len)] // General Usage -#![feature(trusted_len)] // used in MoveList +#![cfg_attr(feature = "nightly", feature(core_intrinsics))] +#![cfg_attr(feature = "nightly", feature(const_slice_len))] +#![cfg_attr(feature = "nightly", feature(trusted_len))] #![allow(dead_code)] @@ -80,8 +80,6 @@ extern crate lazy_static; extern crate num_cpus; extern crate rand; extern crate rayon; -// This requires nightly, probably should find a better way to prefetch. -extern crate prefetch; extern crate mucow; pub mod core; diff --git a/pleco/src/tools/mod.rs b/pleco/src/tools/mod.rs index 0b45abe..f3015c7 100644 --- a/pleco/src/tools/mod.rs +++ b/pleco/src/tools/mod.rs @@ -8,6 +8,7 @@ pub mod eval; pub mod tt; pub mod pleco_arc; + use core::piece_move::BitMove; use board::Board; @@ -34,3 +35,50 @@ pub trait PreFetchable { self.prefetch(key + 1); } } + +/// Prefetch's `ptr` to all levels of the cache. +pub fn prefetch_write(ptr: *const T) { + __prefetch_write::(ptr); +} + + +#[cfg(feature = "nightly")] +fn __prefetch_write(ptr: *const T) { + use std::intrinsics::prefetch_write_data; + unsafe { + prefetch_write_data::(ptr, 3); + } +} + +#[cfg( + all( + not(feature = "nightly"), + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse" + ) +)] +fn __prefetch_write(ptr: *const T) { + #[cfg(target_arch = "x86")] + use std::arch::x86::_mm_prefetch; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::_mm_prefetch; + unsafe { + _mm_prefetch(ptr as *const i8, 3); + } +} + +#[cfg( + all( + not(feature = "nightly"), + any( + all( + any(target_arch = "x86", target_arch = "x86_64"), + not(target_feature = "sse") + ), + not(any(target_arch = "x86", target_arch = "x86_64")) + ) + ) +)] +fn __prefetch_write(ptr: *const T) { + // Do nothing +} \ No newline at end of file diff --git a/pleco/src/tools/tt.rs b/pleco/src/tools/tt.rs index dd787ea..48ba7cb 100644 --- a/pleco/src/tools/tt.rs +++ b/pleco/src/tools/tt.rs @@ -39,10 +39,9 @@ use std::alloc::{Layout, handle_alloc_error, self}; use std::cmp::min; use std::cell::UnsafeCell; -use prefetch::prefetch::*; - use super::PreFetchable; use core::piece_move::BitMove; +use super::prefetch_write; // TODO: investigate potention for SIMD in key lookup // Currently, there is now way to do this right now in rust without it being extensive. @@ -462,7 +461,7 @@ impl PreFetchable for TranspositionTable { let index: usize = ((self.num_clusters() - 1) as u64 & key) as usize; unsafe { let ptr = (*self.clusters.get()).as_ptr().offset(index as isize); - prefetch::(ptr); + prefetch_write(ptr); }; } } diff --git a/pleco/tests/test.rs b/pleco/tests/test.rs index 9733be7..9de5df6 100644 --- a/pleco/tests/test.rs +++ b/pleco/tests/test.rs @@ -1,7 +1,5 @@ -#![feature(test)] extern crate pleco; -extern crate test; mod board_build; mod move_generating; diff --git a/pleco_engine/src/tables/material.rs b/pleco_engine/src/tables/material.rs index a75bd5b..b5e0dbc 100644 --- a/pleco_engine/src/tables/material.rs +++ b/pleco_engine/src/tables/material.rs @@ -1,12 +1,10 @@ //! Table to map from position -> material value; -use prefetch::prefetch::*; - use pleco::{Player, Board, PieceType}; use pleco::core::masks::{PLAYER_CNT,PIECE_TYPE_CNT}; use pleco::core::score::*; use pleco::core::mono_traits::*; -use pleco::tools::PreFetchable; +use pleco::tools::{PreFetchable, prefetch_write}; use super::{TableBase,TableBaseConst}; @@ -79,7 +77,7 @@ impl PreFetchable for Material { fn prefetch(&self, key: u64) { unsafe { let ptr = self.table.get_ptr(key); - prefetch::(ptr); + prefetch_write(ptr); } } } diff --git a/pleco_engine/src/tables/pawn_table.rs b/pleco_engine/src/tables/pawn_table.rs index b5419ee..176c3fd 100644 --- a/pleco_engine/src/tables/pawn_table.rs +++ b/pleco_engine/src/tables/pawn_table.rs @@ -6,8 +6,6 @@ use std::mem::transmute; -use prefetch::prefetch::*; - use pleco::{Player, File, SQ, BitBoard, Board, PieceType, Rank, Piece}; use pleco::core::masks::{PLAYER_CNT,RANK_CNT}; use pleco::core::score::*; @@ -15,7 +13,7 @@ use pleco::core::mono_traits::*; use pleco::board::castle_rights::Castling; use pleco::core::CastleType; use pleco::helper::prelude::*; -use pleco::tools::PreFetchable; +use pleco::tools::{PreFetchable,prefetch_write}; use super::{TableBase,TableBaseConst}; @@ -185,7 +183,7 @@ impl PreFetchable for PawnTable { fn prefetch(&self, key: u64) { unsafe { let ptr = self.table.get_ptr(key); - prefetch::(ptr); + prefetch_write(ptr); } } @@ -193,9 +191,9 @@ impl PreFetchable for PawnTable { fn prefetch2(&self, key: u64) { unsafe { let ptr = self.table.get_ptr(key); - prefetch::(ptr); + prefetch_write(ptr); let ptr_2 = (ptr as *mut u8).offset(64) as *mut PawnEntry; - prefetch::(ptr_2); + prefetch_write(ptr_2); } } } From 86b8d58c84efa4ff9065ce26d187ca33943894ac Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 17:42:43 -0700 Subject: [PATCH 03/10] Modify some Integrated testing stuff and features Signed-off-by: Stephen Fleischman --- .travis.yml | 4 ++++ pleco/Cargo.toml | 5 ++--- pleco/README.md | 2 +- pleco/benches/perft_benches.rs | 4 ++-- pleco_engine/Cargo.toml | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 474040c..b52e89b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,10 @@ os: script: - cargo build --verbose + - echo " ------ TESTING STABLE BRANCH ------- " + - cargo +stable test --package pleco + - cargo +stable bench --package pleco + - echo " ------ TESTING NIGHTLY BRANCH ------- " - cargo test --verbose - cargo bench # - cd pleco/ && cargo bench diff --git a/pleco/Cargo.toml b/pleco/Cargo.toml index 784056d..8f35328 100644 --- a/pleco/Cargo.toml +++ b/pleco/Cargo.toml @@ -66,11 +66,10 @@ lazy_static = "1.3.0" [features] default = [] -nightly = ["criterion/real_blackbox"] +nightly = [] [dev-dependencies] -#criterion = { version = '0.2.10', default-features = false, features=['real_blackbox'] } -criterion = { version = '0.2.10', default-features = false } +criterion = { version = '0.2.10', default-features = false} #[build-dependencies] #itertools = {version = "0.8"} diff --git a/pleco/README.md b/pleco/README.md index 7b4bdfc..3c6e571 100644 --- a/pleco/README.md +++ b/pleco/README.md @@ -35,7 +35,7 @@ Use ------- To use Pleco inside your own Rust projects, [Pleco.rs is available as a library on crates.io](https://crates.io/crates/pleco). -`nightly` rust is required to use. +Pleco runs on all three distributions (`nightly`, `beta`, `stable`) of rust. ### Basic Usage diff --git a/pleco/benches/perft_benches.rs b/pleco/benches/perft_benches.rs index d9fbb4d..46b1455 100644 --- a/pleco/benches/perft_benches.rs +++ b/pleco/benches/perft_benches.rs @@ -38,8 +38,8 @@ fn perft_all(c: &mut Criterion) { criterion_group!(name = perft_benches; config = Criterion::default() - .sample_size(8) - .warm_up_time(Duration::from_millis(10)); + .sample_size(12) + .warm_up_time(Duration::from_millis(20)); targets = perft_all ); diff --git a/pleco_engine/Cargo.toml b/pleco_engine/Cargo.toml index 7642f5d..b61c0a6 100644 --- a/pleco_engine/Cargo.toml +++ b/pleco_engine/Cargo.toml @@ -57,7 +57,7 @@ path = "src/lib.rs" doctest = true [dependencies] -pleco = { path = "../pleco", version = "0.4.4" } +pleco = { path = "../pleco", version = "*", features =["nightly"]} chrono = "0.4.6" rand = "0.6.5" num_cpus = "1.8.0" From d9822962152c180e5caf453e04a6120d059a71c2 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 17:52:48 -0700 Subject: [PATCH 04/10] travis CI fixes Signed-off-by: Stephen Fleischman --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index b52e89b..37796a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,9 @@ env: # - kalakris-cmake +before_script: + - rustup install stable-x86_64-unknown-linux-gnu + os: - linux From fb27046d362e348f8e39af3e3636e1afc224879b Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 17:58:38 -0700 Subject: [PATCH 05/10] Attempt at travis fixin Signed-off-by: Stephen Fleischman --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 37796a4..cbc00b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ sudo: required env: global: - RUST_BACKTRACE=FULL - - RUSTFLAGS="-Ctarget-cpu=native -Zmutable-noalias" + - RUSTFLAGS="-Ctarget-cpu=native" - RUST_MIN_STACK=8000000 # - RUST_TEST_THREADS=1 @@ -46,7 +46,7 @@ script: - cargo +stable bench --package pleco - echo " ------ TESTING NIGHTLY BRANCH ------- " - cargo test --verbose - - cargo bench + - cargo bench -- -Zmutable-noalias # - cd pleco/ && cargo bench # - cd ../pleco_engine/ && cargo bench --bench eval_benches From 77718a278642dc05ab27bdf07867dd2e639e3f74 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 18:36:06 -0700 Subject: [PATCH 06/10] More travis fixin Signed-off-by: Stephen Fleischman --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cbc00b9..9f8611a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,7 @@ script: - cargo +stable bench --package pleco - echo " ------ TESTING NIGHTLY BRANCH ------- " - cargo test --verbose - - cargo bench -- -Zmutable-noalias + - cargo bench -- -Z mutable-noalias # - cd pleco/ && cargo bench # - cd ../pleco_engine/ && cargo bench --bench eval_benches From 428e79a089e03e27c0fb0516d9e49823ed13c831 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 18:36:29 -0700 Subject: [PATCH 07/10] More travis Signed-off-by: Stephen Fleischman --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9f8611a..feca36b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,7 @@ script: - cargo +stable bench --package pleco - echo " ------ TESTING NIGHTLY BRANCH ------- " - cargo test --verbose - - cargo bench -- -Z mutable-noalias + - cargo bench # - cd pleco/ && cargo bench # - cd ../pleco_engine/ && cargo bench --bench eval_benches From 6fcade1d3739ac4791fdd7c53c94f9533c9adc5b Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 21:18:20 -0700 Subject: [PATCH 08/10] More documentation. changed MAX_MOVES size to be cache aligned. PRNG gives a more random singular bit. Signed-off-by: Stephen Fleischman --- .travis.yml | 2 +- pleco/Cargo.toml | 4 --- pleco/README.md | 11 +++++++ pleco/src/board/board_state.rs | 3 +- pleco/src/board/mod.rs | 6 ++++ pleco/src/board/piece_locations.rs | 2 +- pleco/src/core/bitboard.rs | 22 ++++++++++++-- pleco/src/core/masks.rs | 32 ++++++++++++++++++++ pleco/src/core/move_list.rs | 31 +++++++++++++++----- pleco/src/core/piece_move.rs | 12 +++++++- pleco/src/core/score.rs | 6 ++-- pleco/src/lib.rs | 29 ++++++++++-------- pleco/src/tools/eval.rs | 13 ++++++++- pleco/src/tools/mod.rs | 47 ++++++++++++++++++++++++++++++ pleco/src/tools/prng.rs | 45 ++++++++++++++++++++++++++-- pleco/src/tools/tt.rs | 2 +- pleco_engine/src/root_moves/mod.rs | 3 +- 17 files changed, 232 insertions(+), 38 deletions(-) diff --git a/.travis.yml b/.travis.yml index feca36b..dfbbb33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,7 @@ script: - cargo +stable bench --package pleco - echo " ------ TESTING NIGHTLY BRANCH ------- " - cargo test --verbose - - cargo bench + - cargo bench # - cd pleco/ && cargo bench # - cd ../pleco_engine/ && cargo bench --bench eval_benches diff --git a/pleco/Cargo.toml b/pleco/Cargo.toml index 8f35328..cbc525b 100644 --- a/pleco/Cargo.toml +++ b/pleco/Cargo.toml @@ -60,7 +60,6 @@ bitflags = "1.0.4" rand = "0.6.5" rayon = "1.0.3" num_cpus = "1.10.0" -#prefetch = "0.2.0" mucow = "0.1.0" lazy_static = "1.3.0" @@ -71,9 +70,6 @@ nightly = [] [dev-dependencies] criterion = { version = '0.2.10', default-features = false} -#[build-dependencies] -#itertools = {version = "0.8"} - [[bench]] name = "bench_main" harness = false diff --git a/pleco/README.md b/pleco/README.md index 3c6e571..ff219b3 100644 --- a/pleco/README.md +++ b/pleco/README.md @@ -95,6 +95,17 @@ board.undo_move(); assert_eq!(board.moves_played(),0); ``` +#### Features + +If on nightly rust, the feature `"nightly"` is available. This enables some nightly +optimizations and speed improvements. + +Usage is as easy as updating your `cargo.toml` to include: + +``` +[dependencies] +pleco = {version = "*", features = ["nightly"]} +``` Contributing ------- diff --git a/pleco/src/board/board_state.rs b/pleco/src/board/board_state.rs index 9da207e..f81e06b 100644 --- a/pleco/src/board/board_state.rs +++ b/pleco/src/board/board_state.rs @@ -20,7 +20,6 @@ use core::bitboard::BitBoard; use core::masks::*; use core::score::{Value,Score}; -//use std::sync::Arc; use tools::pleco_arc::Arc; use helper::prelude::*; @@ -156,7 +155,7 @@ impl BoardState { /// /// Specifically, sets Blockers, Pinners, and Check Squares for each piece. /// - /// The `checkers_bb` must beset before this methof can be used. + /// The `checkers_bb` must beset before this method can be used. pub(crate) fn set_check_info(&mut self, board: &Board) { let mut white_pinners: BitBoard = BitBoard(0); diff --git a/pleco/src/board/mod.rs b/pleco/src/board/mod.rs index b1ba54e..9bb3833 100644 --- a/pleco/src/board/mod.rs +++ b/pleco/src/board/mod.rs @@ -1980,6 +1980,12 @@ impl Board { /// `see_ge` stands for Static Exchange Evaluation, Greater or Equal. This teats if the /// Static Exchange Evaluation of a move is greater than or equal to a value. + /// + /// This is a recursive algorithm that works by checking the destination square of + /// the given move, and attempting to repeatedly capture that spot for both players. + /// + /// If the move is invalid for the current board, `false` will be returned regardless + /// of the threshold. pub fn see_ge(&self, mov: BitMove, threshold: i32) -> bool { if mov.move_type() != MoveType::Normal { return 0 >= threshold; diff --git a/pleco/src/board/piece_locations.rs b/pleco/src/board/piece_locations.rs index f6f780e..778cc03 100644 --- a/pleco/src/board/piece_locations.rs +++ b/pleco/src/board/piece_locations.rs @@ -46,7 +46,7 @@ impl PieceLocations { /// /// # Panics /// - /// Panics if Square is of index higher than 63. + /// Panics if Square is of index higher than 63 or the piece is `PieceType::{None || All}` #[inline] pub fn place(&mut self, square: SQ, player: Player, piece: PieceType) { debug_assert!(square.is_okay()); diff --git a/pleco/src/core/bitboard.rs b/pleco/src/core/bitboard.rs index 216acd6..2ea1fb5 100644 --- a/pleco/src/core/bitboard.rs +++ b/pleco/src/core/bitboard.rs @@ -163,6 +163,13 @@ impl BitBoard { /// Returns the index (as a square) of the least significant bit and removes /// that bit from the `BitBoard`. + /// + /// # Safety + /// + /// Panics if the `BitBoard` is empty. See [`BitBoard::pop_some_lsb`] for a + /// non-panicking version of the method. + /// + /// [`BitBoard::pop_some_lsb`]: struct.BitBoard.html#method.pop_some_lsb #[inline(always)] pub fn pop_lsb(&mut self) -> SQ { let sq = self.bit_scan_forward(); @@ -170,7 +177,8 @@ impl BitBoard { sq } - /// Returns the least significant bit of a `BitBoard`, if it has any. + /// Returns the least significant bit of a `BitBoard`, if it has any. If there is a bit to + /// return, it removes that bit from itself. #[inline(always)] pub fn pop_some_lsb(&mut self) -> Option { if self.is_empty() { @@ -182,6 +190,13 @@ impl BitBoard { /// Returns the index (as a square) and bit of the least significant bit and removes /// that bit from the `BitBoard`. + /// + /// # Safety + /// + /// Panics if the `BitBoard` is empty. See [`BitBoard::pop_some_lsb_and_bit`] for a + /// non-panicking version of the method. + /// + /// [`BitBoard::pop_some_lsb_and_bit`]: struct.BitBoard.html#method.pop_some_lsb_and_bit #[inline(always)] pub fn pop_lsb_and_bit(&mut self) -> (SQ, BitBoard) { let sq: SQ = self.bit_scan_forward(); @@ -189,6 +204,9 @@ impl BitBoard { (sq, sq.to_bb()) } + /// Returns the index (as a square) and bit of the least significant bit and removes + /// that bit from the `BitBoard`. If there are no bits left (the board is empty), returns + /// `None`. #[inline(always)] pub fn pop_some_lsb_and_bit(&mut self) -> Option<(SQ, BitBoard)> { if self.is_empty() { @@ -202,7 +220,7 @@ impl BitBoard { /// /// # Safety /// - /// panics if the `BitBoard` is empty. + /// Panics if the `BitBoard` is empty. #[inline] pub fn frontmost_sq(self, player: Player) -> SQ { match player { diff --git a/pleco/src/core/masks.rs b/pleco/src/core/masks.rs index fc95cca..74bff0d 100644 --- a/pleco/src/core/masks.rs +++ b/pleco/src/core/masks.rs @@ -243,6 +243,17 @@ pub static SQ_DISPLAY_ORDER: [u8; SQ_CNT] = [56, 57, 58, 59, 60, 61, 62, 63, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7]; +/// Array mapping a square index to a string representation. +/// +/// # Examples +/// +/// ``` +/// use pleco::core::masks::SQ_DISPLAY; +/// +/// assert_eq!(SQ_DISPLAY[0], "a1"); +/// assert_eq!(SQ_DISPLAY[1], "b1"); +/// assert_eq!(SQ_DISPLAY[8], "a2"); +/// ``` pub static SQ_DISPLAY: [&str; SQ_CNT] = [ "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", @@ -254,13 +265,34 @@ pub static SQ_DISPLAY: [&str; SQ_CNT] = [ "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"]; /// Characters for each combination of player and piece. +/// +/// White pieces are displayed as Uppercase letters, while black pieces are lowercase. pub static PIECE_DISPLAYS: [[char; PIECE_TYPE_CNT]; PLAYER_CNT] = [ ['_', 'P', 'N', 'B', 'R', 'Q', 'K', '*'], ['_', 'p', 'n', 'b', 'r', 'q', 'k', '*'], ]; /// Characters for each file, index from file A to file H. +/// # Examples +/// +/// ``` +/// use pleco::core::masks::FILE_DISPLAYS; +/// +/// assert_eq!(FILE_DISPLAYS[0], "a"); +/// assert_eq!(FILE_DISPLAYS[1], "b"); +/// assert_eq!(FILE_DISPLAYS[7], "h"); +/// ``` pub static FILE_DISPLAYS: [char; FILE_CNT] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; /// Characters for each rank, index from rank 1 to rank 8. +/// +/// # Examples +/// +/// ``` +/// use pleco::core::masks::RANK_DISPLAYS; +/// +/// assert_eq!(RANK_DISPLAYS[0], "1"); +/// assert_eq!(RANK_DISPLAYS[1], "2"); +/// assert_eq!(RANK_DISPLAYS[7], "8"); +/// ``` pub static RANK_DISPLAYS: [char; FILE_CNT] = ['1', '2', '3', '4', '5', '6', '7', '8']; diff --git a/pleco/src/core/move_list.rs b/pleco/src/core/move_list.rs index bb5bd80..c19c093 100644 --- a/pleco/src/core/move_list.rs +++ b/pleco/src/core/move_list.rs @@ -23,6 +23,7 @@ use std::iter::TrustedLen; use super::piece_move::{BitMove, ScoringMove}; +/// Trait to help generalize operations involving sctures containing a collection of `BitMove`s. pub trait MVPushable: Sized + IndexMut + Index + DerefMut { /// Adds a `BitMove` to the end of the list. @@ -36,7 +37,7 @@ pub trait MVPushable: Sized + IndexMut + Index + DerefMut { /// /// # Safety /// - /// Undefined behavior if pushing to the list when `MoveList::len() = 256`. + /// Undefined behavior if pushing to the list when `MoveList::len() = MAX_MOVES`. unsafe fn unchecked_push_mv(&mut self, mv: BitMove); /// Set the length of the list. @@ -47,14 +48,14 @@ pub trait MVPushable: Sized + IndexMut + Index + DerefMut { unsafe fn unchecked_set_len(&mut self, len: usize); - /// Return a pointer to the first (0-th index) element in the list + /// Return a pointer to the first (0-th index) element in the list. /// /// # Safety /// /// Unsafe due to allow modification of elements possibly not inside the length. unsafe fn list_ptr(&mut self) -> *mut Self::Output; - /// Return a pointer to the element next to the last element in the list + /// Return a pointer to the element next to the last element in the list. /// /// # Safety /// @@ -62,12 +63,26 @@ pub trait MVPushable: Sized + IndexMut + Index + DerefMut { unsafe fn over_bounds_ptr(&mut self) -> *mut Self::Output; } -const MAX_MOVES: usize = 256; +/// The maximum number of moves a `MoveList` or `ScoringMoveList` may contain. +/// +/// This value differs based on the `target_pointer_width` to align lists of moves into +/// values equally dividable by the cache size. +#[cfg(target_pointer_width = "128")] +pub const MAX_MOVES: usize = 248; +#[cfg(target_pointer_width = "64")] +pub const MAX_MOVES: usize = 252; +#[cfg(target_pointer_width = "32")] +pub const MAX_MOVES: usize = 254; +#[cfg(any( + target_pointer_width = "16", + target_pointer_width = "8", +))] +pub const MAX_MOVES: usize = 255; /// This is the list of possible moves for a current position. Think of it alike a faster /// version of `Vec`, as all the data is stored in the Stack rather than the Heap. pub struct MoveList { - inner: [BitMove; 256], + inner: [BitMove; MAX_MOVES], len: usize, } @@ -75,7 +90,7 @@ impl Default for MoveList { #[inline] fn default() -> Self { MoveList { - inner: [BitMove::null(); 256], + inner: [BitMove::null(); MAX_MOVES], len: 0, } } @@ -375,7 +390,7 @@ unsafe impl TrustedLen for MoveIntoIter {} /// This is similar to a `MoveList`, but also keeps the scores for each move as well. pub struct ScoringMoveList { - inner: [ScoringMove; 256], + inner: [ScoringMove; MAX_MOVES], len: usize, } @@ -383,7 +398,7 @@ impl Default for ScoringMoveList { #[inline] fn default() -> Self { ScoringMoveList { - inner: [ScoringMove::default(); 256], + inner: [ScoringMove::default(); MAX_MOVES], len: 0, } } diff --git a/pleco/src/core/piece_move.rs b/pleco/src/core/piece_move.rs index 110f3ee..d555878 100644 --- a/pleco/src/core/piece_move.rs +++ b/pleco/src/core/piece_move.rs @@ -466,7 +466,9 @@ impl BitMove { } } -/// A move that stores a score as well +/// Structure containing both a score (represented as a i16) and a `BitMove`. +/// +/// This is useful for tracking a list of moves alongside each of their scores. #[derive(Eq, Copy, Clone, Debug)] #[repr(C)] pub struct ScoringMove { @@ -485,6 +487,7 @@ impl Default for ScoringMove { } impl ScoringMove { + /// Creates a new `ScoringMove` with a default score of 0. #[inline(always)] pub fn new(m: BitMove) -> Self { ScoringMove { @@ -493,6 +496,7 @@ impl ScoringMove { } } + /// Creates a new `ScoringMove`. #[inline(always)] pub fn new_score(m: BitMove, score: i16) -> Self { ScoringMove { @@ -501,6 +505,7 @@ impl ScoringMove { } } + /// Returns a `ScoringMove` containing a `BitMove::null()` and a user-defined score. #[inline(always)] pub fn blank(score: i16) -> Self { ScoringMove { @@ -509,28 +514,33 @@ impl ScoringMove { } } + /// Returns the move. #[inline(always)] pub fn bitmove(&self) -> BitMove { self.bit_move } + /// Returns the score. #[inline(always)] pub fn score(&self) -> i16 { self.score } + /// Negates the current score. #[inline(always)] pub fn negate(mut self) -> Self { self.score = self.score.wrapping_neg(); self } + /// Swaps the current move with another move. #[inline(always)] pub fn swap_move(mut self, mov: BitMove) -> Self { self.bit_move = mov; self } + /// Returns a `ScoringMove` containing a `BitMove::null()` and a score of zero. #[inline(always)] pub const fn null() -> Self { ScoringMove { diff --git a/pleco/src/core/score.rs b/pleco/src/core/score.rs index e6fdb90..42a42aa 100644 --- a/pleco/src/core/score.rs +++ b/pleco/src/core/score.rs @@ -1,12 +1,14 @@ //! Primitives for determining the value / score of a specific location. //! -//! A `Value` stores a single `i16` to represent a score. `Score` stores two `i16`s inside of it, +//! A `Value` stores a single `i32` to represent a score. `Score` stores two `i32`s inside of it, //! the first to determine the mid-game score, and the second to determine the end-game score. use std::ops::*; use std::fmt; -/// Type for `i16` to determine the `Value` of an evaluation. +// TODO: Why is Value an i32 now? Need some notes on why that changed. + +/// Type for `i32` to determine the `Value` of an evaluation. pub type Value = i32; diff --git a/pleco/src/lib.rs b/pleco/src/lib.rs index 5230567..bd912f9 100644 --- a/pleco/src/lib.rs +++ b/pleco/src/lib.rs @@ -1,22 +1,33 @@ -//! A Rust re-write of the basic building blocks of the [Stockfish](https://stockfishchess.org/) -//! chess engine. +//! A blazingly fast chess library. //! //! This package is separated into two parts. Firstly, the board representation & associated functions //! (the current crate, `pleco`), and secondly, the AI implementations using these chess foundations, //! [pleco_engine](https://crates.io/crates/pleco_engine). //! -//! This crate requires *nightly* Rust to use. +//! The general formatting and structure of the library take heavy influence from the basic building +//! blocks of the [Stockfish](https://stockfishchess.org/) chess engine. //! //! # Usage //! //! This crate is [on crates.io](https://crates.io/crates/pleco) and can be //! used by adding `pleco` to the dependencies in your project's `Cargo.toml`. //! +//! # Platforms +//! +//! `pleco` is currently tested and created for use with the `x86_64` instruction set in mind. +//! Currently, there are no guarantees of correct behavior if compiled for a different +//! instruction set. +//! +//! # Nightly Features +//! +//! If on nightly rust, the feature `nightly` is available. This enables some nightly +//! optimizations and speed improvements. +//! //! # Safety //! -//! While generally a safe library, pleco was built with a focus of speed in mind. Usage of methods must be followed -//! carefully, as there are many possible ways to `panic` unexpectedly. Methods with the ability to panic will be -//! documented as such. +//! While generally a safe library, pleco was built with a focus of speed in mind. Usage of methods +//! must be followed carefully, as there are many possible ways to `panic` unexpectedly. Methods +//! with the ability to panic will be documented as such. //! //! # Examples //! @@ -61,12 +72,6 @@ //#![crate_type = "rlib"] -// Unneeded I think -//#![feature(test)] -//#![feature(integer_atomics)] -//#![feature(const_fn)] -//#![feature(stdsimd)] - #![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(feature = "nightly", feature(const_slice_len))] #![cfg_attr(feature = "nightly", feature(trusted_len))] diff --git a/pleco/src/tools/eval.rs b/pleco/src/tools/eval.rs index b3b9355..865b182 100644 --- a/pleco/src/tools/eval.rs +++ b/pleco/src/tools/eval.rs @@ -43,7 +43,18 @@ fn flatten(arr: [[i32; FILE_CNT]; RANK_CNT]) -> [i32; SQ_CNT] { new_arr } -pub struct Eval {} +/// A simple evaluation structure. This is included as an example, and shouldn't +/// neccessarily be used inside serious chess engines. +/// +/// ``` +/// use pleco::tools::eval::Eval; +/// use pleco::Board; +/// +/// let board = Board::start_pos(); +/// let score = Eval::eval_low(&board); +/// println!("Score: {}"); +/// ``` +pub struct Eval; trait EvalRuns { fn eval_castling(&self) -> i32; diff --git a/pleco/src/tools/mod.rs b/pleco/src/tools/mod.rs index f3015c7..64f0138 100644 --- a/pleco/src/tools/mod.rs +++ b/pleco/src/tools/mod.rs @@ -37,12 +37,19 @@ pub trait PreFetchable { } /// Prefetch's `ptr` to all levels of the cache. +/// +/// For some platforms this may compile down to nothing, and be optimized away. +/// To prevent compiling down into nothing, compilation must be done for a +/// `x86` or `x86_64` platform with SSE instructions available. An easy way to +/// do this is to add the environmental variable `RUSTFLAGS=-C target-cpu=native`. +#[inline(always)] pub fn prefetch_write(ptr: *const T) { __prefetch_write::(ptr); } #[cfg(feature = "nightly")] +#[inline(always)] fn __prefetch_write(ptr: *const T) { use std::intrinsics::prefetch_write_data; unsafe { @@ -57,6 +64,7 @@ fn __prefetch_write(ptr: *const T) { target_feature = "sse" ) )] +#[inline(always)] fn __prefetch_write(ptr: *const T) { #[cfg(target_arch = "x86")] use std::arch::x86::_mm_prefetch; @@ -79,6 +87,45 @@ fn __prefetch_write(ptr: *const T) { ) ) )] +#[inline(always)] fn __prefetch_write(ptr: *const T) { // Do nothing +} + +/// Hints to the compiler for optimizations. +/// +/// These functions normally compile down to no-operations without the `nightly` flag. +pub mod hint { + #[cfg(feature = "nightly")] + use std::intrinsics; + + /// Hints to the compiler that branch condition is likely to be false. + /// Returns the value passed to it. + /// + /// Any use other than with `if` statements will probably not have an effect. + #[inline(always)] + pub fn unlikely(cond: bool) -> bool { + #[cfg(feature = "nightly")] + unsafe { + intrinsics::unlikely(cond) + } + #[cfg(not(feature = "nightly"))] + cond + } + + /// Hints to the compiler that branch condition is likely to be true. + /// Returns the value passed to it. + /// + /// Any use other than with `if` statements will probably not have an effect. + #[inline(always)] + pub fn likely(cond: bool) -> bool { + #[cfg(feature = "nightly")] + unsafe { + intrinsics::likely(cond) + } + #[cfg(not(feature = "nightly"))] + cond + } + + } \ No newline at end of file diff --git a/pleco/src/tools/prng.rs b/pleco/src/tools/prng.rs index 764d2a2..b184809 100644 --- a/pleco/src/tools/prng.rs +++ b/pleco/src/tools/prng.rs @@ -1,6 +1,8 @@ //! Contains the Pseudo-random number generator. Used for generating random `Board`s and //! `BitBoard`s. +use std::mem::transmute; + /// Object for generating pseudo-random numbers. pub struct PRNG { seed: u64, @@ -33,8 +35,9 @@ impl PRNG { /// Returns a u64 with exactly one bit set in a random location. pub fn singular_bit(&mut self) -> u64 { - let num: u64 = 1; - num.wrapping_shl(self.rand().count_ones()) + let arr: [u8; 8] = unsafe {transmute(self.rand() ^ self.rand())}; + let byte: u8 = arr.iter().fold(0, |acc, &x| acc ^ x); + (1u64).wrapping_shl(((byte) >> 2) as u32) } /// Randomizes the current seed and returns a random value. @@ -44,4 +47,42 @@ impl PRNG { self.seed ^= self.seed >> 27; self.seed.wrapping_mul(2685_8216_5773_6338_717) } +} + +#[cfg(test)] +mod test { + use super::PRNG; + + const ROUNDS: u32 = 4; + const MUTS: u32 = 32; + + #[test] + fn check_bit_displacement() { + let mut seeder = PRNG::init(10300014); + let mut acc = [0u32; 64]; + for _ in 0..ROUNDS { + let mut prng = PRNG::init(seeder.rand()); + for _ in 0..MUTS { + add_to_bit_counts(prng.singular_bit(), &mut acc); + } + } + + let max = *acc.iter().max().unwrap(); + for (_i, m) in acc.iter_mut().enumerate() { + *m *= 100; + *m /= max; + //println!("{} : {}",_i, m); + } + + let _sum: u32 = acc.iter().sum(); +// println!("avg: {}", _sum / 64); + } + + fn add_to_bit_counts(mut num: u64, acc: &mut [u32; 64]) { + while num != 0 { + let i = num.trailing_zeros(); + acc[i as usize] += 1; + num &= !((1u64) << i); + } + } } \ No newline at end of file diff --git a/pleco/src/tools/tt.rs b/pleco/src/tools/tt.rs index 48ba7cb..be85fb0 100644 --- a/pleco/src/tools/tt.rs +++ b/pleco/src/tools/tt.rs @@ -472,7 +472,7 @@ impl Drop for TranspositionTable { } } -/// Returns the first entry of a cluster +/// Returns the first entry of a cluster. #[inline] unsafe fn cluster_first_entry(cluster: *mut Cluster) -> *mut Entry { (*cluster).entry.get_unchecked_mut(0) as *mut Entry diff --git a/pleco_engine/src/root_moves/mod.rs b/pleco_engine/src/root_moves/mod.rs index ca74df6..1945a06 100644 --- a/pleco_engine/src/root_moves/mod.rs +++ b/pleco_engine/src/root_moves/mod.rs @@ -8,7 +8,8 @@ use std::cmp::Ordering as CmpOrder; use pleco::core::score::*; use pleco::BitMove; -const MAX_MOVES: usize = 256; +// 250 as this fits into 64 byte cache lines easily. +const MAX_MOVES: usize = 250; /// Keeps track of information of a move for the position to be searched. #[derive(Copy, Clone,Eq)] From 1626b6d72eda2e3ba0e7743aca1f708060c4d6d4 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 21:29:42 -0700 Subject: [PATCH 09/10] Change debug_assertions to be conditionally compiled Signed-off-by: Stephen Fleischman --- pleco/src/board/mod.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/pleco/src/board/mod.rs b/pleco/src/board/mod.rs index 9bb3833..5bf3fde 100644 --- a/pleco/src/board/mod.rs +++ b/pleco/src/board/mod.rs @@ -756,11 +756,10 @@ impl Board { } self.state = next_arc_state.shareable(); - if cfg!(debug_assertions) { - self.is_okay().unwrap(); - } else { - assert!(self.is_ok_quick()); - } + #[cfg(debug_assertions)] + self.is_okay().unwrap(); + #[cfg(not(debug_assertions))] + assert!(self.is_ok_quick()); } /// Applies a UCI move to the board. If the move is a valid string representing a UCI move, then @@ -855,11 +854,10 @@ impl Board { self.half_moves -= 1; self.depth -= 1; - if cfg!(debug_assertions) { - self.is_okay().unwrap(); - } else { - assert!(self.is_ok_quick()); - } + #[cfg(debug_assertions)] + self.is_okay().unwrap(); + #[cfg(not(debug_assertions))] + assert!(self.is_ok_quick()); } /// Apply a "Null Move" to the board, essentially swapping the current turn of @@ -920,11 +918,10 @@ impl Board { } self.state = next_arc_state.shareable(); - if cfg!(debug_assertions) { - self.is_okay().unwrap(); - } else { - assert!(self.is_ok_quick()); - } + #[cfg(debug_assertions)] + self.is_okay().unwrap(); + #[cfg(not(debug_assertions))] + assert!(self.is_ok_quick()); } /// Undo a "Null Move" to the Board, returning to the previous state. From 000d81e44114299442657c11b393cee40cf40bad Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 26 Mar 2019 22:45:03 -0700 Subject: [PATCH 10/10] Bug fixes Signed-off-by: Stephen Fleischman --- pleco/src/core/masks.rs | 12 ++++++------ pleco/src/tools/eval.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pleco/src/core/masks.rs b/pleco/src/core/masks.rs index 74bff0d..d4424ab 100644 --- a/pleco/src/core/masks.rs +++ b/pleco/src/core/masks.rs @@ -278,9 +278,9 @@ pub static PIECE_DISPLAYS: [[char; PIECE_TYPE_CNT]; PLAYER_CNT] = [ /// ``` /// use pleco::core::masks::FILE_DISPLAYS; /// -/// assert_eq!(FILE_DISPLAYS[0], "a"); -/// assert_eq!(FILE_DISPLAYS[1], "b"); -/// assert_eq!(FILE_DISPLAYS[7], "h"); +/// assert_eq!(FILE_DISPLAYS[0], 'a'); +/// assert_eq!(FILE_DISPLAYS[1], 'b'); +/// assert_eq!(FILE_DISPLAYS[7], 'h'); /// ``` pub static FILE_DISPLAYS: [char; FILE_CNT] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; @@ -291,8 +291,8 @@ pub static FILE_DISPLAYS: [char; FILE_CNT] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', /// ``` /// use pleco::core::masks::RANK_DISPLAYS; /// -/// assert_eq!(RANK_DISPLAYS[0], "1"); -/// assert_eq!(RANK_DISPLAYS[1], "2"); -/// assert_eq!(RANK_DISPLAYS[7], "8"); +/// assert_eq!(RANK_DISPLAYS[0], '1'); +/// assert_eq!(RANK_DISPLAYS[1], '2'); +/// assert_eq!(RANK_DISPLAYS[7], '8'); /// ``` pub static RANK_DISPLAYS: [char; FILE_CNT] = ['1', '2', '3', '4', '5', '6', '7', '8']; diff --git a/pleco/src/tools/eval.rs b/pleco/src/tools/eval.rs index 865b182..ab3dd80 100644 --- a/pleco/src/tools/eval.rs +++ b/pleco/src/tools/eval.rs @@ -52,7 +52,7 @@ fn flatten(arr: [[i32; FILE_CNT]; RANK_CNT]) -> [i32; SQ_CNT] { /// /// let board = Board::start_pos(); /// let score = Eval::eval_low(&board); -/// println!("Score: {}"); +/// println!("Score: {}", score); /// ``` pub struct Eval;