117 lines
3.2 KiB
Rust
117 lines
3.2 KiB
Rust
use crate::board;
|
|
use crate::rand::Rng;
|
|
|
|
impl board::PieceType {
|
|
fn value(&self) -> f32 {
|
|
match self {
|
|
board::PieceType::Pawn => 1.0,
|
|
board::PieceType::Knight => 3.0,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Move_ {
|
|
pub source: board::Position,
|
|
pub target: board::Position,
|
|
}
|
|
|
|
pub struct Engine {
|
|
board: board::Board,
|
|
}
|
|
|
|
impl Engine {
|
|
pub fn new() -> Self {
|
|
let mut board = board::Board::new();
|
|
board.reset();
|
|
Engine {
|
|
board,
|
|
}
|
|
}
|
|
pub fn reset(&mut self) {
|
|
self.board.reset()
|
|
}
|
|
pub fn get_state(&self) -> &board::Board {
|
|
&self.board
|
|
}
|
|
pub fn set_state(&mut self, board: board::Board) {
|
|
self.board = board;
|
|
}
|
|
pub fn get_legal_moves(
|
|
&self,
|
|
position: &board::Position,
|
|
) -> Result<impl Iterator<Item = board::Position> + '_, ()> {
|
|
Ok(self
|
|
.board
|
|
.find_moves(position)?
|
|
.chain(self.board.find_captures(position)?))
|
|
}
|
|
pub fn make_move(
|
|
&mut self,
|
|
source: &board::Position,
|
|
target: board::Position,
|
|
) -> Result<(), ()> {
|
|
if !self.get_legal_moves(source)?.any(|pos| pos == target) {
|
|
Err(())
|
|
} else {
|
|
// We checked that there is a piece at source in get_legal_moves
|
|
self.board.relocate(source, target)
|
|
}
|
|
}
|
|
pub fn evaluate_position(&self, board: &board::Board) -> f32 {
|
|
board
|
|
.iter()
|
|
.map(|(_, piece)| match piece.color {
|
|
board::Color::White => 1.0,
|
|
board::Color::Black => -1.0,
|
|
} * piece.piece_type.value())
|
|
.sum()
|
|
}
|
|
pub fn evaluate_move(
|
|
&self,
|
|
color: &board::Color,
|
|
move_: &Move_,
|
|
) -> Result<f32, ()> {
|
|
let mut board = self.board.clone();
|
|
board.relocate(&move_.source, move_.target.clone())?;
|
|
Ok(match color {
|
|
board::Color::White => 1.0,
|
|
board::Color::Black => -1.0,
|
|
} * self.evaluate_position(&board))
|
|
}
|
|
pub fn choose_move(&self, color: &board::Color) -> Option<Move_> {
|
|
let all_moves = self
|
|
.board
|
|
.iter()
|
|
.filter_map(|(source, piece)| {
|
|
if &piece.color == color {
|
|
if let Ok(targets) = self.get_legal_moves(source) {
|
|
Some(targets.map(|target| Move_ {
|
|
source: source.clone(),
|
|
target,
|
|
}))
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.flatten();
|
|
let mut rng = rand::thread_rng();
|
|
Some(
|
|
all_moves
|
|
.map(|move_| {
|
|
(
|
|
self.evaluate_move(color, &move_).unwrap()
|
|
+ rng.gen::<f32>() * 0.1,
|
|
move_,
|
|
)
|
|
})
|
|
.max_by(|(score1, _), (score2, _)| {
|
|
score1.partial_cmp(score2).unwrap()
|
|
})?
|
|
.1,
|
|
)
|
|
}
|
|
}
|