rustenginelib/
lineargame.rs

1//use crate::bitboard::*;
2use crate::constants::*;
3//use crate::piece::*;
4use crate::square::*;
5use crate::state::*;
6
7use std::time::Instant;
8
9/// LinearGame represents a single variantion chess game
10pub struct LinearGame {
11    pub states: Vec<State>,
12    pub state_ptr: usize,
13    pub nodes: usize,
14}
15
16/// LinearGame implementation
17impl LinearGame {
18    /// returns a new empty LinearGame
19    pub fn new() -> LinearGame {
20        LinearGame {
21            states: vec![State::new(); MAX_STATES],
22            state_ptr: 0,
23            nodes: 0,
24        }
25    }
26
27    /// current returns the current state of the game
28    pub fn current(&mut self) -> &mut State {
29        &mut self.states[self.state_ptr]
30    }
31
32    /// returns the game as pretty printable string
33    pub fn pretty_print_string(&mut self) -> String {
34        self.current().pretty_print_string()
35    }
36
37    /// prints the game
38    pub fn print(&mut self) {
39        println!("{}", self.pretty_print_string())
40    }
41
42    /// initializes game to variant
43    pub fn init(&mut self, variant: Variant) {
44        self.state_ptr = 0;
45        self.current().init(variant);
46    }
47
48    /// pushes a move
49    pub fn push(&mut self, mv: Move) {
50        self.state_ptr += 1;
51        self.states[self.state_ptr] = self.states[self.state_ptr - 1].clone();
52        self.current().make_move(mv);
53    }
54
55    /// pops a state
56    pub fn pop(&mut self) {
57        if self.state_ptr <= 0 {
58            return;
59        }
60        self.state_ptr -= 1;
61    }
62
63    /// pushes a move by index in state move buff
64    pub fn push_by_index(&mut self, index: usize) -> bool {
65        if index < self.current().move_buff.len() {
66            let mv = self.current().move_buff[index].mv;
67            self.push(mv);
68            return true;
69        }
70        false
71    }
72
73    pub fn perft_rec(&mut self, depth: usize) {
74        self.nodes += 1;
75        if depth == 0 {
76            return;
77        }
78        let moves = self.current().generate_pseudo_legal_moves(MoveGenMode::All);
79        for mv in moves.iter() {
80            self.push(*mv);
81            self.perft_rec(depth - 1);
82            self.pop();
83        }
84    }
85
86    pub fn perft(&mut self, depth: usize) -> (usize, f32, f32) {
87        self.nodes = 0;
88        let start = Instant::now();
89        self.perft_rec(depth);
90        let duration = start.elapsed();
91        let secs = ((duration.as_secs() as f32) * 1e9 + (duration.subsec_nanos() as f32)) / 1e9;
92        (self.nodes, secs, (self.nodes as f32) / secs / 1000.0)
93    }
94}