diff --git a/rs/Cargo.lock b/rs/Cargo.lock index 383b290..2172aa1 100644 --- a/rs/Cargo.lock +++ b/rs/Cargo.lock @@ -2,6 +2,84 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + [[package]] name = "schach" version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/rs/Cargo.toml b/rs/Cargo.toml index ea53fc3..eb29450 100644 --- a/rs/Cargo.toml +++ b/rs/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +rand = "0.8.4" diff --git a/rs/src/board.rs b/rs/src/board.rs index ced1619..18c2a8b 100644 --- a/rs/src/board.rs +++ b/rs/src/board.rs @@ -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) } diff --git a/rs/src/engine.rs b/rs/src/engine.rs index 053d0b4..3c0082c 100644 --- a/rs/src/engine.rs +++ b/rs/src/engine.rs @@ -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, ()> { - Ok(self - .board - .find_moves(position)? - .chain(self.board.find_captures(position)?) - .collect()) + ) -> Result + '_, ()> { + 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()) + } } diff --git a/rs/src/main.rs b/rs/src/main.rs index e97219f..7cb225d 100644 --- a/rs/src/main.rs +++ b/rs/src/main.rs @@ -1,3 +1,4 @@ +extern crate rand; mod board; mod engine; mod ui; diff --git a/rs/src/ui.rs b/rs/src/ui.rs index f041103..84f591c 100644 --- a/rs/src/ui.rs +++ b/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 { + if let [color_str] = args { + if let [color_char] = color_str.chars().collect::>()[..] + { + 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 { 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()), }