use crate::{ agent::{Agent, RandomAgent}, complexagent::ComplexAgent, game_inner::GameInner, logic::FutureMoveConfig, repr::{Piece, Winner}, }; use skillratings::{ elo::{elo, EloConfig, EloRating}, Outcomes, Rating, }; pub fn run() { let mut arena = PlayerArena::new(vec![ ( "RandomAgent".into(), Box::new(|piece| Box::new(RandomAgent::new(piece))), ), ( "ComplexAgentBasic".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, }, )) }), ), ]); for _ in 0..10 { arena.play_two(0, 1); } println!("{}", arena); } pub struct PlayerArena { players: Vec<(String, Box Box>, EloRating)>, } impl std::fmt::Display for PlayerArena { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut players_i: Vec = (0..self.players.len()).collect(); players_i.sort_by_key(|&i| -(self.players[i].2.rating() * 100.0) as i64); for i in players_i { writeln!( f, "({:.2}): {}", self.players[i].2.rating(), self.players[i].0 )?; } Ok(()) } } impl PlayerArena { pub fn new(players: Vec<(String, Box Box>)>) -> Self { Self { players: players .into_iter() .zip([EloRating::new()].into_iter().cycle()) .map(|((a, b), c)| (a, b, c)) .collect(), } } 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(); let outcome = match result { Winner::Player(piece) => match piece { Piece::Black => Outcomes::WIN, Piece::White => Outcomes::LOSS, }, 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; } }