logical improvements and cleanup
This commit is contained in:
parent
2011ae001b
commit
3b07a67d2e
@ -12,10 +12,10 @@ pub struct ComplexAgent {
|
||||
#[allow(dead_code)]
|
||||
impl ComplexAgent {
|
||||
pub const fn new(color: Piece) -> Self {
|
||||
const MAX_DEPTH: usize = 12;
|
||||
const MAX_DEPTH: usize = 10;
|
||||
Self {
|
||||
color,
|
||||
future_moves: FutureMoves::new(color, MAX_DEPTH, 6),
|
||||
future_moves: FutureMoves::new(color, MAX_DEPTH, 8),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,7 +24,7 @@ impl Agent for ComplexAgent {
|
||||
fn next_move(&mut self, board: &Board) -> Option<(usize, usize)> {
|
||||
self.future_moves.update(board);
|
||||
|
||||
println!("# of moves stored: {}", self.future_moves.len());
|
||||
println!("# of moves stored: {}", self.future_moves.arena_len());
|
||||
|
||||
self.future_moves.best_move().inspect(|&(i, j)| {
|
||||
if !self.future_moves.update_root_coord(i, j) {
|
||||
|
||||
@ -37,14 +37,10 @@ impl FutureMoves {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
pub fn arena_len(&self) -> usize {
|
||||
self.arena.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Generate children for all children of `nodes`
|
||||
/// only `pub` for the sake of benchmarking
|
||||
pub fn extend_layers(&mut self) {
|
||||
@ -118,26 +114,17 @@ impl FutureMoves {
|
||||
// because we use [`Board::what_if`] later and we want to reduce calls to [`Board::propegate_from_dry`]
|
||||
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 {
|
||||
i,
|
||||
j,
|
||||
board: new_board,
|
||||
winner: new_board.game_winner(),
|
||||
parent: Some(parent_idx),
|
||||
children: Vec::new(),
|
||||
value: 0,
|
||||
color: new_color,
|
||||
lazy_children,
|
||||
}).collect();
|
||||
.map(|(i, j, new_board)| Move::new(i, j, new_board, new_color, lazy_children, self.agent_color, Some(parent_idx))).collect();
|
||||
|
||||
// negative, because we want the max value to be at the first index
|
||||
new.sort_by_key(|x| -x.compute_self_value(self.agent_color));
|
||||
// abs because we want the most EXTREME possible outcome (win or lose for example)
|
||||
new.sort_by_key(|x| -x.self_value.abs());
|
||||
|
||||
// keep the TOP_K children `self.agent_color`-color moves
|
||||
const TOP_K_CHILDREN: usize = 1;
|
||||
const TOP_K_CHILDREN: usize = 2;
|
||||
|
||||
// we want to keep only the best move of the agent
|
||||
if lazy_children && new_color == self.agent_color && new.len() > TOP_K_CHILDREN {
|
||||
if lazy_children && new.len() > TOP_K_CHILDREN {
|
||||
new.drain(TOP_K_CHILDREN..);
|
||||
}
|
||||
|
||||
@ -156,6 +143,7 @@ impl FutureMoves {
|
||||
} else {
|
||||
self.arena.extend(new);
|
||||
}
|
||||
|
||||
let new_indices = start_idx..self.arena.len();
|
||||
|
||||
self.arena[parent_idx].children.extend(new_indices.clone());
|
||||
@ -191,15 +179,14 @@ impl FutureMoves {
|
||||
// TODO! impl dynamic sorting based on children's states, maybe it propegates
|
||||
// upwards using the `parent` field
|
||||
// SAFETY! the sort_by_key function should not modify anything
|
||||
unsafe { (*(self as *mut Self)).arena.get_unchecked_mut(idx) }
|
||||
unsafe { &mut (*(self as *mut Self)) }.arena[idx]
|
||||
.children
|
||||
// negative because we want the largest value in the first index
|
||||
.sort_by_key(|&x| -self.arena[x].value);
|
||||
// abs so we get the most extreme solutions
|
||||
// but base on `.value` for recursive behavior
|
||||
.sort_by_key(|&x| -self.arena[x].value.abs());
|
||||
|
||||
let node = &self.arena[idx];
|
||||
let self_value = node.compute_self_value(self.agent_color) / (depth + 1) as i64;
|
||||
|
||||
let children_value = node
|
||||
let children_value = self.arena[idx]
|
||||
.children
|
||||
.iter()
|
||||
.rev() // rev then reverse so we get an index starting from the back
|
||||
@ -207,10 +194,11 @@ impl FutureMoves {
|
||||
// since children are sorted by value, we should weight the first one more
|
||||
.map(|(i, &child)| self.arena[child].value * (i as i64 + 1))
|
||||
.sum::<i64>()
|
||||
.checked_div(node.children.len() as i64)
|
||||
.checked_div((&self.arena[idx]).children.len() as i64)
|
||||
.unwrap_or(0);
|
||||
|
||||
self.arena[idx].value = self_value + children_value;
|
||||
self.arena[idx].value =
|
||||
self.arena[idx].self_value / (depth as i64 + 1) + children_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -264,6 +252,7 @@ impl FutureMoves {
|
||||
value: 0,
|
||||
color: !self.agent_color,
|
||||
lazy_children: false,
|
||||
self_value: 0,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -24,9 +24,11 @@ pub struct Move {
|
||||
/// Indices of this Move's Children
|
||||
pub children: Vec<usize>,
|
||||
|
||||
/// Value of this move
|
||||
/// Value of this move (including children)
|
||||
pub value: i64,
|
||||
|
||||
pub self_value: i64,
|
||||
|
||||
pub color: Piece,
|
||||
|
||||
pub lazy_children: bool,
|
||||
@ -37,6 +39,32 @@ lazy_static! {
|
||||
}
|
||||
|
||||
impl Move {
|
||||
pub fn new(
|
||||
i: usize,
|
||||
j: usize,
|
||||
board: Board,
|
||||
color: Piece,
|
||||
lazy_children: bool,
|
||||
agent_color: Piece,
|
||||
parent: Option<usize>,
|
||||
) -> 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;
|
||||
m
|
||||
}
|
||||
|
||||
pub const fn coords(&self) -> (usize, usize) {
|
||||
(self.i, self.j)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user