use crate::position::{
PieceType, Pieces, Position
};
use crate::filter::Filter;
#[cfg(feature = "readerstats")]
use crate::stats::ReaderStat;
#[cfg(feature = "positionstats")]
use crate::stats::Stats;
use std::io::{Cursor, Read};
use bulletformat::ChessBoard;
pub struct SydGame{
#[cfg(feature = "readerstats")]
pub readerstat: ReaderStat,
#[cfg(feature = "positionstats")]
pub posstats: Stats,
#[cfg(feature = "compress")]
last_score: i16,
}
impl SydGame {
pub fn new() -> Self{
Self{
#[cfg(feature = "readerstats")]
readerstat:ReaderStat::new(),
#[cfg(feature = "positionstats")]
posstats:Stats::new(),
#[cfg(feature = "compress")]
last_score: 0,
}
}
pub fn parse_tree<R: std::io::Read>(&mut self, cursor: &mut R, out: &mut Vec<ChessBoard>, pos:&mut Position, filter: &Filter){
let mut buff: [u8; 2] = [0; 2];
cursor.read_exact(&mut buff).unwrap();
let bm: u16 = u16::from_le_bytes(buff);
cursor.read_exact(&mut buff).unwrap();
let score: i16 = i16::from_le_bytes(buff);
cursor.read_exact(&mut buff).unwrap();
let info = buff[0];
let nb_child = buff[1];
pos.bm = bm;
pos.bound = info%3;
pos.depth = info/3;
pos.score = score;
#[cfg(feature = "compress")]
let sizescorediff = ((pos.score as i64 - self.last_score as i64).abs() as u64).next_power_of_two().ilog2() as u64 + 1;
if !filter.should_filter(pos) {
#[cfg(feature = "positionstats")]
self.posstats.update(pos);
out.push(pos.tobullet());
}
#[cfg(feature = "readerstats")]
let mut is_bm_continued = false;
for _id_child in 0..nb_child {
cursor.read_exact(&mut buff).unwrap();
let mv: u16 = u16::from_le_bytes(buff);
#[cfg(feature = "readerstats")]
if mv == bm {
is_bm_continued = true;
}
let mut newpos: Position = *pos;
newpos.play(mv);
#[cfg(feature = "compress")]
{
self.last_score = -pos.score;
}
self.parse_tree(cursor, out, &mut newpos, filter);
}
#[cfg(feature = "compress")]
{
let size_move: u64 =
17 + 5 + 9 * !is_bm_continued as u64 + sizescorediff + ((nb_child.max(2) as u64 - 2).next_power_of_two().ilog2() as u64+3) * (nb_child > 1) as u64; self.readerstat.update(nb_child as usize, is_bm_continued, size_move);
}
#[cfg(all(not(feature = "compress"), feature = "readerstats"))]
{
self.readerstat.update(nb_child as usize, is_bm_continued, 0);
}
}
pub fn parse_syd<R: std::io::Read>(&mut self, reader: &mut R, res: &mut Vec<ChessBoard>, filter: &Filter) -> std::io::Result<()>{
#[cfg(feature = "compress")]
{
self.last_score = 0;
}
let mut buff_4: [u8; 4] = [0; 4];
reader.read_exact(&mut buff_4)?;
let size:u32 = u32::from_le_bytes(buff_4);
res.reserve_exact((size as usize-38)/8+1);
let mut full = Vec::<u8>::new();
full.resize(size as usize, 0);
assert!(full.len() == size as usize);
reader.read_exact(&mut full).unwrap();
let mut c = Cursor::new(full);
let mut marlin: [u8; 32] = [0; 32];
c.read_exact(&mut marlin).unwrap();
let mut startpos: Position = Position::default();
let occupancy = u64::from_le_bytes(marlin[..8].try_into().unwrap());
let mut mask = occupancy;
for id_piece in 0..occupancy.count_ones() {
let pos = mask.trailing_zeros();
let mut piece = Pieces::from_viri((marlin[(8+id_piece/2) as usize] >> 4 * (id_piece%2)) & 0b1111);
if piece.piecetype() == PieceType::Castle {
startpos.update_castle_rights(pos as usize);
piece = Pieces::from_pc_color(PieceType::Rook, piece.color());
}
startpos.push(pos, piece);
mask &= mask - 1;
}
let stmep = marlin[24];
let mut epsquare = stmep & 0b1111111;
let stm: bool = (stmep >> 7) != 0;
if epsquare != 64 {
if stm {
epsquare += 8;
} else {
epsquare -= 8;
}
}
startpos.update_ep(epsquare as usize);
startpos.update_stm(stm as usize);
startpos.rule50 = marlin[25];
self.parse_tree(&mut c, res, &mut startpos, filter);
Ok(())
}
}