ai implemented, needs some perf tuning
This commit is contained in:
parent
8c4b0fc1cd
commit
05536f0dc3
7 changed files with 310 additions and 23 deletions
81
src/ai.rs
Normal file
81
src/ai.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use crate::{
|
||||
board::{Board, explode_board},
|
||||
game::{Game, Team},
|
||||
};
|
||||
|
||||
/// Using alpha-beta pruning and the minimax algorithm, determine the best move
|
||||
/// for a game with a recursion depth of `depth`.
|
||||
pub fn alphabeta(game: Game, depth: u8, mut alpha: i8, mut beta: i8) -> (Board, i8) {
|
||||
if depth == 0 {
|
||||
return (0, game.score().diff());
|
||||
}
|
||||
let moves = game.available();
|
||||
if moves == 0 {
|
||||
return (0, game.score().diff());
|
||||
}
|
||||
|
||||
let mut best_move: Board = 0;
|
||||
// I just establish a convention of maximizing for black and minimizing for white.
|
||||
// I'm not sure if that's conventional or not, but it's what I chose.
|
||||
match game.current_team {
|
||||
Team::Black => {
|
||||
for mv in explode_board(moves) {
|
||||
let mut g = game.clone();
|
||||
g.play(mv);
|
||||
// maximize for the evaluation of subsequent moves
|
||||
let evaluation = alphabeta(g, depth - 1, alpha, beta).1;
|
||||
if evaluation > alpha {
|
||||
alpha = evaluation;
|
||||
best_move = mv;
|
||||
};
|
||||
if beta <= alpha {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(best_move, alpha)
|
||||
}
|
||||
Team::White => {
|
||||
for mv in explode_board(moves) {
|
||||
let mut g = game.clone();
|
||||
g.play(mv);
|
||||
// maximize for the evaluation of subsequent moves
|
||||
let evaluation = alphabeta(g, depth - 1, alpha, beta).1;
|
||||
if evaluation < beta {
|
||||
beta = evaluation;
|
||||
best_move = mv;
|
||||
};
|
||||
if beta <= alpha {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(best_move, beta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::board::view::View;
|
||||
use crate::board::{BitBoard, squares::*};
|
||||
use crate::game::Game;
|
||||
|
||||
#[test]
|
||||
// just a sanity check to ensure that my AI performs up to snuff with another popular engine
|
||||
fn opening() {
|
||||
let mut game = Game::default();
|
||||
|
||||
println!("{}", game.board().render(View::RankAsc, vec![]));
|
||||
game.play(D3);
|
||||
let (best_move, _) = alphabeta(game.clone(), 12, i8::MIN + 1, i8::MAX - 1);
|
||||
println!(
|
||||
"dis:\n{}",
|
||||
BitBoard {
|
||||
boards: [0, best_move]
|
||||
}
|
||||
);
|
||||
game.play(best_move);
|
||||
println!("{}", game.board().render(View::RankAsc, vec![]));
|
||||
assert_eq!(best_move, C3);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue