aboutsummaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs64
1 files changed, 45 insertions, 19 deletions
diff --git a/src/parser.rs b/src/parser.rs
index a1d9a32..73457f0 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,6 +1,6 @@
use crate::game::*;
-fn parse_move(player: Player, mv: &str) -> Result<Action, String> {
+fn parse_move(mv: &str, game: &Game) -> Result<Action, String> {
let mut chars = mv.chars();
let c = chars.next();
@@ -9,19 +9,28 @@ fn parse_move(player: Player, mv: &str) -> Result<Action, String> {
}
let dc = c.unwrap();
- if (dc < '1') || ('9' < dc) {
- return Err(String::from(
- "Moves must begin with a digit in 1-8 indicating the number of drops.",
- ));
- }
- let sum_drops = dc.to_digit(10).unwrap();
+ let sum_drops: u8;
+ let x;
+ if (dc >= 'a') && (dc <= 'h') {
+ // Drop number omitted, must be 1 drop.
+ sum_drops = 1;
+ x = dc;
+ } else {
+ if (dc < '1') || ('9' < dc) {
+ return Err(String::from(
+ "Moves must begin with a digit in 1-8 indicating the number of drops.",
+ ));
+ }
+ sum_drops = dc.to_digit(10).unwrap() as u8;
- let c = chars.next();
- if c.is_none() {
- return Err(String::from("Moves must specify a stack position."));
+ let c = chars.next();
+ if c.is_none() {
+ return Err(String::from("Moves must specify a stack position."));
+ }
+
+ x = c.unwrap();
}
- let x = c.unwrap();
if (x < 'a') || (x > 'h') {
return Err(String::from(
"Moves must specify a valid position on the game board.",
@@ -48,7 +57,9 @@ fn parse_move(player: Player, mv: &str) -> Result<Action, String> {
}
let c = c.unwrap();
- let dir; // This is so cool! Rust supports some very nice patterns!
+ // This is so cool! Rust supports some very nice patterns, and
+ // checks for uninitialised variables too!
+ let dir;
match c {
'+' => dir = Direction::Up,
'-' => dir = Direction::Down,
@@ -75,17 +86,28 @@ fn parse_move(player: Player, mv: &str) -> Result<Action, String> {
}
let sum = drops.iter().map(|&d| d as u32).sum::<u32>();
- if sum != sum_drops {
+ let pos = Position { x: x, y: y };
+ if sum == 0 {
+ // Omitted all the drops, it's a total stack move
+ drops.push(0);
+ if let Some(stack) = game.query_square(&pos) {
+ drops.push(std::cmp::min(stack.len() as u8, game.get_size()));
+ } else {
+ return Err(String::from(
+ "Moves must specify a valid position on the game board.",
+ ));
+ }
+ } else if sum != sum_drops as u32 {
return Err(format!(
"The move called for {} stones, but {} were dropped.",
sum_drops, sum
));
}
- Ok(Action::Move(player, Position { x: x, y: y }, dir, drops))
+ Ok(Action::Move(game.query_stone_owner(), pos, dir, drops))
}
-fn parse_place(player: Player, pl: &str) -> Result<Action, String> {
+fn parse_place(pl: &str, game: &Game) -> Result<Action, String> {
let mut chars = pl.chars();
let c = chars.next();
@@ -139,16 +161,20 @@ fn parse_place(player: Player, pl: &str) -> Result<Action, String> {
}
let y: u8 = (y.to_digit(10).unwrap() - 1) as u8;
- Ok(Action::Place(player, Position { x: x, y: y }, stone))
+ Ok(Action::Place(
+ game.query_stone_owner(),
+ Position { x: x, y: y },
+ stone,
+ ))
}
-pub fn parse_action(player: Player, act: &str) -> Result<Action, String> {
+pub fn parse_action(game: &Game, act: &str) -> Result<Action, String> {
if act
.chars()
.any(|c| c == '+' || c == '-' || c == '>' || c == '<')
{
- parse_move(player, act)
+ parse_move(act, game)
} else {
- parse_place(player, act)
+ parse_place(act, game)
}
}