diff --git a/src/logic/future_moves.rs b/src/logic/future_moves.rs index 5521e59..369a07e 100644 --- a/src/logic/future_moves.rs +++ b/src/logic/future_moves.rs @@ -120,16 +120,22 @@ impl FutureMoves { // use [`Board::all_positions`] here instead of [`Board::possible_moves`] // because we use [`Board::what_if`] later and we want to reduce calls to [`Board::propegate_from_dry`] - let new: Vec = Board::all_positions() + let mut new: Vec = Board::all_positions() .flat_map(|(i, j)| { parent .board .what_if(i, j, new_color) .map(move |x| (i, j, x)) }) - .map(|(i, j, new_board)| Move::new(i, j, new_board, new_color, self.agent_color)) + .map(|(i, j, new_board)| { + Move::new(Some((i, j)), new_board, new_color, self.agent_color) + }) .collect(); + if new.is_empty() { + new.push(Move::new(None, parent.board, new_color, self.agent_color)); + } + let start_idx = self.arena.len(); self.arena.extend(new); @@ -224,7 +230,7 @@ impl FutureMoves { "selected move color should be the same as the color of the agent" ); }) - .map(|&x| self.arena[x].coords()) + .and_then(|&x| self.arena[x].coord) } /// Updates `FutureMoves` based on the current state of the board @@ -248,13 +254,8 @@ impl FutureMoves { /// Clear the arena and create and set a root which contains a Board pub fn set_root_from_board(&mut self, board: Board) { self.arena.clear(); - self.arena.push(Move::new( - 0, // dummy - 0, // dummy - board, - !self.agent_color, - self.agent_color, - )); + self.arena + .push(Move::new(None, board, !self.agent_color, self.agent_color)); // because we have to regenerate root from a [`Board`] // we need to reset the current_depth (fixes `skip_move_recovery`) self.current_depth = 0; @@ -275,7 +276,7 @@ impl FutureMoves { self.arena .iter() .enumerate() - .find(|(_, node)| node.parent == self.current_root && node.coords() == (i, j)) + .find(|(_, node)| node.parent == self.current_root && node.coord == Some((i, j))) .map(|x| x.0) // do raw set so we can prune it on the next move (in `update`) .inspect(|&root| self.update_root_idx_raw(root)) @@ -470,8 +471,7 @@ mod tests { let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG); futm.arena.push(Move { - i: 0, - j: 0, + coord: None, board: Board::new(), winner: Winner::None, parent: None, @@ -487,13 +487,12 @@ mod tests { // child 1 futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(0, 1); // dummy (2) futm.arena.push(Move::new( - 1234, - 1234, + Some((1234, 1234)), Board::new(), Piece::White, Piece::Black, @@ -501,12 +500,12 @@ mod tests { // 3 futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(0, 3); // 4 futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(0, 4); assert_eq!(futm.arena_len(), 5); @@ -515,7 +514,11 @@ mod tests { assert_eq!(futm.arena_len(), 4); assert_eq!(futm.arena[0].children.len(), 3); - assert_ne!(futm.arena[2].i, 1234, "dummy value still exists"); + assert_ne!( + futm.arena[2].coord, + Some((1234, 1234)), + "dummy value still exists" + ); } #[test] @@ -524,8 +527,7 @@ mod tests { futm.config.max_depth = 1; futm.arena.push(Move::new( - 0, - 0, + None, Board::new().starting_pos(), Piece::Black, Piece::Black, @@ -556,8 +558,7 @@ mod tests { let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG); futm.arena.push(Move { - i: 0, - j: 0, + coord: None, board: Board::new(), winner: Winner::None, parent: None, @@ -573,25 +574,20 @@ mod tests { // child 1 futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(0, 1); // dummy - futm.arena.push(Move::new( - 1234, - 1234, - Board::new(), - Piece::White, - Piece::Black, - )); + futm.arena + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(1, 3); futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(0, 4); @@ -603,8 +599,7 @@ mod tests { let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG); futm.arena.push(Move { - i: 0, - j: 0, + coord: None, board: Board::new(), winner: Winner::None, parent: None, @@ -620,20 +615,15 @@ mod tests { // child 1 futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(0, 1); // dummy - futm.arena.push(Move::new( - 1234, - 1234, - Board::new(), - Piece::White, - Piece::Black, - )); + futm.arena + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.arena - .push(Move::new(0, 0, Board::new(), Piece::White, Piece::Black)); + .push(Move::new(None, Board::new(), Piece::White, Piece::Black)); futm.set_parent_child(1, 3); assert_eq!( diff --git a/src/logic/move.rs b/src/logic/move.rs index 2f82ec0..006cd56 100644 --- a/src/logic/move.rs +++ b/src/logic/move.rs @@ -4,11 +4,8 @@ use lazy_static::lazy_static; #[derive(Clone, Debug)] pub struct Move { - /// `i` position of move - pub i: usize, - - /// `j` position of move - pub j: usize, + /// Coordinates (i, j) of the move (if it exists) + pub coord: Option<(usize, usize)>, /// [`Board`] state after move is made pub board: Board, @@ -43,10 +40,14 @@ lazy_static! { } impl Move { - pub fn new(i: usize, j: usize, board: Board, color: Piece, agent_color: Piece) -> Self { + pub fn new( + coord: Option<(usize, usize)>, + board: Board, + color: Piece, + agent_color: Piece, + ) -> Self { let mut m = Move { - i, - j, + coord, board, winner: board.game_winner(), parent: None, @@ -61,10 +62,6 @@ impl Move { m } - pub const fn coords(&self) -> (usize, usize) { - (self.i, self.j) - } - 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