Skip to main content

syd_format/
filter.rs

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