minimax/src/main.rs

134 lines
2.6 KiB
Rust
Raw Normal View History

2024-03-05 10:18:34 -08:00
use std::cmp::Ordering;
2024-03-04 17:46:05 -08:00
use anyhow::{bail, Result};
use termion::color::{self};
2024-02-26 08:54:35 -08:00
2024-03-03 21:48:33 -08:00
mod agents;
2024-02-26 08:54:35 -08:00
mod board;
mod util;
use board::Board;
use util::{Player, Symb};
fn play(
2024-03-04 17:46:05 -08:00
maxi: &mut dyn agents::MaximizerAgent,
2024-03-04 18:46:16 -08:00
maxi_player: Player,
2024-03-04 17:46:05 -08:00
mini: &mut dyn agents::MinimizerAgent,
2024-03-04 18:46:16 -08:00
mini_player: Player,
2024-02-26 08:54:35 -08:00
) -> Result<Board> {
2024-03-04 17:46:05 -08:00
let mut board = Board::new();
let mut is_first_turn = true;
let mut is_maxi_turn = true;
2024-03-04 15:49:40 -08:00
2024-03-04 17:46:05 -08:00
while !board.is_done() {
// Print board
println!(
"\r{}{}{}{}",
" ".repeat(6),
if is_first_turn { '╓' } else { '║' },
2024-03-05 10:18:34 -08:00
board.prettyprint()?,
2024-03-04 17:46:05 -08:00
if is_first_turn { '╖' } else { '║' },
);
is_first_turn = false;
2024-02-26 08:54:35 -08:00
2024-03-04 17:46:05 -08:00
// Take action
let action = if is_maxi_turn {
maxi.step_max(&board)?
2024-02-26 08:54:35 -08:00
} else {
2024-03-04 17:46:05 -08:00
mini.step_min(&board)?
2024-02-26 08:54:35 -08:00
};
2024-03-04 17:46:05 -08:00
if !board.play(
action,
if is_maxi_turn {
2024-03-04 18:46:16 -08:00
maxi_player
2024-03-04 15:49:40 -08:00
} else {
2024-03-04 18:46:16 -08:00
mini_player
2024-03-04 15:49:40 -08:00
},
2024-03-04 17:46:05 -08:00
) {
bail!("agent made invalid move")
2024-02-26 08:54:35 -08:00
}
2024-03-04 18:46:16 -08:00
is_maxi_turn = !is_maxi_turn;
2024-02-26 08:54:35 -08:00
}
2024-03-05 10:18:34 -08:00
println!("\r{}{}", " ".repeat(6), board.prettyprint()?);
2024-03-04 17:46:05 -08:00
println!("\r{}{}", " ".repeat(6), " ".repeat(board.size()));
Ok(board)
2024-02-26 08:54:35 -08:00
}
fn main() -> Result<()> {
2024-03-04 18:46:16 -08:00
rayon::ThreadPoolBuilder::new()
.num_threads(4)
.build_global()
.unwrap();
2024-03-04 17:46:05 -08:00
let mut maxi = agents::PlayerAgent::new(Player::Human);
2024-03-05 10:18:34 -08:00
let mut mini = agents::Diffuse {};
2024-02-26 08:54:35 -08:00
2024-03-04 18:46:16 -08:00
let a = play(&mut maxi, Player::Human, &mut mini, Player::Computer)?;
2024-02-26 08:54:35 -08:00
if a.is_done() {
println!(
"\r\n{}Your score:{} {:.2}\n\n",
color::Fg(Player::Human.color()),
color::Fg(color::Reset),
a.evaluate().unwrap()
);
} else {
println!(
"\r\n{}Quitting{}\r\n",
color::Fg(color::Red),
color::Fg(color::Reset),
);
return Ok(());
}
2024-03-05 10:18:34 -08:00
let mut mini = agents::PlayerAgent::new(Player::Human);
let mut maxi = agents::Diffuse {};
let b = play(&mut maxi, Player::Computer, &mut mini, Player::Human)?;
if b.is_done() {
println!(
"\r\n{}Computer score:{} {:.2}\n\n",
color::Fg(Player::Human.color()),
color::Fg(color::Reset),
b.evaluate().unwrap()
);
} else {
println!(
"\r\n{}Quitting{}\r\n",
color::Fg(color::Red),
color::Fg(color::Reset),
);
return Ok(());
}
match a.evaluate().partial_cmp(&b.evaluate()) {
Some(Ordering::Equal) => {
println!("\r\nTie");
}
Some(Ordering::Greater) => {
println!(
"\r\n{}Human wins{}",
color::Fg(Player::Human.color()),
color::Fg(color::Reset),
);
}
Some(Ordering::Less) => {
println!(
"\r\n{}Computer wins{}",
color::Fg(Player::Computer.color()),
color::Fg(color::Reset),
);
}
None => {
println!(
"\r\n{}Error{}",
color::Fg(color::Red),
color::Fg(color::Reset),
);
}
}
2024-02-26 08:54:35 -08:00
Ok(())
}