allow move arena to properly handle skipping a move
This commit is contained in:
parent
4a82c01d64
commit
d3cac6ae91
@ -120,16 +120,22 @@ impl FutureMoves {
|
|||||||
|
|
||||||
// use [`Board::all_positions`] here instead of [`Board::possible_moves`]
|
// 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`]
|
// because we use [`Board::what_if`] later and we want to reduce calls to [`Board::propegate_from_dry`]
|
||||||
let new: Vec<Move> = Board::all_positions()
|
let mut new: Vec<Move> = Board::all_positions()
|
||||||
.flat_map(|(i, j)| {
|
.flat_map(|(i, j)| {
|
||||||
parent
|
parent
|
||||||
.board
|
.board
|
||||||
.what_if(i, j, new_color)
|
.what_if(i, j, new_color)
|
||||||
.map(move |x| (i, j, x))
|
.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();
|
.collect();
|
||||||
|
|
||||||
|
if new.is_empty() {
|
||||||
|
new.push(Move::new(None, parent.board, new_color, self.agent_color));
|
||||||
|
}
|
||||||
|
|
||||||
let start_idx = self.arena.len();
|
let start_idx = self.arena.len();
|
||||||
self.arena.extend(new);
|
self.arena.extend(new);
|
||||||
|
|
||||||
@ -224,7 +230,7 @@ impl FutureMoves {
|
|||||||
"selected move color should be the same as the color of the agent"
|
"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
|
/// 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
|
/// Clear the arena and create and set a root which contains a Board
|
||||||
pub fn set_root_from_board(&mut self, board: Board) {
|
pub fn set_root_from_board(&mut self, board: Board) {
|
||||||
self.arena.clear();
|
self.arena.clear();
|
||||||
self.arena.push(Move::new(
|
self.arena
|
||||||
0, // dummy
|
.push(Move::new(None, board, !self.agent_color, self.agent_color));
|
||||||
0, // dummy
|
|
||||||
board,
|
|
||||||
!self.agent_color,
|
|
||||||
self.agent_color,
|
|
||||||
));
|
|
||||||
// because we have to regenerate root from a [`Board`]
|
// because we have to regenerate root from a [`Board`]
|
||||||
// we need to reset the current_depth (fixes `skip_move_recovery`)
|
// we need to reset the current_depth (fixes `skip_move_recovery`)
|
||||||
self.current_depth = 0;
|
self.current_depth = 0;
|
||||||
@ -275,7 +276,7 @@ impl FutureMoves {
|
|||||||
self.arena
|
self.arena
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.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)
|
.map(|x| x.0)
|
||||||
// do raw set so we can prune it on the next move (in `update`)
|
// do raw set so we can prune it on the next move (in `update`)
|
||||||
.inspect(|&root| self.update_root_idx_raw(root))
|
.inspect(|&root| self.update_root_idx_raw(root))
|
||||||
@ -470,8 +471,7 @@ mod tests {
|
|||||||
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
futm.arena.push(Move {
|
futm.arena.push(Move {
|
||||||
i: 0,
|
coord: None,
|
||||||
j: 0,
|
|
||||||
board: Board::new(),
|
board: Board::new(),
|
||||||
winner: Winner::None,
|
winner: Winner::None,
|
||||||
parent: None,
|
parent: None,
|
||||||
@ -487,13 +487,12 @@ mod tests {
|
|||||||
|
|
||||||
// child 1
|
// child 1
|
||||||
futm.arena
|
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);
|
futm.set_parent_child(0, 1);
|
||||||
|
|
||||||
// dummy (2)
|
// dummy (2)
|
||||||
futm.arena.push(Move::new(
|
futm.arena.push(Move::new(
|
||||||
1234,
|
Some((1234, 1234)),
|
||||||
1234,
|
|
||||||
Board::new(),
|
Board::new(),
|
||||||
Piece::White,
|
Piece::White,
|
||||||
Piece::Black,
|
Piece::Black,
|
||||||
@ -501,12 +500,12 @@ mod tests {
|
|||||||
|
|
||||||
// 3
|
// 3
|
||||||
futm.arena
|
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);
|
futm.set_parent_child(0, 3);
|
||||||
|
|
||||||
// 4
|
// 4
|
||||||
futm.arena
|
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);
|
futm.set_parent_child(0, 4);
|
||||||
|
|
||||||
assert_eq!(futm.arena_len(), 5);
|
assert_eq!(futm.arena_len(), 5);
|
||||||
@ -515,7 +514,11 @@ mod tests {
|
|||||||
assert_eq!(futm.arena_len(), 4);
|
assert_eq!(futm.arena_len(), 4);
|
||||||
assert_eq!(futm.arena[0].children.len(), 3);
|
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]
|
#[test]
|
||||||
@ -524,8 +527,7 @@ mod tests {
|
|||||||
futm.config.max_depth = 1;
|
futm.config.max_depth = 1;
|
||||||
|
|
||||||
futm.arena.push(Move::new(
|
futm.arena.push(Move::new(
|
||||||
0,
|
None,
|
||||||
0,
|
|
||||||
Board::new().starting_pos(),
|
Board::new().starting_pos(),
|
||||||
Piece::Black,
|
Piece::Black,
|
||||||
Piece::Black,
|
Piece::Black,
|
||||||
@ -556,8 +558,7 @@ mod tests {
|
|||||||
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
futm.arena.push(Move {
|
futm.arena.push(Move {
|
||||||
i: 0,
|
coord: None,
|
||||||
j: 0,
|
|
||||||
board: Board::new(),
|
board: Board::new(),
|
||||||
winner: Winner::None,
|
winner: Winner::None,
|
||||||
parent: None,
|
parent: None,
|
||||||
@ -573,25 +574,20 @@ mod tests {
|
|||||||
|
|
||||||
// child 1
|
// child 1
|
||||||
futm.arena
|
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);
|
futm.set_parent_child(0, 1);
|
||||||
|
|
||||||
// dummy
|
// dummy
|
||||||
futm.arena.push(Move::new(
|
futm.arena
|
||||||
1234,
|
.push(Move::new(None, Board::new(), Piece::White, Piece::Black));
|
||||||
1234,
|
|
||||||
Board::new(),
|
|
||||||
Piece::White,
|
|
||||||
Piece::Black,
|
|
||||||
));
|
|
||||||
|
|
||||||
futm.arena
|
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.set_parent_child(1, 3);
|
||||||
|
|
||||||
futm.arena
|
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);
|
futm.set_parent_child(0, 4);
|
||||||
|
|
||||||
@ -603,8 +599,7 @@ mod tests {
|
|||||||
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
futm.arena.push(Move {
|
futm.arena.push(Move {
|
||||||
i: 0,
|
coord: None,
|
||||||
j: 0,
|
|
||||||
board: Board::new(),
|
board: Board::new(),
|
||||||
winner: Winner::None,
|
winner: Winner::None,
|
||||||
parent: None,
|
parent: None,
|
||||||
@ -620,20 +615,15 @@ mod tests {
|
|||||||
|
|
||||||
// child 1
|
// child 1
|
||||||
futm.arena
|
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);
|
futm.set_parent_child(0, 1);
|
||||||
|
|
||||||
// dummy
|
// dummy
|
||||||
futm.arena.push(Move::new(
|
futm.arena
|
||||||
1234,
|
.push(Move::new(None, Board::new(), Piece::White, Piece::Black));
|
||||||
1234,
|
|
||||||
Board::new(),
|
|
||||||
Piece::White,
|
|
||||||
Piece::Black,
|
|
||||||
));
|
|
||||||
|
|
||||||
futm.arena
|
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.set_parent_child(1, 3);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@ -4,11 +4,8 @@ use lazy_static::lazy_static;
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Move {
|
pub struct Move {
|
||||||
/// `i` position of move
|
/// Coordinates (i, j) of the move (if it exists)
|
||||||
pub i: usize,
|
pub coord: Option<(usize, usize)>,
|
||||||
|
|
||||||
/// `j` position of move
|
|
||||||
pub j: usize,
|
|
||||||
|
|
||||||
/// [`Board`] state after move is made
|
/// [`Board`] state after move is made
|
||||||
pub board: Board,
|
pub board: Board,
|
||||||
@ -43,10 +40,14 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Move {
|
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 {
|
let mut m = Move {
|
||||||
i,
|
coord,
|
||||||
j,
|
|
||||||
board,
|
board,
|
||||||
winner: board.game_winner(),
|
winner: board.game_winner(),
|
||||||
parent: None,
|
parent: None,
|
||||||
@ -61,10 +62,6 @@ impl Move {
|
|||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn coords(&self) -> (usize, usize) {
|
|
||||||
(self.i, self.j)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_self_value(&self, agent_color: Piece) -> i64 {
|
fn compute_self_value(&self, agent_color: Piece) -> i64 {
|
||||||
if self.winner == Winner::Player(!agent_color) {
|
if self.winner == Winner::Player(!agent_color) {
|
||||||
// if this board results in the opponent winning, MAJORLY negatively weigh this move
|
// if this board results in the opponent winning, MAJORLY negatively weigh this move
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user