#![feature(custom_test_frameworks)] #![test_runner(criterion::runner)] use std::time::Duration; use criterion::{black_box, Criterion}; use criterion_macro::criterion; use ncpig::prelude::*; use ncpig_testing::dots_and_boxes::*; use ncpig_testing::number_claim::*; use ncpig_testing::rolit::*; use ncpig_testing::tic_tac_toe::*; fn config() -> Criterion { Criterion::default().noise_threshold(0.05) } macro_rules! bench_game_algo { ($group:expr, $game:expr, $state:expr, [$($name:expr => $algo:expr),* $(,)?]) => {{ $( let game = $game.clone(); let state = $state.clone(); $group.bench_function($name, |b| b.iter(|| black_box($algo.choose_action(&game, &state).unwrap()))); )* }}; } #[criterion(config())] fn tic_tac_toe(c: &mut Criterion) { let mut group = c.benchmark_group("tic_tac_toe"); bench_game_algo!( group, TicTacToe, TicTacToeState::default(), [ "random" => Random::default(), "maxn-no-pruning" => MaxN::default(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn number_claim_3pool_2player(c: &mut Criterion) { let mut group = c.benchmark_group("number_claim_3pool_2player"); bench_game_algo!( group, NumberClaim::<2, 3>::new([4, 7, 10]).unwrap(), NumberClaimState::default(), [ "random" => Random::default(), "maxn-no-pruning" => MaxN::default(), "maxn-with-pruning" => MaxN::builder().pruning(30).build(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn number_claim_6pool_3player(c: &mut Criterion) { let mut group = c.benchmark_group("number_claim_6pool_3player"); bench_game_algo!( group, NumberClaim::<3, 6>::new([4, 7, 10, 12, 13, 18]).unwrap(), NumberClaimState::default(), [ "random" => Random::default(), "maxn-no-pruning" => MaxN::default(), "maxn-with-pruning" => MaxN::builder().pruning(91).build(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn dots_boxes_3x2_2player(c: &mut Criterion) { let mut group = c.benchmark_group("dots_boxes_3x2_2player"); bench_game_algo!( group, DotsAndBoxes::<2, 3, 2>::new([DotsAndBoxesPlayer::Red, DotsAndBoxesPlayer::Blue]), DotsAndBoxesState::default(), [ "random" => Random::default(), "maxn-no-pruning" => MaxN::default(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn dots_boxes_3x2_3player(c: &mut Criterion) { let mut group = c.benchmark_group("dots_boxes_3x2_3player"); bench_game_algo!( group, DotsAndBoxes::<3, 3, 2>::new([DotsAndBoxesPlayer::Red, DotsAndBoxesPlayer::Blue, DotsAndBoxesPlayer::Green]), DotsAndBoxesState::default(), [ "random" => Random::default(), "maxn-no-pruning" => MaxN::default(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn rolit_2player(c: &mut Criterion) { let mut group = c.benchmark_group("rolit_2player"); bench_game_algo!( group, Rolit::new([RolitPlayer::Red, RolitPlayer::Green]), RolitState::default(), [ "random" => Random::default(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn rolit_3player(c: &mut Criterion) { let mut group = c.benchmark_group("rolit_3player"); bench_game_algo!( group, Rolit::new([RolitPlayer::Red, RolitPlayer::Green, RolitPlayer::Blue]), RolitState::default(), [ "random" => Random::default(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); } #[criterion(config())] fn rolit_4player(c: &mut Criterion) { let mut group = c.benchmark_group("rolit_4player"); bench_game_algo!( group, Rolit::new([RolitPlayer::Red, RolitPlayer::Green, RolitPlayer::Blue, RolitPlayer::Yellow]), RolitState::default(), [ "random" => Random::default(), "mcts-100it-uct0.7-greedy-random-winrate-mostvisits" => MonteCarloTreeSearch::builder() .max_time(Duration::from_secs(10)) .max_iters(100) .selection(UCT::new(0.7, None)) .expansion(Greedy) .playout(Random::default()) .backpropagation(WinRate) .final_scorer(NumVisits) .build::() ] ); group.finish(); }