Skip to main content

syd_format/
filter.rs

1
2use montyformat::chess::Attacks;
3use crate::position::{PieceType, Position};
4
5#[derive(Clone, Copy)]
6pub struct Filter{
7    pub min_depth: u8,
8    // bound condition
9    pub require_exact: bool,
10    // bestmove conditions
11    pub require_bm: bool,
12    pub filter_check: bool,
13    pub filter_tactical: bool,
14    pub filter_castling: bool,
15
16    // pieces condition
17    pub min_pieces: u32,
18
19    // eval condition
20    pub max_eval: u16,
21}
22
23impl Default for Filter {
24    fn default() -> Self {
25        Self {
26            min_depth: 5,
27            require_exact: false,
28            require_bm: false,
29            filter_check: true,
30            filter_tactical: true,
31            filter_castling: false,
32            min_pieces: 4,
33            max_eval: 20000,
34        }
35    }
36}
37
38impl Filter {
39    pub fn nofilter() -> Self {
40        Self {
41            min_depth: 0,
42            require_exact: false,
43            require_bm: false,
44            filter_check: false,
45            filter_tactical: false,
46            filter_castling: false,
47            min_pieces: 0,
48            max_eval: u16::MAX,
49        }
50    }
51    pub fn should_filter(
52        &self,
53        pos: &Position
54    ) -> bool {
55        let occ: u64 = pos.bbs[0] | pos.bbs[1];
56        if pos.depth < self.min_depth {
57            return true;
58        }
59        if self.require_exact && pos.bound != 0 {
60            return true;
61        }
62        if self.require_bm && pos.bm == 0 {
63            return true;
64        }
65        if pos.score.unsigned_abs() >= self.max_eval {
66            return true;
67        }
68        if occ.count_ones() < self.min_pieces {
69            return true;
70        }
71        if self.filter_tactical && pos.bm != 0 {
72            let to: u8 = ((pos.bm >> 6) & 0x3f) as u8;
73            let flag: u8 = (pos.bm >> 14) as u8;
74            if (occ & (1 << to as u64)) != 0 || flag == 3 || flag == 1 {
75                return true;
76            }
77        }
78        if self.filter_check {
79            let kingpos = (pos.bbs[PieceType::King as usize + 2] & pos.bbs[pos.stm as usize]).trailing_ones();
80            let attacks: u64 = 
81                (
82                    (Attacks::pawn(kingpos as usize, pos.stm as usize) & pos.bbs[2]) |
83                    (Attacks::knight(kingpos as usize) & pos.bbs[3]) |
84                    (Attacks::bishop(kingpos as usize, occ) & pos.bbs[4]) |
85                    (Attacks::rook(kingpos as usize, occ) & pos.bbs[5]) |
86                    (Attacks::queen(kingpos as usize, occ) & pos.bbs[6])
87                ) & pos.bbs[pos.stm as usize ^ 1];
88            if attacks != 0 {
89                return true;
90            }
91
92        }
93        return false;
94    }
95}