ai implemented, needs some perf tuning

This commit is contained in:
jackjohn7 2025-11-08 05:50:32 -06:00
parent 8c4b0fc1cd
commit 05536f0dc3
7 changed files with 310 additions and 23 deletions

81
src/ai.rs Normal file
View 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);
}
}