"Stuff"
parent
289d77d822
commit
f856c15a61
@ -1,98 +1,156 @@
|
||||
use rand::prelude::*;
|
||||
use std::f64::{INFINITY, NEG_INFINITY};
|
||||
|
||||
use chess::{Board, BoardStatus, ChessMove, Color, MoveGen, Piece};
|
||||
|
||||
pub fn eval_board(
|
||||
fn static_board_eval(
|
||||
mov: ChessMove,
|
||||
board: Board,
|
||||
playing_as: Color,
|
||||
curr_depth: u8,
|
||||
move_history: Vec<(ChessMove, Board)>,
|
||||
) -> i128 {
|
||||
let mut current_eval: i128 = 0;
|
||||
) -> f64 {
|
||||
if move_history.len() > 6 {
|
||||
if move_history[move_history.len() - 1].0 == mov
|
||||
&& move_history[move_history.len() - 2].0 == mov
|
||||
{
|
||||
return -666.0;
|
||||
}
|
||||
}
|
||||
|
||||
let moves_iter = MoveGen::new_legal(&board).into_iter();
|
||||
let mut current_eval = 0.0;
|
||||
|
||||
moves_iter.for_each(|mov| {
|
||||
let tmp_board = board.make_move_new(mov);
|
||||
// basic material counting
|
||||
board.color_combined(playing_as).for_each(|square| {
|
||||
match board.piece_on(square) {
|
||||
Some(Piece::Pawn) => current_eval += 1.0,
|
||||
Some(Piece::Knight) => current_eval += 3.0,
|
||||
Some(Piece::Bishop) => current_eval += 5.0,
|
||||
Some(Piece::Rook) => current_eval += 5.0,
|
||||
Some(Piece::Queen) => current_eval += 8.0,
|
||||
_ => { /* do nothing */ }
|
||||
}
|
||||
});
|
||||
|
||||
// force it to not draw (and cockblock someone trying *to* draw)
|
||||
if move_history.len() > 6 {
|
||||
if move_history[move_history.len() - 2].0 == mov
|
||||
&& move_history[move_history.len() - 6].0 == mov
|
||||
{
|
||||
current_eval -= 6666666666666666666666666666;
|
||||
return;
|
||||
}
|
||||
board.color_combined(!playing_as).for_each(|square| {
|
||||
match board.piece_on(square) {
|
||||
Some(Piece::Pawn) => current_eval -= 1.0,
|
||||
Some(Piece::Knight) => current_eval -= 3.0,
|
||||
Some(Piece::Bishop) => current_eval -= 5.0,
|
||||
Some(Piece::Rook) => current_eval -= 5.0,
|
||||
Some(Piece::Queen) => current_eval -= 8.0,
|
||||
_ => { /* do nothing */ }
|
||||
}
|
||||
});
|
||||
|
||||
// basic material counting
|
||||
tmp_board.color_combined(playing_as).for_each(|square| {
|
||||
match tmp_board.piece_on(square) {
|
||||
Some(Piece::Pawn) => current_eval += 1,
|
||||
Some(Piece::Knight) => current_eval += 3,
|
||||
Some(Piece::Bishop) => current_eval += 5,
|
||||
Some(Piece::Rook) => current_eval += 5,
|
||||
Some(Piece::Queen) => current_eval += 8,
|
||||
_ => { /* do nothing */ }
|
||||
// checking heuristic
|
||||
let mut are_we_in_check = false;
|
||||
let mut is_opponent_in_check = false;
|
||||
board
|
||||
.checkers()
|
||||
.filter(|sq| board.color_on(*sq).unwrap() == playing_as)
|
||||
.for_each(|_| {
|
||||
if !are_we_in_check {
|
||||
current_eval -= 66.6;
|
||||
are_we_in_check = true;
|
||||
} else {
|
||||
current_eval -= 12.5;
|
||||
}
|
||||
});
|
||||
|
||||
tmp_board.color_combined(!playing_as).for_each(|square| {
|
||||
match tmp_board.piece_on(square) {
|
||||
Some(Piece::Pawn) => current_eval -= 1,
|
||||
Some(Piece::Knight) => current_eval -= 3,
|
||||
Some(Piece::Bishop) => current_eval -= 5,
|
||||
Some(Piece::Rook) => current_eval -= 5,
|
||||
Some(Piece::Queen) => current_eval -= 8,
|
||||
_ => { /* do nothing */ }
|
||||
board
|
||||
.checkers()
|
||||
.filter(|sq| board.color_on(*sq).unwrap() == !playing_as)
|
||||
.for_each(|_| {
|
||||
if !is_opponent_in_check
|
||||
&& move_history.len()
|
||||
> *vec![10, 11, 12, 13, 14, 15]
|
||||
.choose(&mut rand::thread_rng())
|
||||
.unwrap() as usize
|
||||
{
|
||||
current_eval += 17.5;
|
||||
is_opponent_in_check = true;
|
||||
} else {
|
||||
current_eval += 3.5;
|
||||
}
|
||||
});
|
||||
|
||||
// checking heuristic
|
||||
let mut are_we_in_check = false;
|
||||
let mut is_opponent_in_check = false;
|
||||
tmp_board
|
||||
.checkers()
|
||||
.filter(|sq| tmp_board.color_on(*sq).unwrap() == playing_as)
|
||||
.for_each(|_| {
|
||||
if !are_we_in_check {
|
||||
current_eval -= 666;
|
||||
are_we_in_check = true;
|
||||
} else {
|
||||
current_eval -= 15;
|
||||
}
|
||||
});
|
||||
tmp_board
|
||||
.checkers()
|
||||
.filter(|sq| tmp_board.color_on(*sq).unwrap() == !playing_as)
|
||||
.for_each(|_| {
|
||||
if !is_opponent_in_check {
|
||||
current_eval += 15;
|
||||
is_opponent_in_check = true;
|
||||
} else {
|
||||
current_eval += 5;
|
||||
}
|
||||
});
|
||||
// deprioritize king movement
|
||||
if board.piece_on(mov.get_source()).unwrap_or(Piece::Pawn) == Piece::King && !are_we_in_check {
|
||||
current_eval -= 12.5;
|
||||
}
|
||||
|
||||
// die
|
||||
if tmp_board.status() == BoardStatus::Checkmate && tmp_board.side_to_move() == playing_as {
|
||||
current_eval -= 666_666;
|
||||
}
|
||||
current_eval
|
||||
}
|
||||
|
||||
// go for checkmate
|
||||
if tmp_board.status() == BoardStatus::Checkmate && tmp_board.side_to_move() == !playing_as {
|
||||
current_eval += 666_666;
|
||||
}
|
||||
pub fn eval_board(
|
||||
board: Board,
|
||||
is_maximizing_player: bool,
|
||||
depth: u8,
|
||||
move_history: Vec<(ChessMove, Board)>,
|
||||
last_move: Option<ChessMove>,
|
||||
original_playing_as: Color,
|
||||
mut alpha: f64,
|
||||
mut beta: f64,
|
||||
) -> f64 {
|
||||
let moves_iter = MoveGen::new_legal(&board).into_iter();
|
||||
|
||||
// deprioritize king movement
|
||||
if board.piece_on(mov.get_source()).unwrap() == Piece::King && !are_we_in_check {
|
||||
current_eval -= 10;
|
||||
}
|
||||
if depth == 0 || board.status() == BoardStatus::Checkmate {
|
||||
return static_board_eval(
|
||||
last_move.unwrap_or(move_history.last().unwrap().0),
|
||||
board,
|
||||
original_playing_as,
|
||||
move_history,
|
||||
);
|
||||
} else {
|
||||
if is_maximizing_player {
|
||||
let mut max_eval = NEG_INFINITY;
|
||||
for mov in moves_iter {
|
||||
let mut new_move_history = move_history.clone();
|
||||
|
||||
if curr_depth != 0 {
|
||||
let mut new_move_history = move_history.clone();
|
||||
new_move_history.push((mov, tmp_board));
|
||||
current_eval += eval_board(tmp_board, playing_as, curr_depth - 1, new_move_history);
|
||||
}
|
||||
});
|
||||
let new_board = board.make_move_new(mov);
|
||||
new_move_history.push((mov, new_board));
|
||||
|
||||
return current_eval;
|
||||
let eval = eval_board(
|
||||
new_board,
|
||||
false,
|
||||
depth - 1,
|
||||
new_move_history,
|
||||
Some(mov),
|
||||
original_playing_as,
|
||||
alpha,
|
||||
beta,
|
||||
);
|
||||
max_eval = max_eval.max(eval);
|
||||
alpha = alpha.max(eval);
|
||||
if beta <= alpha {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return max_eval;
|
||||
} else {
|
||||
let mut min_eval = INFINITY;
|
||||
for mov in moves_iter {
|
||||
let mut new_move_history = move_history.clone();
|
||||
|
||||
let new_board = board.make_move_new(mov);
|
||||
new_move_history.push((mov, new_board));
|
||||
|
||||
let eval = eval_board(
|
||||
new_board,
|
||||
true,
|
||||
depth - 1,
|
||||
new_move_history,
|
||||
Some(mov),
|
||||
original_playing_as,
|
||||
alpha,
|
||||
beta,
|
||||
);
|
||||
min_eval = min_eval.min(eval);
|
||||
beta = beta.min(eval);
|
||||
if beta <= alpha {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return min_eval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in new issue