This commit is contained in:
Simon Gardling 2025-03-02 23:36:40 -05:00
parent 1dd1f3da25
commit a9dd85762d
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D
3 changed files with 159 additions and 27 deletions

View File

@ -12,6 +12,7 @@ fn extend_layers_no_pruning(depth: usize, arena_size: usize) -> usize {
up_to_minus: 4,
max_arena_size: arena_size,
do_not_prune: true,
print: false,
};
let mut fut = FutureMoves::new(Piece::Black, config);
fut.set_root_from_board(Board::new().starting_pos());

View File

@ -11,38 +11,131 @@ use skillratings::{
};
pub fn run() {
const FMV_BASE: FutureMoveConfig = FutureMoveConfig {
max_depth: 20,
min_arena_depth: 14,
top_k_children: 2,
up_to_minus: 10,
max_arena_size: 5_000_000,
do_not_prune: false,
print: false,
};
let mut arena = PlayerArena::new(vec![
(
"RandomAgent".into(),
Box::new(|piece| Box::new(RandomAgent::new(piece))),
1,
),
(
"ComplexAgentBasic".into(),
"ComplexAgent100K".into(),
Box::new(|piece| {
Box::new(ComplexAgent::new(
piece,
FutureMoveConfig {
max_depth: 20,
min_arena_depth: 14,
top_k_children: 2,
up_to_minus: 10,
max_arena_size: 100_000,
do_not_prune: false,
print: false,
..FMV_BASE
},
))
}),
1,
),
(
"ComplexAgent500K".into(),
Box::new(|piece| {
Box::new(ComplexAgent::new(
piece,
FutureMoveConfig {
max_arena_size: 500_000,
..FMV_BASE
},
))
}),
1,
),
(
"ComplexAgent1M".into(),
Box::new(|piece| {
Box::new(ComplexAgent::new(
piece,
FutureMoveConfig {
max_arena_size: 1_000_000,
..FMV_BASE
},
))
}),
1,
),
// NO PRUNING :
(
"ComplexAgent100K_NOPRUNE".into(),
Box::new(|piece| {
Box::new(ComplexAgent::new(
piece,
FutureMoveConfig {
max_arena_size: 100_000,
do_not_prune: true,
..FMV_BASE
},
))
}),
1,
),
(
"ComplexAgent500K_NOPRUNE".into(),
Box::new(|piece| {
Box::new(ComplexAgent::new(
piece,
FutureMoveConfig {
max_arena_size: 500_000,
do_not_prune: true,
..FMV_BASE
},
))
}),
1,
),
(
"ComplexAgent1M_NOPRUNE".into(),
Box::new(|piece| {
Box::new(ComplexAgent::new(
piece,
FutureMoveConfig {
max_arena_size: 1_000_000,
do_not_prune: true,
..FMV_BASE
},
))
}),
1,
),
]);
for _ in 0..10 {
arena.play_two(0, 1);
// for _ in 0..100 {
// arena.prop_arena();
// }
for _ in 0..20 {
arena.play_all_against(0);
}
// for _ in 0..2 {
// arena.play_two(1, 2);
// }
println!("{}", arena);
}
pub struct PlayerArena {
players: Vec<(String, Box<dyn Fn(Piece) -> Box<dyn Agent>>, EloRating)>,
/// Name, Creator, Elo, freq (mod)
players: Vec<(
String,
Box<dyn Fn(Piece) -> Box<dyn Agent>>,
EloRating,
usize,
)>,
freq_map: Vec<usize>,
}
impl std::fmt::Display for PlayerArena {
@ -64,23 +157,68 @@ impl std::fmt::Display for PlayerArena {
}
impl PlayerArena {
pub fn new(players: Vec<(String, Box<dyn Fn(Piece) -> Box<dyn Agent>>)>) -> Self {
pub fn new(players: Vec<(String, Box<dyn Fn(Piece) -> Box<dyn Agent>>, usize)>) -> Self {
let len = players.len();
Self {
players: players
.into_iter()
.zip([EloRating::new()].into_iter().cycle())
.map(|((a, b), c)| (a, b, c))
.map(|((a, b, d), c)| (a, b, c, d))
.collect(),
freq_map: [0].repeat(len).to_vec(),
}
}
fn play_all_against(&mut self, i: usize) {
for j in 0..self.players.len() {
if i == j {
continue;
}
self.freq_map[i] += 1;
self.freq_map[j] += 1;
if self.freq_map[i] % self.players[i].3 != 0 {
continue;
}
if self.freq_map[j] % self.players[j].3 != 0 {
continue;
}
self.play_two(i, j);
}
}
fn prop_arena(&mut self) {
for i in 0..self.players.len() {
self.play_all_against(i);
}
}
fn play_two(&mut self, player1: usize, player2: usize) {
let result = GameInner::new(
self.players[player1].1(Piece::Black),
self.players[player2].1(Piece::White),
false,
)
.loop_until_result();
println!(
"{} vs {}...",
self.players[player1].0, self.players[player2].0
);
let (np1, np2) = Self::play_two_inner(
&self.players[player1].1,
&self.players[player2].1,
&self.players[player1].2,
&self.players[player2].2,
);
self.players[player1].2 = np1;
self.players[player2].2 = np2;
}
fn play_two_inner(
player_1_fn: &Box<dyn Fn(Piece) -> Box<dyn Agent>>,
player_2_fn: &Box<dyn Fn(Piece) -> Box<dyn Agent>>,
player_1_elo: &EloRating,
player_2_elo: &EloRating,
) -> (EloRating, EloRating) {
let result = GameInner::new(player_1_fn(Piece::Black), player_2_fn(Piece::White), false)
.loop_until_result();
let outcome = match result {
Winner::Player(piece) => match piece {
Piece::Black => Outcomes::WIN,
@ -89,13 +227,7 @@ impl PlayerArena {
Winner::Tie => Outcomes::DRAW,
Winner::None => panic!("somehow met None"),
};
let (np1, np2) = elo(
&self.players[player1].2,
&self.players[player2].2,
&outcome,
&EloConfig::new(),
);
self.players[player1].2 = np1;
self.players[player2].2 = np2;
elo(player_1_elo, player_2_elo, &outcome, &EloConfig::new())
}
}

View File

@ -1,7 +1,6 @@
use crate::{
agent::Agent,
game_inner::GameInner,
repr::{Board, Piece, Winner},
};
pub struct Game {