From ce7a69f85898baa5c3920b3e8f92ddb50059b42c Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Tue, 16 Apr 2019 23:59:31 -0700 Subject: [PATCH 1/7] Clippy lints, prepare for releases Signed-off-by: Stephen Fleischman --- README.md | 2 ++ pleco/README.md | 3 +- pleco/src/board/castle_rights.rs | 8 ++--- pleco/src/board/mod.rs | 8 ++--- pleco/src/core/mod.rs | 30 +++++++++--------- pleco/src/core/piece_move.rs | 54 ++++++++++++++++---------------- pleco_engine/Cargo.toml | 4 +-- pleco_engine/README.md | 7 ++++- 8 files changed, 62 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 01cbd0f..5481056 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ And add the following to a `main.rs` or `lib.rs`: extern crate pleco; ``` +As of version `0.5.0`, the pleco library is available on all three Rust channels (stable, beta, nightly). + ### Basic Usage Setting up a board position is extremely simple. ```rust diff --git a/pleco/README.md b/pleco/README.md index ff219b3..2d05198 100644 --- a/pleco/README.md +++ b/pleco/README.md @@ -34,7 +34,8 @@ Some of the features `pleco` implements: Use ------- -To use Pleco inside your own Rust projects, [Pleco.rs is available as a library on crates.io](https://crates.io/crates/pleco). +To use Pleco inside your own Rust projects, +[Pleco.rs is available as a library on crates.io](https://crates.io/crates/pleco). Pleco runs on all three distributions (`nightly`, `beta`, `stable`) of rust. ### Basic Usage diff --git a/pleco/src/board/castle_rights.rs b/pleco/src/board/castle_rights.rs index 2cddaae..b194cdc 100644 --- a/pleco/src/board/castle_rights.rs +++ b/pleco/src/board/castle_rights.rs @@ -84,7 +84,7 @@ impl Castling { /// Returns if a player can castle for a given side #[inline] - pub fn castle_rights(&self, player: Player, side: CastleType) -> bool { + pub fn castle_rights(self, player: Player, side: CastleType) -> bool { match player { Player::White => { match side { @@ -102,7 +102,7 @@ impl Castling { } #[inline] - pub fn player_can_castle(&self, player: Player) -> Castling { + pub fn player_can_castle(self, player: Player) -> Castling { Castling { bits: self.bits & (Castling::WHITE_ALL.bits >> (2 * player as u16)) } @@ -110,7 +110,7 @@ impl Castling { /// Returns if both players have lost their ability to castle #[inline] - pub fn no_castling(&self) -> bool { + pub fn no_castling(self) -> bool { !self.contains(Castling::WHITE_K) && !self.contains(Castling::WHITE_Q) && !self.contains(Castling::BLACK_K) && @@ -155,7 +155,7 @@ impl Castling { /// Used for FEN Strings, with (`K` | `Q`) representing white castling abilities, /// and (`k` | `q`) representing black castling abilities. If there are no bits set, /// returns a String containing "-". - pub fn pretty_string(&self) -> String { + pub fn pretty_string(self) -> String { if self.no_castling() { "-".to_owned() } else { diff --git a/pleco/src/board/mod.rs b/pleco/src/board/mod.rs index 5bf3fde..bc91866 100644 --- a/pleco/src/board/mod.rs +++ b/pleco/src/board/mod.rs @@ -238,8 +238,8 @@ impl Board { pub fn shallow_clone(&self) -> Board { Board { turn: self.turn, - bbs: self.bbs.clone(), - bbs_player: self.bbs_player.clone(), + bbs: self.bbs, + bbs_player: self.bbs_player, half_moves: self.half_moves, depth: 0, piece_counts: self.piece_counts, @@ -279,8 +279,8 @@ impl Board { pub fn parallel_clone(&self) -> Board { Board { turn: self.turn, - bbs: self.bbs.clone(), - bbs_player: self.bbs_player.clone(), + bbs: self.bbs, + bbs_player: self.bbs_player, half_moves: self.half_moves, depth: self.depth, piece_counts: self.piece_counts, diff --git a/pleco/src/core/mod.rs b/pleco/src/core/mod.rs index 32d4618..2951ecc 100644 --- a/pleco/src/core/mod.rs +++ b/pleco/src/core/mod.rs @@ -75,21 +75,21 @@ impl Player { /// assert_eq!(b.other_player(), Player::White); /// ``` #[inline(always)] - pub fn other_player(&self) -> Player { - !(*self) + pub fn other_player(self) -> Player { + !(self) } /// Returns the relative square from a given square. #[inline(always)] - pub fn relative_square(&self, sq: SQ) -> SQ { + pub fn relative_square(self, sq: SQ) -> SQ { assert!(sq.is_okay()); - sq ^ SQ((*self) as u8 * 56) + sq ^ SQ((self) as u8 * 56) } /// Gets the direction of a pawn push for a given player. #[inline(always)] - pub fn pawn_push(&self) -> i8 { - match *self { + pub fn pawn_push(self) -> i8 { + match self { Player::White => NORTH, Player::Black => SOUTH, } @@ -111,7 +111,7 @@ impl Player { /// assert_eq!(b.relative_rank_of_sq(SQ::A1), Rank::R8); /// ``` #[inline(always)] - pub fn relative_rank_of_sq(&self, sq: SQ) -> Rank { + pub fn relative_rank_of_sq(self, sq: SQ) -> Rank { self.relative_rank(sq.rank()) } @@ -131,8 +131,8 @@ impl Player { /// assert_eq!(b.relative_rank(Rank::R1), Rank::R8); /// ``` #[inline] - pub fn relative_rank(&self, rank: Rank) -> Rank { - let r = (rank as u8) ^ (*self as u8 * 7); + pub fn relative_rank(self, rank: Rank) -> Rank { + let r = (rank as u8) ^ (self as u8 * 7); debug_assert!(r < 8); // ALL_RANKS[((rank as u8) ^ (*self as u8 * 7)) as usize] unsafe { @@ -219,8 +219,8 @@ impl PieceType { /// /// Used for sorting moves. #[inline] - pub fn value(&self) -> i8 { - match *self { + pub fn value(self) -> i8 { + match self { PieceType::P => 1, PieceType::N | PieceType::B => 3, PieceType::R => 5, @@ -250,8 +250,8 @@ impl PieceType { /// Return the lowercase character of a `Piece`. #[inline] - pub fn char_lower(&self) -> char { - match *self { + pub fn char_lower(self) -> char { + match self { PieceType::P => 'p', PieceType::N => 'n', PieceType::B => 'b', @@ -264,8 +264,8 @@ impl PieceType { /// Return the uppercase character of a `Piece`. #[inline] - pub fn char_upper(&self) -> char { - match *self { + pub fn char_upper(self) -> char { + match self { PieceType::P => 'P', PieceType::N => 'N', PieceType::B => 'B', diff --git a/pleco/src/core/piece_move.rs b/pleco/src/core/piece_move.rs index d555878..10e98f4 100644 --- a/pleco/src/core/piece_move.rs +++ b/pleco/src/core/piece_move.rs @@ -267,79 +267,79 @@ impl BitMove { /// /// See `BitMove::null()` for more information on Null moves. #[inline] - pub const fn is_null(&self) -> bool { + pub const fn is_null(self) -> bool { self.data == 0 } /// Returns if a `BitMove` captures an opponent's piece. #[inline(always)] - pub const fn is_capture(&self) -> bool { + pub const fn is_capture(self) -> bool { ((self.data & CP_MASK) >> 14) == 1 } /// Returns if a `BitMove` is a Quiet Move, meaning it is not any of the following: a capture, promotion, castle, or double pawn push. #[inline(always)] - pub const fn is_quiet_move(&self) -> bool { + pub const fn is_quiet_move(self) -> bool { self.flag() == 0 } /// Returns if a `BitMove` is a promotion. #[inline(always)] - pub const fn is_promo(&self) -> bool { + pub const fn is_promo(self) -> bool { (self.data & PR_MASK) != 0 } /// Returns the destination of a `BitMove`. #[inline(always)] - pub const fn get_dest(&self) -> SQ { + pub const fn get_dest(self) -> SQ { SQ(self.get_dest_u8()) } /// Returns the destination of a `BitMove`. #[inline(always)] - pub const fn get_dest_u8(&self) -> u8 { + pub const fn get_dest_u8(self) -> u8 { ((self.data & DST_MASK) >> 6) as u8 } /// Returns the source square of a `BitMove`. #[inline(always)] - pub const fn get_src(&self) -> SQ { + pub const fn get_src(self) -> SQ { SQ(self.get_src_u8()) } /// Returns the source square of a `BitMove`. #[inline(always)] - pub const fn get_src_u8(&self) -> u8 { + pub const fn get_src_u8(self) -> u8 { (self.data & SRC_MASK) as u8 } /// Returns if a `BitMove` is a castle. #[inline(always)] - pub const fn is_castle(&self) -> bool { + pub const fn is_castle(self) -> bool { (self.data >> 13) == 1 } /// Returns if a `BitMove` is a Castle && it is a KingSide Castle. #[inline(always)] - pub const fn is_king_castle(&self) -> bool { + pub const fn is_king_castle(self) -> bool { self.flag() == BitMove::FLAG_KING_CASTLE } /// Returns if a `BitMove` is a Castle && it is a QueenSide Castle. #[inline(always)] - pub const fn is_queen_castle(&self) -> bool { + pub const fn is_queen_castle(self) -> bool { self.flag() == BitMove::FLAG_QUEEN_CASTLE } /// Returns if a `BitMove` is an enpassant capture. #[inline(always)] - pub const fn is_en_passant(&self) -> bool { + pub const fn is_en_passant(self) -> bool { self.flag() == BitMove::FLAG_EP } /// Returns if a `BitMove` is a double push, and if so returns the Destination square as well. #[inline(always)] - pub fn is_double_push(&self) -> (bool, u8) { + pub fn is_double_push(self) -> (bool, u8) { let is_double_push: u8 = self.flag() as u8; match is_double_push { 1 => (true, self.get_dest().0 as u8), @@ -350,7 +350,7 @@ impl BitMove { /// Returns the `Rank` (otherwise known as row) that the destination square of a `BitMove` /// lies on. #[inline(always)] - pub fn dest_row(&self) -> Rank { + pub fn dest_row(self) -> Rank { // ALL_RANKS[(((self.data & DST_MASK) >> 6) as u8 / 8) as usize] self.get_dest().rank() } @@ -358,19 +358,19 @@ impl BitMove { /// Returns the `File` (otherwise known as column) that the destination square of a `BitMove` /// lies on. #[inline(always)] - pub fn dest_col(&self) -> File { + pub fn dest_col(self) -> File { self.get_dest().file() } /// Returns the `Rank` (otherwise known as row) that the from-square of a `BitMove` lies on. #[inline(always)] - pub fn src_row(&self) -> Rank { + pub fn src_row(self) -> Rank { self.get_src().rank() } /// Returns the `File` (otherwise known as column) that the from-square of a `BitMove` lies on. #[inline(always)] - pub fn src_col(&self) -> File { + pub fn src_col(self) -> File { self.get_src().file() } @@ -380,7 +380,7 @@ impl BitMove { /// /// Method should only be used if the [BitMove] is a promotion. Otherwise, Undefined Behavior may result. #[inline(always)] - pub fn promo_piece(&self) -> PieceType { + pub fn promo_piece(self) -> PieceType { match (self.flag()) & 0b0011 { 0 => PieceType::N, 1 => PieceType::B, @@ -393,7 +393,7 @@ impl BitMove { // TODO: Simply with (m >> 4) & 3 /// Returns the `MoveType` of a `BitMove`. #[inline(always)] - pub fn move_type(&self) -> MoveType { + pub fn move_type(self) -> MoveType { if self.is_castle() { return MoveType::Castle; } @@ -411,7 +411,7 @@ impl BitMove { /// Format goes "Source Square, Destination Square, (Promo Piece)". Moving a Queen from A1 to B8 /// will stringify to "a1b8". If there is a pawn promotion involved, the piece promoted to will be /// appended to the end of the string, alike "a7a8q" in the case of a queen promotion. - pub fn stringify(&self) -> String { + pub fn stringify(self) -> String { let src = self.get_src().to_string(); let dst_sq = self.get_dest(); @@ -436,32 +436,32 @@ impl BitMove { /// Returns the raw number representation of the move. #[inline(always)] - pub const fn get_raw(&self) -> u16 { + pub const fn get_raw(self) -> u16 { self.data } /// Returns if the move has an incorrect flag inside, and therefore is invalid. #[inline(always)] - pub fn incorrect_flag(&self) -> bool { + pub fn incorrect_flag(self) -> bool { ((self.flag()) & 0b1110) == 0b0110 } /// Returns the 4 bit flag of the `BitMove`. #[inline(always)] - pub const fn flag(&self) -> u16 { + pub const fn flag(self) -> u16 { self.data >> 12 } /// Returns if the move is within bounds, ala the to and from squares /// are not equal. #[inline(always)] - pub const fn is_okay(&self) -> bool { + pub const fn is_okay(self) -> bool { self.get_dest_u8() != self.get_src_u8() } /// Returns only from "from" and "to" squares of the move. #[inline(always)] - pub const fn from_to(&self) -> u16 { + pub const fn from_to(self) -> u16 { self.data & FROM_TO_MASK } } @@ -516,13 +516,13 @@ impl ScoringMove { /// Returns the move. #[inline(always)] - pub fn bitmove(&self) -> BitMove { + pub fn bitmove(self) -> BitMove { self.bit_move } /// Returns the score. #[inline(always)] - pub fn score(&self) -> i16 { + pub fn score(self) -> i16 { self.score } diff --git a/pleco_engine/Cargo.toml b/pleco_engine/Cargo.toml index b61c0a6..8965119 100644 --- a/pleco_engine/Cargo.toml +++ b/pleco_engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pleco_engine" -version = "0.1.5" +version = "0.1.6" authors = ["Stephen Fleischman "] description = "A blazingly-fast Chess AI." homepage = "https://github.com/sfleischman105/Pleco" @@ -60,7 +60,7 @@ doctest = true pleco = { path = "../pleco", version = "*", features =["nightly"]} chrono = "0.4.6" rand = "0.6.5" -num_cpus = "1.8.0" +num_cpus = "1.10.0" prefetch = "0.2.0" [features] diff --git a/pleco_engine/README.md b/pleco_engine/README.md index 085e7e1..bbd6b69 100644 --- a/pleco_engine/README.md +++ b/pleco_engine/README.md @@ -42,7 +42,12 @@ The compiled program will appear in `./target/release/`. Pleco can now be run with a `./Pleco` on Linux or a `./Pleco.exe` on Windows. - +Rust Toolchain Version +------- + +Currently, `pleco_engine` requires **nightly** rust to use. + + Contributing ------- From 46f6d13d63915445ea20813118153bca9b76a4a5 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Fri, 26 Apr 2019 18:56:52 -0700 Subject: [PATCH 2/7] redo travis file Signed-off-by: Stephen Fleischman --- .travis.yml | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index dfbbb33..d953695 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: rust rust: - nightly - + - stable cache: - cargo @@ -32,23 +32,30 @@ env: # sources: # - kalakris-cmake - -before_script: - - rustup install stable-x86_64-unknown-linux-gnu - os: - linux 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 -# - cd ../pleco_engine/ && cargo bench --bench eval_benches + - if [ "$TRAVIS_RUST_VERSION" == "stable" ]; + then + cargo build --verbose --package pleco; + cargo test --package pleco; + cargo build --package pleco; + else + cargo build --verbose; + cargo test; + cargo bench --package pleco --all-features; + cargo bench --package pleco_engine --all-features; + fi + +# - 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 --package pleco --all-features +# - cargo bench --package pleco_engine --all-features #after_success: # - | From 01ea6067e5e50e62ee787657f86800a660eba43e Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Fri, 26 Apr 2019 19:04:13 -0700 Subject: [PATCH 3/7] Forgot to stable bench Signed-off-by: Stephen Fleischman --- .travis.yml | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index d953695..9af82b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,18 +20,6 @@ env: - RUST_MIN_STACK=8000000 # - RUST_TEST_THREADS=1 - -#addons: -# apt: -# packages: -# - libcurl4-openssl-dev -# - libelf-dev -# - libdw-dev -# - binutils-dev -# - cmake -# sources: -# - kalakris-cmake - os: - linux @@ -40,7 +28,7 @@ script: then cargo build --verbose --package pleco; cargo test --package pleco; - cargo build --package pleco; + cargo bench --package pleco; else cargo build --verbose; cargo test; @@ -56,13 +44,3 @@ script: # - cargo test --verbose # - cargo bench --package pleco --all-features # - cargo bench --package pleco_engine --all-features - -#after_success: -# - | -# if [[ "$TRAVIS_BRANCH" = "master" ]] AND [ "$TRAVIS_PULL_REQUEST" = "false" ] -# then -# cargo install cargo-travis || echo "cargo-travis has been already installed" -# export PATH=$HOME/.cargo/bin:$PATH -# cargo coveralls -# fi -# From 9defad5d230366d954a4b86a05f2148613eb1546 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Fri, 26 Apr 2019 20:04:52 -0700 Subject: [PATCH 4/7] Clippy lints + cleanups Signed-off-by: Stephen Fleischman --- pleco/src/board/board_state.rs | 2 +- pleco/src/board/mod.rs | 4 +- pleco/src/helper/magic.rs | 2 +- pleco/src/helper/mod.rs | 46 +++++------ pleco/src/lib.rs | 4 + pleco_engine/src/consts.rs | 8 +- pleco_engine/src/engine.rs | 12 ++- pleco_engine/src/lib.rs | 5 ++ pleco_engine/src/movepick/mod.rs | 14 ++-- pleco_engine/src/movepick/pick.rs | 6 +- pleco_engine/src/root_moves/mod.rs | 2 +- .../src/root_moves/root_moves_list.rs | 14 +--- pleco_engine/src/search/eval.rs | 2 +- pleco_engine/src/search/mod.rs | 4 +- pleco_engine/src/tables/mod.rs | 2 +- pleco_engine/src/tables/pawn_table.rs | 2 +- pleco_engine/src/threadpool/mod.rs | 77 +++++++++---------- pleco_engine/src/time/time_management.rs | 5 +- pleco_engine/src/uci/options.rs | 2 +- 19 files changed, 103 insertions(+), 110 deletions(-) diff --git a/pleco/src/board/board_state.rs b/pleco/src/board/board_state.rs index f81e06b..55aa890 100644 --- a/pleco/src/board/board_state.rs +++ b/pleco/src/board/board_state.rs @@ -234,7 +234,7 @@ impl BoardState { /// If there was no previous state, returns `None`. #[inline] pub fn get_prev(&self) -> Option> { - (&self).prev.as_ref().cloned() + self.prev.as_ref().cloned() } /// Iterates through all previous `BoardStates` and prints debug information for each. diff --git a/pleco/src/board/mod.rs b/pleco/src/board/mod.rs index bc91866..92abae4 100644 --- a/pleco/src/board/mod.rs +++ b/pleco/src/board/mod.rs @@ -2519,9 +2519,7 @@ impl RandBoard { moves[self.random() % moves.len()] } else if self.random() % 5 == 0 { AlphaBetaSearcher::best_move(board.shallow_clone(),2) - } else if self.random() % 3 == 0 { - AlphaBetaSearcher::best_move(board.shallow_clone(),3) - } else if !favorable && self.random() % 5 < 4 { + } else if self.random() % 3 == 0 || !favorable && self.random() % 5 < 4 { AlphaBetaSearcher::best_move(board.shallow_clone(),3) } else { AlphaBetaSearcher::best_move(board.shallow_clone(),4) diff --git a/pleco/src/helper/magic.rs b/pleco/src/helper/magic.rs index 79df908..deb3d6f 100644 --- a/pleco/src/helper/magic.rs +++ b/pleco/src/helper/magic.rs @@ -238,7 +238,7 @@ unsafe fn gen_magic_board(table_size: usize, deltas: &[i8; 4], static_magics: *m // points to the static entry let staticptr: *mut SMagic = static_magics.offset(i as isize); - let mut table_i: SMagic = SMagic { + let table_i: SMagic = SMagic { ptr: mem::transmute::<*const u64, usize>(beginptr), mask: pre_sq_table[i].mask, magic: pre_sq_table[i].magic, diff --git a/pleco/src/helper/mod.rs b/pleco/src/helper/mod.rs index 6306484..917afba 100644 --- a/pleco/src/helper/mod.rs +++ b/pleco/src/helper/mod.rs @@ -54,7 +54,7 @@ impl Helper { /// This function will return captures to pieces on both sides. The resulting `BitBoard` must be /// AND'd with the inverse of the intending moving player's pieces. #[inline(always)] - pub fn bishop_moves(&self, occupied: BitBoard, sq: SQ) -> BitBoard { + pub fn bishop_moves(self, occupied: BitBoard, sq: SQ) -> BitBoard { prelude::bishop_moves(occupied,sq) } @@ -62,7 +62,7 @@ impl Helper { /// This function will return captures to pieces on both sides. The resulting `BitBoard` must be /// AND'd with the inverse of the intending moving player's pieces. #[inline(always)] - pub fn rook_moves(&self, occupied: BitBoard, sq: SQ) -> BitBoard { + pub fn rook_moves(self, occupied: BitBoard, sq: SQ) -> BitBoard { prelude::rook_moves(occupied,sq) } @@ -70,62 +70,62 @@ impl Helper { /// This function will return captures to pieces on both sides. The resulting `BitBoard` must be /// AND'd with the inverse of the intending moving player's pieces. #[inline(always)] - pub fn queen_moves(&self, occupied: BitBoard, sq: SQ) -> BitBoard { + pub fn queen_moves(self, occupied: BitBoard, sq: SQ) -> BitBoard { prelude::queen_moves(occupied,sq) } /// Generate Knight Moves `BitBoard` from a source square. #[inline(always)] - pub fn knight_moves(&self, sq: SQ) -> BitBoard { + pub fn knight_moves(self, sq: SQ) -> BitBoard { prelude::knight_moves(sq) } /// Generate King moves `BitBoard` from a source square. #[inline(always)] - pub fn king_moves(&self, sq: SQ) -> BitBoard { + pub fn king_moves(self, sq: SQ) -> BitBoard { prelude::king_moves(sq) } /// Get the distance of two squares. #[inline(always)] - pub fn distance_of_sqs(&self, sq_one: SQ, sq_two: SQ) -> u8 { + pub fn distance_of_sqs(self, sq_one: SQ, sq_two: SQ) -> u8 { prelude::distance_of_sqs(sq_one, sq_two) } /// Get the line (diagonal / file / rank) `BitBoard` that two squares both exist on, if it exists. #[inline(always)] - pub fn line_bb(&self, sq_one: SQ, sq_two: SQ) -> BitBoard { + pub fn line_bb(self, sq_one: SQ, sq_two: SQ) -> BitBoard { prelude::line_bb(sq_one, sq_two) } /// Get the line (diagonal / file / rank) `BitBoard` between two squares, not including the squares, if it exists. #[inline(always)] - pub fn between_bb(&self, sq_one: SQ, sq_two: SQ) -> BitBoard { + pub fn between_bb(self, sq_one: SQ, sq_two: SQ) -> BitBoard { prelude::between_bb(sq_one, sq_two) } /// Gets the adjacent files `BitBoard` of the square #[inline(always)] - pub fn adjacent_sq_file(&self, sq: SQ) -> BitBoard { + pub fn adjacent_sq_file(self, sq: SQ) -> BitBoard { prelude::adjacent_sq_file(sq) } /// Gets the adjacent files `BitBoard` of the file #[inline(always)] - pub fn adjacent_file(&self, f: File) -> BitBoard { + pub fn adjacent_file(self, f: File) -> BitBoard { prelude::adjacent_file(f) } /// Pawn attacks `BitBoard` from a given square, per player. /// Basically, given square x, returns the BitBoard of squares a pawn on x attacks. #[inline(always)] - pub fn pawn_attacks_from(&self, sq: SQ, player: Player) -> BitBoard { + pub fn pawn_attacks_from(self, sq: SQ, player: Player) -> BitBoard { prelude::pawn_attacks_from(sq,player) } /// Returns if three Squares are in the same diagonal, file, or rank. #[inline(always)] - pub fn aligned(&self, s1: SQ, s2: SQ, s3: SQ) -> bool { + pub fn aligned(self, s1: SQ, s2: SQ, s3: SQ) -> bool { prelude::aligned(s1,s2,s3) } @@ -135,13 +135,13 @@ impl Helper { /// /// distance must be less than 8, or else a panic will occur. #[inline(always)] - pub fn ring_distance(&self, sq: SQ, distance: u8) -> BitBoard { + pub fn ring_distance(self, sq: SQ, distance: u8) -> BitBoard { prelude::ring_distance(sq,distance) } /// Returns the BitBoard of all squares in the rank in front of the given one. #[inline(always)] - pub fn forward_rank_bb(&self, player: Player, rank: Rank) -> BitBoard { + pub fn forward_rank_bb(self, player: Player, rank: Rank) -> BitBoard { prelude::forward_rank_bb(player,rank) } @@ -155,7 +155,7 @@ impl Helper { /// /// The Square must be within normal bounds, or else a panic or undefined behvaior may occur. #[inline(always)] - pub fn pawn_attacks_span(&self, player: Player, sq: SQ) -> BitBoard { + pub fn pawn_attacks_span(self, player: Player, sq: SQ) -> BitBoard { prelude::pawn_attacks_span(player,sq) } @@ -165,7 +165,7 @@ impl Helper { /// /// The Square must be within normal bounds, or else a panic or undefined behvaior may occur. #[inline(always)] - pub fn forward_file_bb(&self, player: Player, sq: SQ) -> BitBoard { + pub fn forward_file_bb(self, player: Player, sq: SQ) -> BitBoard { prelude::forward_file_bb(player,sq) } @@ -176,44 +176,44 @@ impl Helper { /// /// The Square must be within normal bounds, or else a panic or undefined behvaior may occur. #[inline(always)] - pub fn passed_pawn_mask(&self, player: Player, sq: SQ) -> BitBoard { + pub fn passed_pawn_mask(self, player: Player, sq: SQ) -> BitBoard { prelude::passed_pawn_mask(player, sq) } /// Returns the zobrist hash of a specific player's piece being at a particular square. #[inline(always)] - pub fn z_square(&self, sq: SQ, piece: Piece) -> u64 { + pub fn z_square(self, sq: SQ, piece: Piece) -> u64 { prelude::z_square(sq, piece) } /// Returns the zobrist hash of a given file having an en-passant square. #[inline(always)] - pub fn z_ep(&self, sq: SQ) -> u64 { + pub fn z_ep(self, sq: SQ) -> u64 { prelude::z_ep(sq) } /// Returns a zobrist hash of the castling rights, as defined by the Board. #[inline(always)] - pub fn z_castle(&self, castle: u8) -> u64 { + pub fn z_castle(self, castle: u8) -> u64 { prelude::z_castle(castle) } /// Returns Zobrist Hash of flipping sides. #[inline(always)] - pub fn z_side(&self) -> u64 { + pub fn z_side(self) -> u64 { prelude::z_side() } /// Returns the score for a player's piece being at a particular square. #[inline(always)] - pub fn psq(&self, piece: Piece, sq: SQ) -> Score { + pub fn psq(self, piece: Piece, sq: SQ) -> Score { prelude::psq(piece, sq) } /// Returns the value of a piece for a player. If `eg` is true, it returns the end game value. Otherwise, /// it'll return the midgame value. #[inline(always)] - pub fn piece_value(&self, piece: Piece, eg: bool) -> Value { + pub fn piece_value(self, piece: Piece, eg: bool) -> Value { prelude::piece_value(piece, eg) } } diff --git a/pleco/src/lib.rs b/pleco/src/lib.rs index bd912f9..8a2941b 100644 --- a/pleco/src/lib.rs +++ b/pleco/src/lib.rs @@ -70,12 +70,16 @@ #![cfg_attr(feature = "dev", allow(unstable_features))] #![cfg_attr(test, allow(dead_code))] + //#![crate_type = "rlib"] #![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(feature = "nightly", feature(const_slice_len))] #![cfg_attr(feature = "nightly", feature(trusted_len))] +#![allow(clippy::cast_lossless)] +#![allow(clippy::unreadable_literal)] + #![allow(dead_code)] #[macro_use] diff --git a/pleco_engine/src/consts.rs b/pleco_engine/src/consts.rs index 1f66b8b..4e9a8e9 100644 --- a/pleco_engine/src/consts.rs +++ b/pleco_engine/src/consts.rs @@ -56,7 +56,7 @@ pub fn init_globals() { #[cold] fn init_tt() { unsafe { - let tt: *mut TranspositionTable = mem::transmute(&mut TT_TABLE); + let tt = &mut TT_TABLE as *mut DummyTranspositionTable as *mut TranspositionTable; ptr::write(tt, TranspositionTable::new(DEFAULT_TT_SIZE)); } } @@ -65,7 +65,7 @@ fn init_tt() { #[cold] fn init_timer() { unsafe { - let timer: *mut TimeManager = mem::transmute(&mut TIMER); + let timer: *mut TimeManager = &mut TIMER as *mut DummyTimeManager as *mut TimeManager; ptr::write(timer, TimeManager::uninitialized()); } } @@ -73,7 +73,7 @@ fn init_timer() { // Returns access to the global timer pub fn timer() -> &'static TimeManager { unsafe { - mem::transmute(&TIMER) + &*(&TIMER as *const DummyTimeManager as *const TimeManager) } } @@ -81,7 +81,7 @@ pub fn timer() -> &'static TimeManager { #[inline(always)] pub fn tt() -> &'static TranspositionTable { unsafe { - mem::transmute(&TT_TABLE) + &*(&TT_TABLE as *const DummyTranspositionTable as *const TranspositionTable) } } diff --git a/pleco_engine/src/engine.rs b/pleco_engine/src/engine.rs index 8bd0eb5..1545067 100644 --- a/pleco_engine/src/engine.rs +++ b/pleco_engine/src/engine.rs @@ -50,7 +50,7 @@ impl PlecoSearcher { pub fn uci(&mut self) { self.uci_startup(); let mut full_command = String::new(); - 'main: loop { + loop { full_command.clear(); io::stdin().read_line(&mut full_command).ok().unwrap(); let args: Vec<&str> = full_command.split_whitespace().collect(); @@ -183,18 +183,16 @@ impl PlecoSearcher { threadpool().wait_for_finish(); threadpool().best_move() } else { - return BitMove::null(); + BitMove::null() } } pub fn await_move(&mut self) -> BitMove { if self.is_searching() { - return { - threadpool().wait_for_finish(); - threadpool().best_move() - } + threadpool().wait_for_finish(); + threadpool().best_move() } else { - return BitMove::null(); + BitMove::null() } } diff --git a/pleco_engine/src/lib.rs b/pleco_engine/src/lib.rs index 1ae34a6..f7949b8 100644 --- a/pleco_engine/src/lib.rs +++ b/pleco_engine/src/lib.rs @@ -10,6 +10,11 @@ #![cfg_attr(test, allow(dead_code))] #![allow(dead_code)] +#![allow(clippy::cast_lossless)] +#![allow(clippy::unreadable_literal)] +#![allow(clippy::cast_ptr_alignment)] +#![allow(clippy::mut_from_ref)] +#![allow(clippy::cognitive_complexity)] #![feature(ptr_internals)] #![feature(integer_atomics)] diff --git a/pleco_engine/src/movepick/mod.rs b/pleco_engine/src/movepick/mod.rs index 82eebfc..0ce7581 100644 --- a/pleco_engine/src/movepick/mod.rs +++ b/pleco_engine/src/movepick/mod.rs @@ -40,7 +40,7 @@ impl MovePicker { cap_hist: &CapturePieceToHistory, cont_hist: *const [*const PieceToHistory; 4], mut ttm: BitMove, - killers: &[BitMove; 2], counter_move: BitMove) -> Self { + killers: [BitMove; 2], counter_move: BitMove) -> Self { assert!(depth > 0); let mut pick = if board.in_check() {Pick::EvasionSearch} else {Pick::MainSearch}; @@ -58,13 +58,13 @@ impl MovePicker { moves, depth, ttm, - killers: (*killers).clone(), + killers, cm: counter_move, recapture_sq: unsafe {mem::uninitialized()}, threshold: unsafe {mem::uninitialized()}, - main_hist: main_hist, + main_hist, capture_hist: cap_hist, - cont_hist: cont_hist, + cont_hist, cur_ptr: first, end_ptr: first, end_bad_captures: first, @@ -91,7 +91,7 @@ impl MovePicker { cm: unsafe { mem::uninitialized() }, recapture_sq: unsafe { mem::uninitialized() }, threshold: unsafe {mem::uninitialized()}, - main_hist: main_hist, + main_hist, capture_hist: cap_hist, cont_hist: unsafe {mem::uninitialized()}, cur_ptr: first, @@ -565,7 +565,7 @@ mod tests { #[test] fn movepick_rand_mainsearch() { for _x in 0..15 { - let mut b = Board::random().one(); + let b = Board::random().one(); movepick_rand_one(b); println!("pass movepick rand! {} ",_x); } @@ -724,7 +724,7 @@ mod tests { &cont_hist3 as *const _, &cont_hist4 as *const _]; let mut mp = MovePicker::main_search(&b, depth, &main_hist, &cap_hist, &cont_hist as *const _, - ttm, &killers, cm); + ttm, *killers, cm); let mut mp_next = mp.next_mov( false); while mp_next != BitMove::null() { diff --git a/pleco_engine/src/movepick/pick.rs b/pleco_engine/src/movepick/pick.rs index 3a05617..f58b32c 100644 --- a/pleco_engine/src/movepick/pick.rs +++ b/pleco_engine/src/movepick/pick.rs @@ -37,8 +37,8 @@ impl Pick { unsafe {*self = mem::transmute(*self as u8 + 1); } } - pub fn to_string(&self) -> &'static str { - match *self { + pub fn to_string(self) -> &'static str { + match self { Pick::MainSearch => "MainSearch", Pick::CapturesInit => "CapturesInit", Pick::GoodCaptures => "GoodCaptures", @@ -66,7 +66,7 @@ impl Pick { impl fmt::Display for Pick { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(self.to_string()) + f.pad(&self.to_string()) } } diff --git a/pleco_engine/src/root_moves/mod.rs b/pleco_engine/src/root_moves/mod.rs index 1945a06..a50de3e 100644 --- a/pleco_engine/src/root_moves/mod.rs +++ b/pleco_engine/src/root_moves/mod.rs @@ -26,7 +26,7 @@ impl RootMove { #[inline] pub fn new(bit_move: BitMove) -> Self { RootMove { - bit_move: bit_move, + bit_move, score: NEG_INFINITE as i32, prev_score: NEG_INFINITE as i32, depth_reached: 0, diff --git a/pleco_engine/src/root_moves/root_moves_list.rs b/pleco_engine/src/root_moves/root_moves_list.rs index 3044dd5..a3bb68d 100644 --- a/pleco_engine/src/root_moves/root_moves_list.rs +++ b/pleco_engine/src/root_moves/root_moves_list.rs @@ -4,8 +4,6 @@ use std::ops::{Deref,DerefMut,Index,IndexMut}; use std::iter::{Iterator,IntoIterator,FusedIterator,TrustedLen,ExactSizeIterator}; use std::ptr; use std::mem; - -use std::mem::transmute; use std::sync::atomic::{Ordering,AtomicUsize}; use pleco::{MoveList, BitMove}; @@ -51,8 +49,8 @@ impl RootMoveList { pub fn clone_from_other(&mut self, other: &RootMoveList) { self.len.store(other.len(), Ordering::SeqCst); unsafe { - let self_moves: *mut [RootMove; MAX_MOVES] = transmute::<*mut RootMove, *mut [RootMove; MAX_MOVES]>(self.moves.as_mut_ptr()); - let other_moves: *const [RootMove; MAX_MOVES] = transmute::<*const RootMove, *const [RootMove; MAX_MOVES]>(other.moves.as_ptr()); + let self_moves: *mut [RootMove; MAX_MOVES] = self.moves.as_mut_ptr() as *mut [RootMove; MAX_MOVES]; + let other_moves: *const [RootMove; MAX_MOVES] = other.moves.as_ptr() as *const [RootMove; MAX_MOVES]; ptr::copy_nonoverlapping(other_moves, self_moves, 1); } } @@ -117,12 +115,8 @@ impl RootMoveList { } pub fn find(&mut self, mov: BitMove) -> Option<&mut RootMove> { - for m in self.iter_mut() { - if m.bit_move == mov { - return Some(m); - } - } - None + self.iter_mut() + .find(|m| m.bit_move == mov) } } diff --git a/pleco_engine/src/search/eval.rs b/pleco_engine/src/search/eval.rs index 401d005..0c4f4df 100644 --- a/pleco_engine/src/search/eval.rs +++ b/pleco_engine/src/search/eval.rs @@ -985,7 +985,7 @@ impl <'a, 'b, T: Tracing> EvaluationInner<'a, 'b, T> { trace.add_one(EvalPasses::Initiative, Score(0, v)); } - return Score(0, v); + Score(0, v) } fn scale_factor(&self, eg: i32) -> u8 { diff --git a/pleco_engine/src/search/mod.rs b/pleco_engine/src/search/mod.rs index 4248f92..b54dddb 100644 --- a/pleco_engine/src/search/mod.rs +++ b/pleco_engine/src/search/mod.rs @@ -441,7 +441,7 @@ impl Searcher { // Main thread only from here on! // check for time - if let Some(_) = self.limit.use_time_management() { + if self.limit.use_time_management().is_some() { if !self.stop() { let score_diff: i32 = best_value - self.previous_score; @@ -687,7 +687,7 @@ impl Searcher { &self.capture_history, &cont_hists as *const _, tt_move, - &ss.killers, + ss.killers, counter); singular_extension_node = !at_root diff --git a/pleco_engine/src/tables/mod.rs b/pleco_engine/src/tables/mod.rs index 1c95366..667f0ba 100644 --- a/pleco_engine/src/tables/mod.rs +++ b/pleco_engine/src/tables/mod.rs @@ -43,7 +43,7 @@ pub trait StatBoard: Sized + IndexMut let num: usize = mem::size_of::() / mem::size_of::(); unsafe { - let ptr: *mut T = mem::transmute(self as *mut Self); + let ptr: *mut T = self as *mut Self as *mut T; for i in 0..num { ptr::write(ptr.add(i), val); } diff --git a/pleco_engine/src/tables/pawn_table.rs b/pleco_engine/src/tables/pawn_table.rs index 176c3fd..ca23033 100644 --- a/pleco_engine/src/tables/pawn_table.rs +++ b/pleco_engine/src/tables/pawn_table.rs @@ -192,7 +192,7 @@ impl PreFetchable for PawnTable { unsafe { let ptr = self.table.get_ptr(key); prefetch_write(ptr); - let ptr_2 = (ptr as *mut u8).offset(64) as *mut PawnEntry; + let ptr_2 = (ptr as *mut u8).offset(64) as *const PawnEntry; prefetch_write(ptr_2); } } diff --git a/pleco_engine/src/threadpool/mod.rs b/pleco_engine/src/threadpool/mod.rs index c2859f8..eb03ec9 100644 --- a/pleco_engine/src/threadpool/mod.rs +++ b/pleco_engine/src/threadpool/mod.rs @@ -63,6 +63,24 @@ pub fn threadpool() -> &'static mut ThreadPool { } } +#[derive(Copy, Clone)] +enum ThreadSelection { + Main, + NonMain, + All +} + +impl ThreadSelection { + #[inline(always)] + pub fn is_selection(self, id: usize) -> bool { + match self { + ThreadSelection::Main => id == 0, + ThreadSelection::NonMain => id != 0, + ThreadSelection::All => true + } + } +} + // Dummy struct to allow us to pass a pointer into a spawned thread. struct SearcherPtr { ptr: UnsafeCell<*mut Searcher> @@ -163,7 +181,7 @@ impl ThreadPool { fn main(&mut self) -> &mut Searcher { unsafe { let main_thread: *mut Searcher = *self.threads.get_unchecked(0).get(); - return &mut *main_thread; + &mut *main_thread } } @@ -199,17 +217,12 @@ impl ThreadPool { // tell each thread to drop self.threads.iter() .map(|s| &**s.get()) - .for_each(|s: &Searcher| { - s.kill.store(true, Ordering::SeqCst) - }); + .for_each(|s: &Searcher| { s.kill.store(true, Ordering::SeqCst) }); // If awaiting a signal, wake up each thread so each can drop self.threads.iter() .map(|s| &**s.get()) - .for_each(|s: &Searcher| { - s.cond.set(); - }); - + .for_each(|s: &Searcher| { s.cond.set(); }); // Start connecting each join handle. We don't unwrap here, as if one of the // threads fail, the other threads remain un-joined. @@ -240,53 +253,35 @@ impl ThreadPool { /// Waits for all the threads to finish pub fn wait_for_finish(&self) { - unsafe { - self.threads.iter() - .map(|t| &**t.get()) - .for_each(|t| t.searching.await(false)); - } + self.await_search_cond(ThreadSelection::All, false); } /// Waits for all the threads to start. pub fn wait_for_start(&self) { - unsafe { - self.threads.iter() - .map(|t| &**t.get()) - .for_each(|t| t.searching.await(true)); - } + self.await_search_cond(ThreadSelection::All, true); } /// Waits for all non-main threads to finish. pub fn wait_for_non_main(&self) { - unsafe { - self.threads.iter() - .map(|s| &**s.get()) - .for_each(|t: &Searcher|{ - if t.id != 0 { - t.searching.await(false); - } - }); - } + self.await_search_cond(ThreadSelection::NonMain, true); } /// Waits for all the non-main threads to start running pub fn wait_for_main_start(&self) { - unsafe { - self.threads.iter() - .map(|s| &**s.get()) - .for_each(|t: &Searcher|{ - if t.id == 0 { - t.searching.await(true); - } - }); - } + self.await_search_cond(ThreadSelection::Main, true); + } + + fn await_search_cond(&self, thread_sel: ThreadSelection, await_search: bool) { + self.threads.iter() + .map(|s| unsafe {&**s.get()}) + .filter(|t| thread_sel.is_selection(t.id)) + .for_each(|t: &Searcher|{ t.searching.await(await_search); }); } pub fn clear_all(&mut self) { - for thread_ptr in self.threads.iter_mut() { - let mut thread: &mut Searcher = unsafe { &mut **(*thread_ptr).get() }; - thread.clear(); - } + self.threads.iter_mut() + .map(|thread_ptr| unsafe { &mut **(*thread_ptr).get() }) + .for_each(|t| t.clear()); } /// Starts a UCI search. The result will be printed to stdout if the stdout setting @@ -307,7 +302,7 @@ impl ThreadPool { self.stop.store(false, Ordering::Relaxed); for thread_ptr in self.threads.iter_mut() { - let mut thread: &mut Searcher = unsafe {&mut **(*thread_ptr).get()}; + let thread: &mut Searcher = unsafe {&mut **(*thread_ptr).get()}; thread.nodes.store(0, Ordering::Relaxed); thread.depth_completed = 0; thread.board = board.shallow_clone(); diff --git a/pleco_engine/src/time/time_management.rs b/pleco_engine/src/time/time_management.rs index 0f983e4..deb4988 100644 --- a/pleco_engine/src/time/time_management.rs +++ b/pleco_engine/src/time/time_management.rs @@ -83,7 +83,7 @@ impl TimeManager { // We calculate optimum time usage for different hypothetical "moves to go"-values // and choose the minimum of calculated search time values. Usually the greatest // hypMTG gives the minimum values. - for hyp_mtg in 1..(max_mtg + 1) { + for hyp_mtg in 1..=max_mtg { let mut hyp_my_time: i64 = my_time + my_inc * (hyp_mtg - 1) - MOVE_OVERHEAD * (2 + hyp_mtg.min(40)); @@ -108,8 +108,7 @@ impl TimeManager { pub fn start(&self) -> Instant { unsafe { - let start = &*self.start.get(); - start.clone() + *self.start.get() } } diff --git a/pleco_engine/src/uci/options.rs b/pleco_engine/src/uci/options.rs index 7a5c4c6..6271056 100644 --- a/pleco_engine/src/uci/options.rs +++ b/pleco_engine/src/uci/options.rs @@ -76,7 +76,7 @@ impl OptionsMap { }; Box::new(UCIButton { option_name: "Clear Hash", - mutator: mutator + mutator }) } From 11fad3d50946d64304783e6492cfaee7566baf28 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Fri, 26 Apr 2019 20:46:12 -0700 Subject: [PATCH 5/7] Bug fix Signed-off-by: Stephen Fleischman --- pleco_engine/src/threadpool/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pleco_engine/src/threadpool/mod.rs b/pleco_engine/src/threadpool/mod.rs index eb03ec9..11ccbf2 100644 --- a/pleco_engine/src/threadpool/mod.rs +++ b/pleco_engine/src/threadpool/mod.rs @@ -263,7 +263,7 @@ impl ThreadPool { /// Waits for all non-main threads to finish. pub fn wait_for_non_main(&self) { - self.await_search_cond(ThreadSelection::NonMain, true); + self.await_search_cond(ThreadSelection::NonMain, false); } /// Waits for all the non-main threads to start running From ae4b46fff9f5c866684fb5f3184ed29b1c9bd82d Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Fri, 26 Apr 2019 21:18:09 -0700 Subject: [PATCH 6/7] Turn off travis sudo Signed-off-by: Stephen Fleischman --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9af82b6..7e678c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,11 +7,8 @@ rust: cache: - cargo - apt -# cache: -# directories: -# - $HOME/.cache/pip -sudo: required +sudo: false env: global: From 7122ae552507abd3853c5ad6ed37cc36637a0831 Mon Sep 17 00:00:00 2001 From: Stephen Fleischman Date: Fri, 26 Apr 2019 22:25:45 -0700 Subject: [PATCH 7/7] modify Cargo.tomls Signed-off-by: Stephen Fleischman --- pleco/Cargo.toml | 2 +- pleco_engine/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pleco/Cargo.toml b/pleco/Cargo.toml index cbc525b..53f9c43 100644 --- a/pleco/Cargo.toml +++ b/pleco/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pleco" -version = "0.4.4" +version = "0.5.0" authors = ["Stephen Fleischman "] description = "A blazingly-fast chess library." homepage = "https://github.com/sfleischman105/Pleco" diff --git a/pleco_engine/Cargo.toml b/pleco_engine/Cargo.toml index 8965119..83192ee 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 = "*", features =["nightly"]} +pleco = { path = "../pleco", version = "0.5.0", features =["nightly"]} chrono = "0.4.6" rand = "0.6.5" num_cpus = "1.10.0"