Compare commits

..

4 Commits

Author SHA1 Message Date
Varga Dávid Lajos
7e64a7ca16 fixed incorrect test parameter in bitboard::legality::tests::check_test_test 2025-11-18 16:20:42 +01:00
Varga Dávid Lajos
6e0efc76f3 added missing method place_piece to struct bitboard::Board 2025-11-18 16:18:19 +01:00
Varga Dávid Lajos
1a9d7ad460 added tests for method bitboard::legality::check_test 2025-11-18 16:15:28 +01:00
Varga Dávid Lajos
9209f1c4e0 implemented method check_test in bitboard::checktest.rs 2025-11-18 12:14:22 +01:00
6 changed files with 97 additions and 129 deletions

View File

@@ -3,7 +3,5 @@ mod utils;
mod legality;
mod checkinfo;
mod attacks;
mod bitmove;
mod movebuffer;
pub mod board;

View File

@@ -1,77 +0,0 @@
use super::utils::*;
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct BitMove {
move_type: BitMoveType,
from_square: u8,
to_square: u8,
promotion_piece: Option<u8>
}
impl BitMove {
#[inline]
pub fn quiet(from: u8, to: u8, promotion_piece: Option<u8>) -> Self {
return Self {
move_type: BitMoveType::Quiet,
from_square: from,
to_square: to,
promotion_piece: promotion_piece
};
}
#[inline]
pub fn capture(from: u8, to: u8, promotion_piece: Option<u8>) -> Self {
return Self {
move_type: BitMoveType::Capture,
from_square: from,
to_square: to,
promotion_piece: promotion_piece
};
}
#[inline]
pub fn castle(from: u8, to: u8) -> Self {
return Self {
move_type: BitMoveType::Castle,
from_square: from,
to_square: to,
promotion_piece: None
};
}
#[inline(always)]
pub fn move_type(&self) -> BitMoveType {
return self.move_type;
}
#[inline(always)]
pub fn from_square(&self) -> u8 {
return self.from_square;
}
#[inline(always)]
pub fn to_square(&self) -> u8 {
return self.to_square;
}
#[inline(always)]
pub fn promotion_piece(&self) -> Option<u8> {
return self.promotion_piece;
}
pub fn uci_notation(&self) -> String {
let mut notation = notation_from_square_number(self.from_square());
notation.push_str(&notation_from_square_number(self.to_square()));
if let Some(promotion_piece) = self.promotion_piece {
notation.push(get_character_by_piece_id(promotion_piece).to_ascii_lowercase());
}
return notation;
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum BitMoveType {
Quiet,
Capture,
Castle,
EnPassant
}

View File

@@ -64,7 +64,7 @@ impl Board {
for (i, c) in coming_up.chars().enumerate() {
if pieces.contains(&c) {
// board.place_piece(row*8 + col, c);
board.place_piece(row*8 + col, c);
col += 1;
}
else if ('1'..='8').contains(&c) {
@@ -179,4 +179,21 @@ impl Board {
}
}
pub fn place_piece(&mut self, sq: i32, piece: char) {
match piece {
'p' => {self.bitboards[6] |= 1 << sq}
'n' => {self.bitboards[7] |= 1 << sq}
'b' => {self.bitboards[8] |= 1 << sq}
'r' => {self.bitboards[9] |= 1 << sq}
'q' => {self.bitboards[10] |= 1 << sq}
'k' => {self.bitboards[11] |= 1 << sq}
'P' => {self.bitboards[0] |= 1 << sq}
'N' => {self.bitboards[1] |= 1 << sq}
'B' => {self.bitboards[2] |= 1 << sq}
'R' => {self.bitboards[3] |= 1 << sq}
'Q' => {self.bitboards[4] |= 1 << sq}
'K' => {self.bitboards[5] |= 1 << sq}
_ => ()
}
}
}

View File

@@ -1,8 +1,56 @@
use super::board::Board;
use super::attackmaps::RAY_TABLE;
use super::checkinfo::CheckInfo;
use super::attacks::get_raycast_from_square_in_direction;
impl Board {
pub fn check_test(&self) -> CheckInfo {
let mut check_info: CheckInfo = CheckInfo::new();
let offset: usize = 6 * self.side_to_move as usize;
let king: u64 = self.bitboards[5 + offset];
let king_sq = king.trailing_zeros() as usize;
let occupancy = self.occupancy[2];
// queen-rook checks (+)
let attacker_mask = self.bitboards[10 - offset] | self.bitboards[9 - offset];
for dir in [0, 2, 4, 6] {
let threat_mask: u64 = get_raycast_from_square_in_direction(occupancy, king_sq, dir);
if threat_mask & attacker_mask != 0 {
check_info.add_checker(threat_mask);
}
}
// queen-bishop checks (x)
let attacker_mask = self.bitboards[10 - offset] | self.bitboards[8 - offset];
for dir in [1, 3, 5, 7] {
let threat_mask = get_raycast_from_square_in_direction(occupancy, king_sq, dir);
if threat_mask & attacker_mask != 0 {
check_info.add_checker(threat_mask);
}
}
// knight checks (L)
let attacker_mask = self.bitboards[7 - offset];
let threat_mask = self.get_pseudo_knight_moves(king_sq as u32);
let checker = threat_mask & attacker_mask;
if checker != 0 {
check_info.add_checker(checker);
}
// pawn checks (v)
let attacker_mask = self.bitboards[6 - offset];
let threat_mask = self.get_pseudo_pawn_captures(king_sq as u32);
let checker = threat_mask & attacker_mask;
if checker != 0 {
check_info.add_checker(checker);
}
return check_info;
}
pub(in super) fn calc_pinned_squares(&mut self) {
self.pinned_squares = [4; 64];
self.pin_mask = 0u64;
@@ -45,4 +93,35 @@ impl Board {
}
}
}
// <----- TESTS ----->
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_test_test() {
let fens = [
"rnb1k1nr/pppppppp/4q3/8/1b6/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", // no check
"rnb1k1nr/pppppppp/4q3/8/1b1P4/8/PPP1PPPP/RNBQKBNR w KQkq d3 0 1", // single check
"rnb1k1nr/ppp1p2p/3pq1p1/8/1b1P1P2/8/PPP2PPP/RNBQKBNR w KQkq - 0 1" // double check
];
let expected_results = [
CheckInfo { check_count: 0, move_mask: 0xFFFF_FFFF_FFFF_FFFF },
CheckInfo { check_count: 1, move_mask: 0x0000_0000_0204_0800 },
CheckInfo { check_count: 2, move_mask: 0x0000_0000_0000_0000 }
];
for test_nr in 0..3 {
let fen = fens[test_nr];
let board = Board::build(fen);
let check_test_actual = board.check_test();
assert_eq!(check_test_actual.check_count, expected_results[test_nr].check_count);
assert_eq!(check_test_actual.move_mask, expected_results[test_nr].move_mask);
}
}
}

View File

@@ -1,44 +0,0 @@
use super::bitmove::BitMove;
pub struct MoveBuffer {
buffer: [BitMove; 256],
count: usize
}
impl MoveBuffer {
pub fn new() -> Self {
return Self {
buffer: [BitMove::quiet(0, 0, None); 256],
count: 0
};
}
#[inline]
pub fn add(&mut self, bitmove: BitMove) {
self.buffer[self.count] = bitmove;
self.count += 1;
}
#[inline]
pub fn append(&mut self, other: &MoveBuffer) {
self.buffer[self.count..self.count + other.count()].copy_from_slice(other.contents());
self.count += other.count();
}
#[inline(always)]
pub fn clear(&mut self) {
self.count = 0;
}
#[inline(always)]
pub fn count(&self) -> usize{
return self.count;
}
#[inline(always)]
pub fn get(&self, idx: usize) -> &BitMove {
return &self.buffer[idx];
}
#[inline(always)]
pub fn contents(&self) -> &[BitMove] {
return &self.buffer[0..self.count];
}
}

View File

@@ -48,11 +48,6 @@ pub fn try_get_square_number_from_notation(notation: &str) -> Result<u8, ()> {
}
}
const PIECE_CHARACTERS: [char; 12] = ['P', 'N', 'B', 'R', 'Q', 'K', 'p', 'n', 'b', 'r', 'q', 'k'];
pub fn get_character_by_piece_id(id: u8) -> char {
return PIECE_CHARACTERS[id as usize];
}
// <----- TESTS ----->