diff --git a/src/elo.rs b/src/elo.rs index 78d8bb0..a17350e 100644 --- a/src/elo.rs +++ b/src/elo.rs @@ -5,6 +5,7 @@ use crate::{ logic::FutureMoveConfig, repr::{Piece, Winner}, }; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; use skillratings::{ elo::{elo, EloConfig, EloRating}, Outcomes, Rating, @@ -114,14 +115,28 @@ impl PlayerArena { } } - fn play_all_against(&mut self, i: usize) { - for j in 0..self.players.len() { - if i == j { - continue; - } + fn play(&mut self, pairs: &[(usize, usize)]) { + pairs + .iter() + .map(|&(i, j)| { + ( + (i, j), + Self::create_agents(&self.players[i].1, &self.players[j].1), + ) + }) + .map(|((i, j), (p1, p2))| (i, j, Self::play_two_inner(p1, p2))) + .collect::>() + .into_iter() + .for_each(|(i, j, o)| self.process_outcome(i, j, &o)); + } - self.play_two(i, j); - } + fn play_all_against(&mut self, i: usize) { + self.play( + &(0..self.players.len()) + .zip([i].into_iter().cycle()) + .filter(|(i, j)| i != j) + .collect::>(), + ) } fn prop_arena(&mut self) { @@ -130,30 +145,38 @@ impl PlayerArena { } } - fn play_two(&mut self, player1: usize, player2: usize) { - println!( - "{} vs {}...", - self.players[player1].0, self.players[player2].0 - ); - - let outcome = Self::play_two_inner(&self.players[player1].1, &self.players[player2].1); - + fn process_outcome(&mut self, player1: usize, player2: usize, outcome: &Outcomes) { let (np1, np2) = elo( &self.players[player1].2, &self.players[player2].2, - &outcome, + outcome, &EloConfig::new(), ); self.players[player1].2 = np1; self.players[player2].2 = np2; } - fn play_two_inner( + fn play_two(&mut self, player1: usize, player2: usize) { + println!( + "{} vs {}...", + self.players[player1].0, self.players[player2].0 + ); + + let (p1, p2) = Self::create_agents(&self.players[player1].1, &self.players[player2].1); + + let outcome = Self::play_two_inner(p1, p2); + self.process_outcome(player1, player2, &outcome); + } + + fn create_agents( player_1_fn: &Box Box>, player_2_fn: &Box Box>, - ) -> Outcomes { - let result = GameInner::new(player_1_fn(Piece::Black), player_2_fn(Piece::White), false) - .loop_until_result(); + ) -> (Box, Box) { + (player_1_fn(Piece::Black), player_2_fn(Piece::White)) + } + + fn play_two_inner(player_1: Box, player_2: Box) -> Outcomes { + let result = GameInner::new(player_1, player_2, false).loop_until_result(); match result { Winner::Player(piece) => match piece {