Implement dummy chess solver
It chooses a random available move ¯\_(ツ)_/¯
This commit is contained in:
@@ -247,6 +247,9 @@ impl Board {
|
||||
state: Default::default(),
|
||||
}
|
||||
}
|
||||
pub fn occupied(&self, position: &Position) -> bool {
|
||||
self.state.contains_key(position)
|
||||
}
|
||||
pub fn get_at(&self, position: &Position) -> Option<&Piece> {
|
||||
self.state.get(position)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::board;
|
||||
use rand::seq::IteratorRandom;
|
||||
|
||||
pub struct Engine {
|
||||
board: board::Board,
|
||||
@@ -21,23 +22,47 @@ impl Engine {
|
||||
pub fn get_legal_moves(
|
||||
&self,
|
||||
position: &board::Position,
|
||||
) -> Result<Vec<board::Position>, ()> {
|
||||
Ok(self
|
||||
.board
|
||||
.find_moves(position)?
|
||||
.chain(self.board.find_captures(position)?)
|
||||
.collect())
|
||||
) -> Result<impl Iterator<Item = board::Position> + '_, ()> {
|
||||
if self.board.occupied(position) {
|
||||
Ok(self
|
||||
.board
|
||||
.find_moves(position)
|
||||
.unwrap()
|
||||
.chain(self.board.find_captures(position).unwrap()))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
pub fn make_move(
|
||||
&mut self,
|
||||
source: &board::Position,
|
||||
target: board::Position,
|
||||
) -> Result<(), ()> {
|
||||
if !self.get_legal_moves(source)?.contains(&target) {
|
||||
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 choose_move(
|
||||
&self,
|
||||
color: &board::Color,
|
||||
) -> Option<(board::Position, board::Position)> {
|
||||
self.board
|
||||
.iter()
|
||||
.filter_map(|(source, piece)| {
|
||||
if &piece.color == color {
|
||||
if let Ok(targets) = self.get_legal_moves(source) {
|
||||
Some(targets.map(|target| (source.clone(), target)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.choose(&mut rand::thread_rng())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
extern crate rand;
|
||||
mod board;
|
||||
mod engine;
|
||||
mod ui;
|
||||
|
||||
31
rs/src/ui.rs
31
rs/src/ui.rs
@@ -182,10 +182,9 @@ impl Ui {
|
||||
let error = format!("No moves possible from {}", position);
|
||||
Err(error)
|
||||
}
|
||||
Ok(positions) => Ok(positions
|
||||
.iter()
|
||||
.map(|pos| format!("{}", pos))
|
||||
.collect()),
|
||||
Ok(positions) => {
|
||||
Ok(positions.map(|pos| format!("{}", pos)).collect())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err("get_moves takes 1 arg".to_owned())
|
||||
@@ -208,6 +207,29 @@ impl Ui {
|
||||
Err("make_move takes 2 args".to_owned())
|
||||
}
|
||||
}
|
||||
fn choose_move(&self, args: &[&str]) -> Result<String, String> {
|
||||
if let [color_str] = args {
|
||||
if let [color_char] = color_str.chars().collect::<Vec<char>>()[..]
|
||||
{
|
||||
match self.engine.choose_move(
|
||||
&board::Color::parse(color_char).map_err(|_| {
|
||||
format!("Couldn't parse color code {}", color_char)
|
||||
})?,
|
||||
) {
|
||||
Some((source, target)) => {
|
||||
Ok(format!("{},{}", source, target))
|
||||
}
|
||||
None => {
|
||||
Err(format!("No move possible for {}", color_char))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(format!("Invalid color string {}", color_str))
|
||||
}
|
||||
} else {
|
||||
Err("choose_move takes 1 arg".to_owned())
|
||||
}
|
||||
}
|
||||
fn handle_command(&mut self, s: &str) -> Result<String, String> {
|
||||
let mut cmd = s.split(',');
|
||||
// There will be at least an empty string => otherwise panic
|
||||
@@ -218,6 +240,7 @@ impl Ui {
|
||||
"get_moves" => self.get_moves(&args),
|
||||
"make_move" => self.make_move(&args),
|
||||
"set_state" => self.set_state(&args),
|
||||
"choose_move" => self.choose_move(&args),
|
||||
"" => Err("No command given".to_owned()),
|
||||
_ => Err("Invalid command".to_owned()),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user