fully fix future_moves
This commit is contained in:
parent
efd762e5d2
commit
52e7ed7386
@ -16,7 +16,7 @@ fn extend_layers_no_pruning(depth: usize, arena_size: usize) -> usize {
|
|||||||
children_eval_method: ChildrenEvalMethod::Max,
|
children_eval_method: ChildrenEvalMethod::Max,
|
||||||
};
|
};
|
||||||
let mut fut = FutureMoves::new(Piece::Black, config);
|
let mut fut = FutureMoves::new(Piece::Black, config);
|
||||||
fut.set_root_from_board(Board::new().starting_pos());
|
fut.update_from_board(&Board::new().starting_pos());
|
||||||
fut.extend_layers();
|
fut.extend_layers();
|
||||||
fut.arena_len()
|
fut.arena_len()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ impl ComplexAgent {
|
|||||||
impl Agent for ComplexAgent {
|
impl Agent for ComplexAgent {
|
||||||
fn next_move(&mut self, board: &Board) -> Option<CoordPair> {
|
fn next_move(&mut self, board: &Board) -> Option<CoordPair> {
|
||||||
self.future_moves.update_from_board(board);
|
self.future_moves.update_from_board(board);
|
||||||
|
self.future_moves.generate();
|
||||||
|
|
||||||
self.future_moves
|
self.future_moves
|
||||||
.best_move()
|
.best_move()
|
||||||
|
|||||||
@ -366,54 +366,41 @@ impl FutureMoves {
|
|||||||
// match the agent_color usually root or great-grand child
|
// match the agent_color usually root or great-grand child
|
||||||
.filter(|&idx| self.depth_of(idx) % 2 == 0)
|
.filter(|&idx| self.depth_of(idx) % 2 == 0)
|
||||||
.find(|&idx| {
|
.find(|&idx| {
|
||||||
self.get_board_from_idx(idx).as_ref() == Some(board)
|
self.arena[idx].color == !self.agent_color
|
||||||
&& self.arena[idx].color == !self.agent_color
|
&& self.get_board_from_idx(idx).as_ref() == Some(board)
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(curr_board_idx) = curr_board {
|
if let Some(curr_board_idx) = curr_board {
|
||||||
self.set_root_idx_raw(curr_board_idx);
|
self.root_from_child_idx_board(curr_board_idx, *board);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
if self.config.print && !self.arena.is_empty() {
|
if self.config.print && !self.arena.is_empty() {
|
||||||
println!("regenerating arena from board");
|
println!("regenerating arena from board");
|
||||||
}
|
}
|
||||||
self.set_root_from_board(*board);
|
self.rebuild_from_board(*board);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the arena and create and set a root which contains a Board
|
pub fn generate(&mut self) {
|
||||||
pub fn set_root_from_board(&mut self, board: Board) {
|
self.extend_layers();
|
||||||
|
self.compute_values(0..self.arena.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rebuild_from_board(&mut self, board: Board) {
|
||||||
self.arena.clear();
|
self.arena.clear();
|
||||||
self.arena
|
self.arena
|
||||||
.push(Move::new(None, board, !self.agent_color, self.agent_color));
|
.push(Move::new(None, board, !self.agent_color, self.agent_color));
|
||||||
|
self.current_root = Some(0);
|
||||||
// because we have to regenerate root from a [`Board`]
|
|
||||||
// we need to reset the current_depth (fixes `skip_move_recovery`)
|
|
||||||
self.current_depth = 0;
|
self.current_depth = 0;
|
||||||
|
self.board = board;
|
||||||
self.set_root_idx_raw(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update current root without modifying or pruning the Arena
|
fn root_from_child_idx_board(&mut self, idx: usize, board: Board) {
|
||||||
fn update_root_idx_raw(&mut self, idx: usize) {
|
|
||||||
self.current_root = Some(idx);
|
|
||||||
self.current_depth -= self.depth_of(idx);
|
self.current_depth -= self.depth_of(idx);
|
||||||
}
|
self.current_root = Some(idx);
|
||||||
|
self.board = board;
|
||||||
/// Update current root index while pruning and extending the tree (also recalculate values)
|
|
||||||
fn set_root_idx_raw(&mut self, idx: usize) {
|
|
||||||
self.update_root_idx_raw(idx);
|
|
||||||
|
|
||||||
self.refocus_tree();
|
self.refocus_tree();
|
||||||
self.extend_layers();
|
|
||||||
if self.config.print {
|
|
||||||
println!("# of moves stored: {}", self.arena_len());
|
|
||||||
}
|
|
||||||
self.compute_values(0..self.arena.len());
|
|
||||||
|
|
||||||
// check arena's consistancy
|
|
||||||
debug_assert_eq!(self.check_arena().join("\n"), "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_parent_child(&mut self, parent: usize, child: usize) {
|
pub fn set_parent_child(&mut self, parent: usize, child: usize) {
|
||||||
@ -574,26 +561,14 @@ mod tests {
|
|||||||
max_arena_size: 100,
|
max_arena_size: 100,
|
||||||
do_prune: false,
|
do_prune: false,
|
||||||
print: false,
|
print: false,
|
||||||
children_eval_method: ChildrenEvalMethod::Max,
|
children_eval_method: ChildrenEvalMethod::Average,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prune_tree_test() {
|
fn prune_tree_test() {
|
||||||
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.update_from_board(&Board::new());
|
||||||
coord: None,
|
|
||||||
winner: Winner::None,
|
|
||||||
parent: None,
|
|
||||||
children: Vec::new(),
|
|
||||||
value: None,
|
|
||||||
self_value: 0,
|
|
||||||
color: Piece::Black,
|
|
||||||
is_trimmed: false,
|
|
||||||
tried_children: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
|
||||||
|
|
||||||
// child 1
|
// child 1
|
||||||
futm.arena
|
futm.arena
|
||||||
@ -636,20 +611,17 @@ mod tests {
|
|||||||
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
futm.config.max_depth = 1;
|
futm.config.max_depth = 1;
|
||||||
|
|
||||||
futm.arena.push(Move::new(
|
futm.update_from_board(&Board::new().starting_pos());
|
||||||
None,
|
|
||||||
Board::new().starting_pos(),
|
|
||||||
Piece::Black,
|
|
||||||
Piece::Black,
|
|
||||||
));
|
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
|
||||||
|
|
||||||
futm.extend_layers();
|
futm.extend_layers();
|
||||||
assert_eq!(futm.arena_len(), 5);
|
assert_eq!(futm.arena_len(), 5);
|
||||||
|
|
||||||
// move to a child
|
// move to a child
|
||||||
futm.update_root_idx_raw(1);
|
futm.root_from_child_idx_board(
|
||||||
|
1,
|
||||||
|
futm.get_board_from_idx(1)
|
||||||
|
.expect("unable to get board from child"),
|
||||||
|
);
|
||||||
futm.refocus_tree();
|
futm.refocus_tree();
|
||||||
assert_eq!(futm.arena_len(), 1);
|
assert_eq!(futm.arena_len(), 1);
|
||||||
|
|
||||||
@ -667,19 +639,7 @@ mod tests {
|
|||||||
fn depth_of_test() {
|
fn depth_of_test() {
|
||||||
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.update_from_board(&Board::new());
|
||||||
coord: None,
|
|
||||||
winner: Winner::None,
|
|
||||||
parent: None,
|
|
||||||
children: vec![],
|
|
||||||
value: None,
|
|
||||||
self_value: 0,
|
|
||||||
color: Piece::Black,
|
|
||||||
is_trimmed: false,
|
|
||||||
tried_children: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
|
||||||
|
|
||||||
// child 1
|
// child 1
|
||||||
futm.arena
|
futm.arena
|
||||||
@ -707,19 +667,7 @@ mod tests {
|
|||||||
fn by_depth_test() {
|
fn by_depth_test() {
|
||||||
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.update_from_board(&Board::new());
|
||||||
coord: None,
|
|
||||||
winner: Winner::None,
|
|
||||||
parent: None,
|
|
||||||
children: vec![1],
|
|
||||||
value: None,
|
|
||||||
self_value: 0,
|
|
||||||
color: Piece::Black,
|
|
||||||
is_trimmed: false,
|
|
||||||
tried_children: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
|
||||||
|
|
||||||
// child 1
|
// child 1
|
||||||
futm.arena
|
futm.arena
|
||||||
@ -775,6 +723,7 @@ mod tests {
|
|||||||
|
|
||||||
// seperate variable because we want it to always be executed
|
// seperate variable because we want it to always be executed
|
||||||
let update_result = futm.update_from_board(&board);
|
let update_result = futm.update_from_board(&board);
|
||||||
|
futm.generate();
|
||||||
|
|
||||||
// make sure that the arena should only be
|
// make sure that the arena should only be
|
||||||
// regenerated on the first move
|
// regenerated on the first move
|
||||||
@ -808,9 +757,7 @@ mod tests {
|
|||||||
let mut futm = FutureMoves::new(Piece::White, FUTURE_MOVES_CONFIG);
|
let mut futm = FutureMoves::new(Piece::White, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
let mut b = Board::new().starting_pos();
|
let mut b = Board::new().starting_pos();
|
||||||
futm.arena
|
futm.update_from_board(&Board::new().starting_pos());
|
||||||
.push(Move::new(None, b, Piece::Black, Piece::White));
|
|
||||||
futm.update_root_idx_raw(0);
|
|
||||||
|
|
||||||
b.place((4, 2).into(), Piece::White).unwrap();
|
b.place((4, 2).into(), Piece::White).unwrap();
|
||||||
|
|
||||||
@ -877,7 +824,8 @@ mod tests {
|
|||||||
|
|
||||||
let mut futm = FutureMoves::new(Piece::White, FUTURE_MOVES_CONFIG);
|
let mut futm = FutureMoves::new(Piece::White, FUTURE_MOVES_CONFIG);
|
||||||
futm.update_from_board(&board);
|
futm.update_from_board(&board);
|
||||||
futm.extend_layers();
|
futm.generate();
|
||||||
|
|
||||||
let best_move = futm.best_move();
|
let best_move = futm.best_move();
|
||||||
|
|
||||||
if let Some(best_move) = best_move {
|
if let Some(best_move) = best_move {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user