most basic best move search
This commit is contained in:
parent
af2178abad
commit
9d527634eb
7 changed files with 105 additions and 4 deletions
18
src/eval/basic.rs
Normal file
18
src/eval/basic.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
use crate::board::{Board, Color, PieceType};
|
||||
|
||||
pub fn evaluate_board(board: &Board) -> i32 {
|
||||
let mut score = 0_i32;
|
||||
score += board.pieces[PieceType::Pawn as usize][Color::White as usize].count_ones() as i32 * 100;
|
||||
score += board.pieces[PieceType::Knight as usize][Color::White as usize].count_ones() as i32 * 300;
|
||||
score += board.pieces[PieceType::Bishop as usize][Color::White as usize].count_ones() as i32 * 300;
|
||||
score += board.pieces[PieceType::Rook as usize][Color::White as usize].count_ones() as i32 * 500;
|
||||
score += board.pieces[PieceType::Queen as usize][Color::White as usize].count_ones() as i32 * 900;
|
||||
score += board.pieces[PieceType::King as usize][Color::White as usize].count_ones() as i32 * 10000;
|
||||
score -= board.pieces[PieceType::Pawn as usize][Color::Black as usize].count_ones() as i32 * 100;
|
||||
score -= board.pieces[PieceType::Knight as usize][Color::Black as usize].count_ones() as i32 * 300;
|
||||
score -= board.pieces[PieceType::Bishop as usize][Color::Black as usize].count_ones() as i32 * 300;
|
||||
score -= board.pieces[PieceType::Rook as usize][Color::Black as usize].count_ones() as i32 * 500;
|
||||
score -= board.pieces[PieceType::Queen as usize][Color::Black as usize].count_ones() as i32 * 900;
|
||||
score -= board.pieces[PieceType::King as usize][Color::Black as usize].count_ones() as i32 * 10000;
|
||||
score
|
||||
}
|
||||
1
src/eval/mod.rs
Normal file
1
src/eval/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod basic;
|
||||
|
|
@ -2,5 +2,7 @@ pub mod board;
|
|||
pub mod r#move;
|
||||
pub mod square;
|
||||
pub mod movegen;
|
||||
mod display;
|
||||
mod parsing;
|
||||
pub mod eval;
|
||||
pub mod display;
|
||||
pub mod parsing;
|
||||
pub mod search;
|
||||
|
|
|
|||
11
src/main.rs
11
src/main.rs
|
|
@ -2,8 +2,15 @@ use chess_engine::board::Board;
|
|||
use chess_engine::movegen::generate_pseudo_legal_moves;
|
||||
use chess_engine::movegen::legal_check::is_king_attacked;
|
||||
use chess_engine::r#move::*;
|
||||
|
||||
use chess_engine::search::minimax;
|
||||
use chess_engine::search::minimax::minimax;
|
||||
|
||||
fn main() {
|
||||
|
||||
let mut board = Board::from_fen("rnb1kbnr/pppppppp/8/8/8/4q3/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
|
||||
let (opt_move, _) = minimax(&mut board, 5);
|
||||
if let Some(mv) = opt_move {
|
||||
println!("Found best move: {}", mv)
|
||||
} else {
|
||||
println!("No moves found")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
17
src/move.rs
17
src/move.rs
|
|
@ -1,4 +1,5 @@
|
|||
use std::slice;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use crate::square::Square;
|
||||
use crate::board::PieceType;
|
||||
use crate::square::SQUARES;
|
||||
|
|
@ -103,6 +104,22 @@ impl MoveList {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for MoveList {
|
||||
type Output = Move;
|
||||
|
||||
#[inline(always)]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.moves[..self.count][index]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for MoveList {
|
||||
#[inline(always)]
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
&mut self.moves[..self.count][index]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UndoMove {
|
||||
pub mv: Move,
|
||||
pub captured_piece: Option<PieceType>,
|
||||
|
|
|
|||
55
src/search/minimax.rs
Normal file
55
src/search/minimax.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use crate::board::{Board, Color}; // <-- Assuming you have a Color enum (e.g., Color::White, Color::Black)
|
||||
use crate::eval::basic::evaluate_board;
|
||||
use crate::movegen::generate_pseudo_legal_moves;
|
||||
use crate::movegen::legal_check::is_king_attacked;
|
||||
use crate::r#move::{Move, MoveList};
|
||||
|
||||
|
||||
fn evaluate_board_relative(board: &Board) -> i32 {
|
||||
let static_eval = evaluate_board(board);
|
||||
match board.side_to_move {
|
||||
Color::White => static_eval,
|
||||
Color::Black => -static_eval,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn minimax(board: &mut Board, depth: u8) -> (Option<Move>, i32) {
|
||||
if depth == 0 {
|
||||
return (None, evaluate_board_relative(board));
|
||||
}
|
||||
|
||||
let mut list = MoveList::new();
|
||||
generate_pseudo_legal_moves(board, &mut list);
|
||||
let mut best_move: Option<Move> = None;
|
||||
let mut best_score: i32 = -i32::MAX;
|
||||
let mut legal_moves_found = false;
|
||||
|
||||
for mv in list.iter() {
|
||||
let undo_mv = board.make_move(*mv);
|
||||
let is_illegal = is_king_attacked(board);
|
||||
if is_illegal {
|
||||
board.undo_move(undo_mv);
|
||||
continue;
|
||||
}
|
||||
legal_moves_found = true;
|
||||
let (_, score) = minimax(board, depth - 1);
|
||||
let current_score = -score;
|
||||
|
||||
if current_score > best_score {
|
||||
best_score = current_score;
|
||||
best_move = Some(*mv);
|
||||
}
|
||||
|
||||
board.undo_move(undo_mv);
|
||||
}
|
||||
|
||||
if !legal_moves_found {
|
||||
if is_king_attacked(board) {
|
||||
return (None, -i32::MAX);
|
||||
} else {
|
||||
return (None, 0);
|
||||
}
|
||||
}
|
||||
|
||||
(best_move, best_score)
|
||||
}
|
||||
1
src/search/mod.rs
Normal file
1
src/search/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod minimax;
|
||||
Loading…
Add table
Add a link
Reference in a new issue