create FutureMoveConfig
This commit is contained in:
parent
d8f68e7fb1
commit
ff87337512
@ -1,12 +1,18 @@
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use othello::{
|
||||
logic::FutureMoves,
|
||||
logic::{FutureMoveConfig, FutureMoves},
|
||||
repr::{Board, Piece},
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
fn extend_layers_test(depth: usize) {
|
||||
let mut fut = FutureMoves::new(Piece::Black, depth);
|
||||
let config = FutureMoveConfig {
|
||||
max_depth: depth,
|
||||
start_pruning_at_minus: 4,
|
||||
top_k_children: 2,
|
||||
up_to_mod: 4,
|
||||
};
|
||||
let mut fut = FutureMoves::new(Piece::Black, config);
|
||||
fut.set_root_from_board(Board::new().starting_pos());
|
||||
fut.extend_layers();
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
agent::Agent,
|
||||
logic::FutureMoves,
|
||||
logic::{FutureMoveConfig, FutureMoves},
|
||||
repr::{Board, Piece},
|
||||
};
|
||||
|
||||
@ -12,10 +12,15 @@ pub struct ComplexAgent {
|
||||
#[allow(dead_code)]
|
||||
impl ComplexAgent {
|
||||
pub const fn new(color: Piece) -> Self {
|
||||
const MAX_DEPTH: usize = 9;
|
||||
const CONFIG: FutureMoveConfig = FutureMoveConfig {
|
||||
max_depth: 7,
|
||||
start_pruning_at_minus: 4,
|
||||
top_k_children: 2,
|
||||
up_to_mod: 4,
|
||||
};
|
||||
Self {
|
||||
color,
|
||||
future_moves: FutureMoves::new(color, MAX_DEPTH),
|
||||
future_moves: FutureMoves::new(color, CONFIG),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,21 +15,37 @@ pub struct FutureMoves {
|
||||
/// Current generated depth of the Arena
|
||||
current_depth: usize,
|
||||
|
||||
/// Target depth of children to generate
|
||||
max_depth: usize,
|
||||
|
||||
/// Color w.r.t
|
||||
agent_color: Piece,
|
||||
|
||||
config: FutureMoveConfig,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FutureMoveConfig {
|
||||
/// Max depth of that we should try and traverse
|
||||
pub max_depth: usize,
|
||||
|
||||
/// start pruning at X depth before self.max_depth is reached
|
||||
/// used for pruning during tree generation before the tree is fully grown
|
||||
pub start_pruning_at_minus: usize,
|
||||
|
||||
/// when pruning, keep the top_k # of children
|
||||
pub top_k_children: usize,
|
||||
|
||||
// the lower the value, the more conservative the pruning is, what level to stop pruning at?
|
||||
// a lower value allows more possible paths
|
||||
pub up_to_mod: usize,
|
||||
}
|
||||
|
||||
impl FutureMoves {
|
||||
pub const fn new(agent_color: Piece, max_depth: usize) -> Self {
|
||||
pub const fn new(agent_color: Piece, config: FutureMoveConfig) -> Self {
|
||||
Self {
|
||||
arena: Vec::new(),
|
||||
current_root: None,
|
||||
current_depth: 0,
|
||||
max_depth,
|
||||
agent_color,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +57,7 @@ impl FutureMoves {
|
||||
/// Generate children for all children of `nodes`
|
||||
/// only `pub` for the sake of benchmarking
|
||||
pub fn extend_layers(&mut self) {
|
||||
for i in (self.current_depth + 1)..=self.max_depth {
|
||||
for i in (self.current_depth + 1)..=self.config.max_depth {
|
||||
(0..self.arena.len())
|
||||
// we want to select all nodes that don't have children, or are lazy (need to maybe be regenerated)
|
||||
.filter(|&idx| {
|
||||
@ -54,7 +70,7 @@ impl FutureMoves {
|
||||
.progress_with_style(
|
||||
ProgressStyle::with_template(&format!(
|
||||
"Generating children (depth: {}/{}): ({{pos}}/{{len}}) {{per_sec}}",
|
||||
i, self.max_depth
|
||||
i, self.config.max_depth
|
||||
))
|
||||
.unwrap(),
|
||||
)
|
||||
@ -66,9 +82,9 @@ impl FutureMoves {
|
||||
self.current_depth += 1;
|
||||
}
|
||||
assert_eq!(
|
||||
self.current_depth, self.max_depth,
|
||||
self.current_depth, self.config.max_depth,
|
||||
"iteration and extention did not extend current_depth ({}) to the max_depth ({})",
|
||||
self.current_depth, self.max_depth
|
||||
self.current_depth, self.config.max_depth
|
||||
);
|
||||
}
|
||||
|
||||
@ -323,23 +339,18 @@ impl FutureMoves {
|
||||
|
||||
let by_depth = self.by_depth(0..self.arena.len());
|
||||
|
||||
const TOP_K_CHIL: usize = 2;
|
||||
|
||||
// the lower the value, the more conservative, what level to stop pruning at?
|
||||
// a lower value allows more possible paths
|
||||
let up_to = self.current_depth - 2;
|
||||
|
||||
// start pruning at X depth before self.max_depth is reached
|
||||
// used for pruning during tree generation before the tree is fully grown
|
||||
const START_PRUNING_AT_MINUS: usize = 3;
|
||||
|
||||
if self.max_depth.saturating_sub(START_PRUNING_AT_MINUS) > self.current_depth {
|
||||
if self
|
||||
.config
|
||||
.max_depth
|
||||
.saturating_sub(self.config.start_pruning_at_minus)
|
||||
> self.current_depth
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (depth, indexes) in by_depth {
|
||||
// TODO! maybe update by_depth every iteration or something?
|
||||
if depth > up_to {
|
||||
if depth > self.current_depth.saturating_sub(self.config.up_to_mod) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -355,8 +366,8 @@ impl FutureMoves {
|
||||
}
|
||||
m.is_trimmed = true;
|
||||
m.sort_children(&mut self.arena);
|
||||
if m.children.len() > TOP_K_CHIL {
|
||||
let drained = m.children.drain(TOP_K_CHIL..);
|
||||
if m.children.len() > self.config.top_k_children {
|
||||
let drained = m.children.drain(self.config.top_k_children..);
|
||||
for idx in drained {
|
||||
self.arena[idx].parent = None;
|
||||
}
|
||||
@ -441,7 +452,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn prune_tree_test() {
|
||||
let mut futm = FutureMoves::new(Piece::Black, 0);
|
||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
||||
|
||||
futm.arena.push(Move {
|
||||
i: 0,
|
||||
j: 0,
|
||||
@ -510,7 +522,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn expand_layer_test() {
|
||||
let mut futm = FutureMoves::new(Piece::Black, 1);
|
||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
||||
futm.config.max_depth = 1;
|
||||
|
||||
futm.arena.push(Move::new(
|
||||
0,
|
||||
0,
|
||||
@ -542,7 +556,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn depth_of_test() {
|
||||
let mut futm = FutureMoves::new(Piece::Black, 0);
|
||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
||||
|
||||
futm.arena.push(Move {
|
||||
i: 0,
|
||||
@ -606,7 +620,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn by_depth_test() {
|
||||
let mut futm = FutureMoves::new(Piece::Black, 0);
|
||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
||||
|
||||
futm.arena.push(Move {
|
||||
i: 0,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
mod board_value;
|
||||
mod future_moves;
|
||||
mod r#move;
|
||||
pub use future_moves::FutureMoves;
|
||||
pub use future_moves::{FutureMoveConfig, FutureMoves};
|
||||
|
||||
@ -10,8 +10,8 @@ pub mod repr;
|
||||
fn main() {
|
||||
let player1 = complexagent::ComplexAgent::new(Piece::Black);
|
||||
// let player2 = complexagent::ComplexAgent::new(Piece::White);
|
||||
let player2 = agent::ManualAgent::new(Piece::White);
|
||||
// let player2 = agent::RandomAgent::new(Piece::White);
|
||||
// let player2 = agent::ManualAgent::new(Piece::White);
|
||||
let player2 = agent::RandomAgent::new(Piece::White);
|
||||
let mut game = Game::new(Box::new(player1), Box::new(player2));
|
||||
game.game_loop();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user