Skip to content

Commit

Permalink
Add more asserts
Browse files Browse the repository at this point in the history
  • Loading branch information
Tearth committed Sep 28, 2024
1 parent e5288c4 commit a9637d9
Show file tree
Hide file tree
Showing 20 changed files with 75 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/bin/inanis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ pub fn main() {
let args = env::args_os().collect();
let target_features = get_target_features();

movegen::init();
see::init();
movegen::init();

terminal::run(args, target_features);
}
Expand Down
2 changes: 1 addition & 1 deletion src/cache/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ impl CountermovesTable {
/// Adds countermove `r#move` as response to `previous_move`.
pub fn add(&mut self, previous_move: Move, r#move: Move) {
assert_fast!(previous_move.is_some());
assert_fast!(r#move.is_some());
assert_fast!(previous_move.get_from() < 64);
assert_fast!(previous_move.get_to() < 64);
assert_fast!(r#move.is_some());

self.table[previous_move.get_from()][previous_move.get_to()].r#move = r#move;
}
Expand Down
2 changes: 2 additions & 0 deletions src/cache/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ impl HistoryTable {
pub fn get(&self, from: usize, to: usize, max: u8) -> u8 {
assert_fast!(from < 64);
assert_fast!(to < 64);
assert_fast!(max > 0);
assert_fast!(self.max > 0);

(self.table[from][to].data * (max as u32)).div_ceil_stable(self.max) as u8
}
Expand Down
1 change: 0 additions & 1 deletion src/cache/pawns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::mem;
use std::sync::atomic::AtomicI16;
use std::sync::atomic::AtomicU16;
use std::sync::atomic::Ordering;
use std::u64;

pub struct PawnHashTable {
pub table: Vec<PawnHashTableEntry>,
Expand Down
8 changes: 6 additions & 2 deletions src/cache/perft.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::utils::assert_fast;
use crate::utils::percent;
use std::mem;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
use std::u64;

const BUCKET_SLOTS: usize = 4;

Expand Down Expand Up @@ -42,8 +42,9 @@ impl PerftHashTable {
/// Adds a new entry (storing `hash`, `depth` and `leafs_count`) using `hash` to calculate an index of the bucket.
pub fn add(&self, hash: u64, depth: u8, leafs_count: u64) {
let index = self.get_index(hash);
let bucket = &self.table[index];
assert_fast!(index < self.table.len());

let bucket = &self.table[index];
let mut smallest_depth = u8::MAX;
let mut smallest_depth_index = 0;

Expand All @@ -61,6 +62,7 @@ impl PerftHashTable {
let key = (hash & !0xf) | (depth as u64);
let data = leafs_count;

assert_fast!(smallest_depth_index < BUCKET_SLOTS);
bucket.entries[smallest_depth_index].key.store(key ^ data, Ordering::Relaxed);
bucket.entries[smallest_depth_index].data.store(data, Ordering::Relaxed);
}
Expand All @@ -69,6 +71,8 @@ impl PerftHashTable {
/// Returns [None] if `hash` is incompatible with the stored key.
pub fn get(&self, hash: u64, depth: u8) -> Option<PerftHashTableResult> {
let index = self.get_index(hash);
assert_fast!(index < self.table.len());

let bucket = &self.table[index];

for entry in &bucket.entries {
Expand Down
1 change: 0 additions & 1 deletion src/cache/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::utils::percent;
use std::mem;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
use std::u64;

const BUCKET_SLOTS: usize = 8;

Expand Down
2 changes: 2 additions & 0 deletions src/engine/movesort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub fn sort_next_move(
let mut best_index = start_index;

for index in (start_index + 1)..moves_count {
assert_fast!(index < MAX_MOVES_COUNT);

let score = unsafe { move_scores[index].assume_init() };
if score > best_score {
best_score = score;
Expand Down
1 change: 1 addition & 0 deletions src/engine/qsearch/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::mem::MaybeUninit;
/// - futility pruning (<https://www.chessprogramming.org/Delta_Pruning>)
pub fn run(context: &mut SearchContext, ply: u16, mut alpha: i16, beta: i16) -> i16 {
assert_fast!(alpha <= beta);
assert_fast!(context.board.active_color < 2);

context.statistics.q_nodes_count += 1;
context.statistics.max_ply = cmp::max(ply, context.statistics.max_ply);
Expand Down
15 changes: 10 additions & 5 deletions src/engine/search/movepick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ pub fn get_next_move(
killer_moves_cache: &mut [MaybeUninit<Move>; 2],
) -> Option<(Move, i16)> {
assert_fast!(*move_index < MAX_MOVES_COUNT);
assert_fast!(move_index <= moves_count);
assert_fast!(move_number <= moves_count);
assert_fast!(*move_index <= *moves_count);
assert_fast!(*move_number <= *moves_count);
assert_fast!(*moves_count < MAX_MOVES_COUNT);
assert_fast!(*quiet_moves_start_index < MAX_MOVES_COUNT);
assert_fast!(quiet_moves_start_index <= moves_count);
assert_fast!(*quiet_moves_start_index <= *moves_count);
assert_fast!(context.board.active_color < 2);

if matches!(*stage, MoveGenStage::HashMove | MoveGenStage::Captures | MoveGenStage::Killers | MoveGenStage::Counters | MoveGenStage::AllGenerated) {
*move_index += 1;
Expand Down Expand Up @@ -147,6 +148,8 @@ pub fn get_next_move(
for (index, &killer_move) in killer_moves.iter().enumerate() {
if killer_move != hash_move {
if ((1u64 << killer_move.get_to()) & *evasion_mask) != 0 && killer_move.is_legal(&context.board) {
assert_fast!(*moves_count < MAX_MOVES_COUNT);

moves[*moves_count].write(killer_move);
move_scores[*moves_count].write(MOVE_ORDERING_KILLER_MOVE_1 - (index as i16));
*moves_count += 1;
Expand Down Expand Up @@ -193,6 +196,8 @@ pub fn get_next_move(

if countermove != hash_move && countermove != killer_1 && countermove != killer_2 {
if ((1u64 << countermove.get_to()) & *evasion_mask) != 0 && countermove.is_legal(&context.board) {
assert_fast!(*moves_count < MAX_MOVES_COUNT);

moves[*moves_count].write(countermove);
move_scores[*moves_count].write(MOVE_ORDERING_COUNTERMOVE);
*moves_count += 1;
Expand Down Expand Up @@ -258,7 +263,7 @@ fn assign_capture_scores(
) {
assert_fast!(start_index < MAX_MOVES_COUNT);
assert_fast!(start_index <= moves_count);
assert_fast!(start_index + moves_count < MAX_MOVES_COUNT);
assert_fast!(moves_count < MAX_MOVES_COUNT);

let mut attackers_cache = [0; 64];
let mut defenders_cache = [0; 64];
Expand Down Expand Up @@ -316,7 +321,7 @@ fn assign_quiet_scores(
) {
assert_fast!(start_index < MAX_MOVES_COUNT);
assert_fast!(start_index <= moves_count);
assert_fast!(start_index + moves_count < MAX_MOVES_COUNT);
assert_fast!(moves_count < MAX_MOVES_COUNT);

let killer_moves = context.killers_table.get(ply);
let countermove = context.countermoves_table.get(previous_move);
Expand Down
4 changes: 3 additions & 1 deletion src/engine/search/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ fn run_internal<const ROOT: bool, const PV: bool>(
}

if context.forced_depth == 0 && context.max_nodes_count == 0 && (context.statistics.nodes_count & 8191) == 0 {
if context.search_time_start.elapsed().unwrap().as_millis() > context.deadline as u128 {
if unsafe { context.search_time_start.elapsed().unwrap_unchecked().as_millis() } > context.deadline as u128 {
context.abort_flag.store(true, Ordering::Relaxed);
return INVALID_SCORE;
}
Expand Down Expand Up @@ -392,6 +392,8 @@ fn run_internal<const ROOT: bool, const PV: bool>(

if move_generator_stage == MoveGenStage::AllGenerated {
for i in quiet_moves_start_index..moves_count {
assert_fast!(moves_count < MAX_MOVES_COUNT);

let move_from_list = unsafe { moves[i].assume_init() };
if move_from_list.is_quiet() && move_from_list != best_move {
context.history_table.punish(move_from_list.get_from(), move_from_list.get_to(), depth as u8);
Expand Down
3 changes: 2 additions & 1 deletion src/engine/see.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pub fn get(attacking_piece: usize, target_piece: usize, attackers: usize, defend
let target_piece_index = get_see_piece_index(target_piece);
let updated_attackers = attackers & !(1 << attacking_piece_index);

let see = SEE_TABLE.get().unwrap()[attacking_piece][defenders][updated_attackers];
let table = unsafe { SEE_TABLE.get().unwrap_unchecked() };
let see = table[attacking_piece][defenders][updated_attackers];
(get_piece_value(target_piece_index) - see) as i16 * 50
}

Expand Down
1 change: 1 addition & 0 deletions src/evaluation/pst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub fn get_pst_value(piece: usize, king_square: usize, square: usize) -> PackedE
_ => panic_fast!("Invalid value: piece={}", piece),
};

assert_fast!(KING_BUCKETS[63 - king_square] < KING_BUCKETS_COUNT);
pst[KING_BUCKETS[63 - king_square]][63 - square]
}

Expand Down
1 change: 0 additions & 1 deletion src/perft/divided.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::cache::perft::PerftHashTable;
use crate::state::representation::Board;
use std::mem::MaybeUninit;
use std::sync::Arc;
use std::u64;

/// Entry point of the fixed-`depth` divided perft, which performs a separate perfts for every possible move in the position specified by `board`.
/// Returns a map with the long notation moves as the key, and calculated nodes count as the associated value.
Expand Down
1 change: 0 additions & 1 deletion src/perft/fast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::mem::MaybeUninit;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::u64;

/// Entry point of the fixed-`depth` fast perft, which uses both hashtable (with size specified in `hashtable_size`) and multithreading (with `threads_count` threads).
/// Returns calculated nodes count as the first value, and approximated hashtable usage as the second value.
Expand Down
1 change: 0 additions & 1 deletion src/perft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::engine;
use crate::state::*;
use crate::utils::panic_fast;
use std::mem::MaybeUninit;
use std::u64;

pub mod context;
pub mod divided;
Expand Down
1 change: 0 additions & 1 deletion src/perft/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::cache::perft::PerftHashTable;
use crate::perft::context::PerftContext;
use crate::state::representation::Board;
use std::sync::Arc;
use std::u64;

pub struct NormalPerftResult {
pub nodes: u64,
Expand Down
28 changes: 28 additions & 0 deletions src/state/movescan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ pub fn scan_piece_moves<const PIECE: usize, const CAPTURES: bool>(
mut index: usize,
evasion_mask: u64,
) -> usize {
assert_fast!(board.active_color < 2);

let enemy_color = board.active_color ^ 1;
let mut pieces_bb = board.pieces[board.active_color][PIECE];

Expand All @@ -393,6 +395,8 @@ pub fn scan_piece_moves<const PIECE: usize, const CAPTURES: bool>(
}

while piece_moves_bb != 0 {
assert_fast!(index < engine::MAX_MOVES_COUNT);

let to_bb = piece_moves_bb.get_lsb();
let to = to_bb.bit_scan();
piece_moves_bb = piece_moves_bb.pop_lsb();
Expand All @@ -407,6 +411,8 @@ pub fn scan_piece_moves<const PIECE: usize, const CAPTURES: bool>(
if PIECE == KING && !CAPTURES {
match board.active_color {
WHITE => {
assert_fast!(index < engine::MAX_MOVES_COUNT);

let king_side_castling_rights = board.state.castling_rights.contains(CastlingRights::WHITE_SHORT_CASTLING);
if king_side_castling_rights && (occupancy_bb & (F1_BB | G1_BB)) == 0 {
if !board.are_squares_attacked(board.active_color, &[E1, F1, G1]) {
Expand All @@ -415,6 +421,8 @@ pub fn scan_piece_moves<const PIECE: usize, const CAPTURES: bool>(
}
}

assert_fast!(index < engine::MAX_MOVES_COUNT);

let queen_side_castling_rights = board.state.castling_rights.contains(CastlingRights::WHITE_LONG_CASTLING);
if queen_side_castling_rights && (occupancy_bb & (B1_BB | C1_BB | D1_BB)) == 0 {
if !board.are_squares_attacked(board.active_color, &[C1, D1, E1]) {
Expand All @@ -424,6 +432,8 @@ pub fn scan_piece_moves<const PIECE: usize, const CAPTURES: bool>(
}
}
BLACK => {
assert_fast!(index < engine::MAX_MOVES_COUNT);

let king_side_castling_rights = board.state.castling_rights.contains(CastlingRights::BLACK_SHORT_CASTLING);
if king_side_castling_rights && (occupancy_bb & (F8_BB | G8_BB)) == 0 {
if !board.are_squares_attacked(board.active_color, &[E8, F8, G8]) {
Expand All @@ -432,6 +442,8 @@ pub fn scan_piece_moves<const PIECE: usize, const CAPTURES: bool>(
}
}

assert_fast!(index < engine::MAX_MOVES_COUNT);

let queen_side_castling_rights = board.state.castling_rights.contains(CastlingRights::BLACK_LONG_CASTLING);
if queen_side_castling_rights && (occupancy_bb & (B8_BB | C8_BB | D8_BB)) == 0 {
if !board.are_squares_attacked(board.active_color, &[C8, D8, E8]) {
Expand Down Expand Up @@ -517,6 +529,8 @@ pub fn scan_pawn_moves<const CAPTURES: bool>(
/// and returns index of the first free slot. Use `evasion_mask` with value different than `u64::MAX` to restrict generator to the
/// specified squares (useful during checks).
fn scan_pawn_moves_single_push(board: &Board, moves: &mut [MaybeUninit<Move>; engine::MAX_MOVES_COUNT], mut index: usize, evasion_mask: u64) -> usize {
assert_fast!(board.active_color < 2);

let pieces_bb = board.pieces[board.active_color][PAWN];
let occupancy_bb = board.occupancy[WHITE] | board.occupancy[BLACK];

Expand All @@ -538,12 +552,16 @@ fn scan_pawn_moves_single_push(board: &Board, moves: &mut [MaybeUninit<Move>; en
target_squares_bb = target_squares_bb.pop_lsb();

if (to_bb & promotion_rank_bb) != 0 {
assert_fast!(index + 3 < engine::MAX_MOVES_COUNT);

moves[index + 0].write(Move::new(from, to, MoveFlags::QUEEN_PROMOTION));
moves[index + 1].write(Move::new(from, to, MoveFlags::ROOK_PROMOTION));
moves[index + 2].write(Move::new(from, to, MoveFlags::BISHOP_PROMOTION));
moves[index + 3].write(Move::new(from, to, MoveFlags::KNIGHT_PROMOTION));
index += 4;
} else {
assert_fast!(index < engine::MAX_MOVES_COUNT);

moves[index].write(Move::new(from, to, MoveFlags::SINGLE_PUSH));
index += 1;
}
Expand All @@ -556,6 +574,8 @@ fn scan_pawn_moves_single_push(board: &Board, moves: &mut [MaybeUninit<Move>; en
/// and returns index of the first free slot. Use `evasion_mask` with value different than `u64::MAX` to restrict generator to the
/// specified squares (useful during checks).
fn scan_pawn_moves_double_push(board: &Board, moves: &mut [MaybeUninit<Move>; engine::MAX_MOVES_COUNT], mut index: usize, evasion_mask: u64) -> usize {
assert_fast!(board.active_color < 2);

let pieces_bb = board.pieces[board.active_color][PAWN];
let occupancy_bb = board.occupancy[WHITE] | board.occupancy[BLACK];

Expand All @@ -570,6 +590,8 @@ fn scan_pawn_moves_double_push(board: &Board, moves: &mut [MaybeUninit<Move>; en
target_squares_bb &= !occupancy_bb & evasion_mask;

while target_squares_bb != 0 {
assert_fast!(index < engine::MAX_MOVES_COUNT);

let to_bb = target_squares_bb.get_lsb();
let to = to_bb.bit_scan();
let from = ((to as i8) - shift) as usize;
Expand All @@ -591,6 +613,8 @@ fn scan_pawn_moves_diagonal_attacks<const DIR: usize>(
mut index: usize,
evasion_mask: u64,
) -> usize {
assert_fast!(board.active_color < 2);

let enemy_color = board.active_color ^ 1;
let pieces_bb = board.pieces[board.active_color][PAWN];

Expand All @@ -615,12 +639,16 @@ fn scan_pawn_moves_diagonal_attacks<const DIR: usize>(
target_squares_bb = target_squares_bb.pop_lsb();

if (to_bb & promotion_rank_bb) != 0 {
assert_fast!(index + 3 < engine::MAX_MOVES_COUNT);

moves[index + 0].write(Move::new(from, to, MoveFlags::QUEEN_PROMOTION_CAPTURE));
moves[index + 1].write(Move::new(from, to, MoveFlags::ROOK_PROMOTION_CAPTURE));
moves[index + 2].write(Move::new(from, to, MoveFlags::BISHOP_PROMOTION_CAPTURE));
moves[index + 3].write(Move::new(from, to, MoveFlags::KNIGHT_PROMOTION_CAPTURE));
index += 4;
} else {
assert_fast!(index < engine::MAX_MOVES_COUNT);

let en_passant = (to_bb & board.state.en_passant) != 0;
let flags = if en_passant { MoveFlags::EN_PASSANT } else { MoveFlags::CAPTURE };

Expand Down
Loading

0 comments on commit a9637d9

Please sign in to comment.