use lazy_static::lazy_static; use crate::repr::{Board, Piece, Winner}; use super::board_value::BoardValueMap; #[derive(Clone, Debug)] pub struct Move { /// `i` position of move pub i: usize, /// `j` position of move pub j: usize, /// [`Board`] state after move is made pub board: Board, /// Current winner of the match pub winner: Winner, /// Index of this move's parent pub parent: Option, /// Indices of this Move's Children pub children: Vec, /// Value of this move (including children) pub value: i128, pub self_value: i64, pub color: Piece, pub lazy_children: bool, } lazy_static! { static ref BVM: BoardValueMap = BoardValueMap::new(); } impl Move { pub fn new( i: usize, j: usize, board: Board, color: Piece, lazy_children: bool, agent_color: Piece, parent: Option, ) -> Self { let mut m = Move { i, j, board, winner: board.game_winner(), parent, children: Vec::new(), value: 0, color, lazy_children, self_value: 0, }; m.self_value = m.compute_self_value(agent_color); m.value = m.self_value as i128; m } pub const fn coords(&self) -> (usize, usize) { (self.i, self.j) } pub fn compute_self_value(&self, agent_color: Piece) -> i64 { if self.winner == Winner::Player(!agent_color) { // if this board results in the opponent winning, MAJORLY negatively weigh this move // NOTE! this branch isn't completely deleted because if so, the bot wouldn't make a move. // We shouldn't prune branches because we still need to always react to the opponent's moves return i64::MIN + 1; } else if self.winner == Winner::Player(agent_color) { // results in a win for the agent return i64::MAX - 1; } else if self.winner == Winner::Tie { // idk what a Tie should be valued? return 0; } BVM.board_value(&self.board, agent_color) } }