Skip to main content

syd_format/
reader.rs

1use crate::position::{
2    PieceType, Pieces, Position
3};
4use crate::filter::Filter;
5#[cfg(feature = "readerstats")]
6use crate::stats::ReaderStat;
7#[cfg(feature = "positionstats")]
8use crate::stats::Stats;
9use std::io::{Cursor, Read};
10use bulletformat::ChessBoard;
11
12pub struct SydGame{
13    #[cfg(feature = "readerstats")]
14    pub readerstat: ReaderStat,
15    #[cfg(feature = "positionstats")]
16    pub posstats: Stats,
17    #[cfg(feature = "compress")]
18    last_score: i16,
19}
20impl SydGame {
21    pub fn new() -> Self{
22        Self{
23            #[cfg(feature = "readerstats")]
24            readerstat:ReaderStat::new(),
25            #[cfg(feature = "positionstats")]
26            posstats:Stats::new(),
27            #[cfg(feature = "compress")]
28            last_score: 0,
29        }
30    }
31    pub fn parse_tree<R: std::io::Read>(&mut self, cursor: &mut R, out: &mut Vec<ChessBoard>, pos:&mut Position, filter: &Filter){
32        let mut buff: [u8; 2] = [0; 2];
33
34        cursor.read_exact(&mut buff).unwrap();
35        let bm: u16 = u16::from_le_bytes(buff);
36
37        cursor.read_exact(&mut buff).unwrap();
38        let score: i16 = i16::from_le_bytes(buff);
39
40        cursor.read_exact(&mut buff).unwrap();
41        let info = buff[0];
42        let nb_child = buff[1];
43
44        pos.bm = bm;
45        pos.bound = info%3;
46        pos.depth = info/3;
47        pos.score = score;
48
49        #[cfg(feature = "compress")]
50        let sizescorediff = ((pos.score as i64 - self.last_score as i64).abs() as u64).next_power_of_two().ilog2() as u64 + 1;
51
52        if !filter.should_filter(pos) {
53            #[cfg(feature = "positionstats")]
54            self.posstats.update(pos);
55            out.push(pos.tobullet());
56        }
57        #[cfg(feature = "readerstats")]
58        let mut is_bm_continued = false;
59        for _id_child in 0..nb_child {
60            cursor.read_exact(&mut buff).unwrap();
61            let mv: u16 = u16::from_le_bytes(buff);
62            #[cfg(feature = "readerstats")]
63            if mv == bm {
64                is_bm_continued = true;
65            }
66            let mut newpos: Position = *pos;
67            
68            newpos.play(mv);
69            #[cfg(feature = "compress")]
70            {
71            self.last_score = -pos.score;
72            }
73            self.parse_tree(cursor, out, &mut newpos, filter);
74        }
75        #[cfg(feature = "compress")]
76        {
77        let size_move: u64 =
78            17 +                                                    // bound + branch + move to get this position
79            5 +                             // depth
80            9 * !is_bm_continued as u64 + // bm of the position
81            sizescorediff +  // score
82            ((nb_child.max(2) as u64 - 2).next_power_of_two().ilog2() as u64+3) * (nb_child > 1) as u64;      // number of childs
83        self.readerstat.update(nb_child as usize, is_bm_continued, size_move);
84        }
85        #[cfg(all(not(feature = "compress"), feature = "readerstats"))]
86        {
87            self.readerstat.update(nb_child as usize, is_bm_continued, 0);
88        }
89    }
90
91    pub fn parse_syd<R: std::io::Read>(&mut self, reader: &mut R, res: &mut Vec<ChessBoard>, filter: &Filter) -> std::io::Result<()>{
92
93        #[cfg(feature = "compress")]
94        {
95            self.last_score = 0;
96        }
97
98        let mut buff_4: [u8; 4] = [0; 4];
99        reader.read_exact(&mut buff_4)?;
100        let size:u32 = u32::from_le_bytes(buff_4);
101
102        res.reserve_exact((size as usize-38)/8+1);
103
104        let mut full = Vec::<u8>::new();
105        full.resize(size as usize, 0);
106        assert!(full.len() == size as usize);
107        reader.read_exact(&mut full).unwrap();
108
109        let mut c = Cursor::new(full);
110        let mut marlin: [u8; 32] = [0; 32];
111        c.read_exact(&mut marlin).unwrap();
112        
113        let mut startpos: Position = Position::default();
114        let occupancy = u64::from_le_bytes(marlin[..8].try_into().unwrap());
115        let mut mask = occupancy;
116        for id_piece in 0..occupancy.count_ones() {
117            let pos = mask.trailing_zeros();
118            let mut piece = Pieces::from_viri((marlin[(8+id_piece/2) as usize] >> 4 * (id_piece%2)) & 0b1111);
119            //println!("piece={}", piece);
120            if piece.piecetype() == PieceType::Castle {
121                startpos.update_castle_rights(pos as usize);
122                piece = Pieces::from_pc_color(PieceType::Rook, piece.color());
123            }
124            startpos.push(pos, piece);
125
126            mask &= mask - 1;
127        }
128        let stmep = marlin[24];
129        let mut epsquare = stmep & 0b1111111;
130        let stm: bool = (stmep >> 7) != 0;
131        if epsquare != 64 {
132            if stm {
133                epsquare += 8;
134            } else {
135                epsquare -= 8;
136            }
137        }
138        startpos.update_ep(epsquare as usize);
139        startpos.update_stm(stm as usize);
140        startpos.rule50 = marlin[25];
141        self.parse_tree(&mut c, res, &mut startpos, filter);
142
143        Ok(())
144    }
145}