diff --git a/src/parser.rs b/src/parser.rs
index 6dbee0c..2c0cb88 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -14,7 +14,7 @@
// along with this program. If not, see .
use crate::error::Error;
-use crate::types::{Action, Color, ColorDigit, Digit, GameAction, ReplAction, Slot, Slots};
+use crate::types::{Action, Card, Color, ColorDigit, Digit, GameAction, ReplAction, Slot, Slots};
use nom::{
branch::alt,
bytes::complete::tag,
@@ -23,6 +23,7 @@ use nom::{
multi::many0,
IResult,
};
+use std::convert::TryFrom;
use std::str::FromStr;
fn parse_color(i: &str) -> IResult<&str, ColorDigit> {
@@ -61,9 +62,24 @@ fn parse_digit(i: &str) -> IResult<&str, ColorDigit> {
Ok((i, digit.into()))
}
+fn parse_card(i: &str) -> IResult<&str, Card> {
+ let (i, color) = parse_color(i)?;
+ let (i, _) = space0(i)?;
+ let (i, digit) = parse_digit(i)?;
+ Ok((
+ i,
+ Card {
+ digit: Digit::try_from(digit).unwrap(),
+ color: Color::try_from(color).unwrap(),
+ },
+ ))
+}
+
fn parse_play(i: &str) -> IResult<&str, GameAction> {
let (i, _) = alt((tag("play"), tag("p")))(i)?;
let (i, _) = space1(i)?;
+ let (i, card) = parse_card(i)?;
+ let (i, _) = space1(i)?;
let (i, slot) = digit1(i)?;
let slot = slot
@@ -74,7 +90,7 @@ fn parse_play(i: &str) -> IResult<&str, GameAction> {
return Err(nom::Err::Error(NomError::new("", ErrorKind::IsA)));
}
- Ok((i, GameAction::PlayCard(slot)))
+ Ok((i, GameAction::PlayCard(card, slot)))
}
fn parse_slot(i: &str) -> IResult<&str, Slot> {
@@ -110,9 +126,11 @@ fn parse_slots1(i: &str) -> IResult<&str, Slots> {
fn parse_drop(i: &str) -> IResult<&str, GameAction> {
let (i, _) = alt((tag("drop"), tag("d")))(i)?;
let (i, _) = space1(i)?;
+ let (i, card) = parse_card(i)?;
+ let (i, _) = space1(i)?;
let (i, slot) = parse_slot(i)?;
- Ok((i, GameAction::DropCard(slot)))
+ Ok((i, GameAction::DropCard(card, slot)))
}
fn parse_hint(i: &str) -> IResult<&str, GameAction> {
diff --git a/src/types.rs b/src/types.rs
index a1fd27c..9199812 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -13,6 +13,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+use std::convert::TryFrom;
use std::fmt;
use std::ops::Deref;
use std::str::FromStr;
@@ -150,11 +151,51 @@ impl From for ColorDigit {
}
}
+impl TryFrom for Digit {
+ type Error = Error;
+
+ fn try_from(cd: ColorDigit) -> Result {
+ Ok(match cd {
+ ColorDigit::Digit(d) => d,
+ ColorDigit::Color(c) => return Err(Error::ParseDigitError(c.to_string())),
+ })
+ }
+}
+
+impl TryFrom for Color {
+ type Error = Error;
+
+ fn try_from(cd: ColorDigit) -> Result {
+ Ok(match cd {
+ ColorDigit::Color(c) => c,
+ ColorDigit::Digit(d) => return Err(Error::ParseColorError(d.to_string())),
+ })
+ }
+}
+
/// A card
#[derive(Clone, Debug, PartialEq)]
pub struct Card {
pub digit: Digit,
- pub color: Option,
+ pub color: Color,
+}
+
+impl fmt::Display for Card {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}{}",
+ match self.color {
+ Color::Blue => "b",
+ Color::Green => "g",
+ Color::Purple => "p",
+ Color::Red => "r",
+ Color::White => "w",
+ Color::Yellow => "y",
+ },
+ self.digit
+ )
+ }
}
/// Position in a player's hand
@@ -197,8 +238,8 @@ impl fmt::Display for Slots {
/// Possible actions during the game
#[derive(Clone, Debug, PartialEq)]
pub enum GameAction {
- PlayCard(Slot),
- DropCard(Slot),
+ PlayCard(Card, Slot),
+ DropCard(Card, Slot),
ColorHint(Slots, Color),
DigitHint(Slots, Digit),
}
@@ -215,8 +256,8 @@ impl From<(ColorDigit, Slots)> for GameAction {
impl fmt::Display for GameAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- GameAction::PlayCard(c) => write!(f, "play {}", c),
- GameAction::DropCard(c) => write!(f, "drop {}", c),
+ GameAction::PlayCard(card, slot) => write!(f, "play {} {}", card, slot),
+ GameAction::DropCard(card, slot) => write!(f, "drop {} {}", card, slot),
GameAction::ColorHint(slots, c) => write!(f, "hint {} {}", c, slots),
GameAction::DigitHint(slots, d) => write!(f, "hint {} {}", d, slots),
}