types: PlayCard and DropCard now require Card and Slot

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2022-08-09 18:28:16 +02:00
parent 3762856813
commit 098ce3a1d8
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2
2 changed files with 67 additions and 8 deletions

View file

@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::error::Error; 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::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::tag,
@ -23,6 +23,7 @@ use nom::{
multi::many0, multi::many0,
IResult, IResult,
}; };
use std::convert::TryFrom;
use std::str::FromStr; use std::str::FromStr;
fn parse_color(i: &str) -> IResult<&str, ColorDigit> { fn parse_color(i: &str) -> IResult<&str, ColorDigit> {
@ -61,9 +62,24 @@ fn parse_digit(i: &str) -> IResult<&str, ColorDigit> {
Ok((i, digit.into())) 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> { fn parse_play(i: &str) -> IResult<&str, GameAction> {
let (i, _) = alt((tag("play"), tag("p")))(i)?; let (i, _) = alt((tag("play"), tag("p")))(i)?;
let (i, _) = space1(i)?; let (i, _) = space1(i)?;
let (i, card) = parse_card(i)?;
let (i, _) = space1(i)?;
let (i, slot) = digit1(i)?; let (i, slot) = digit1(i)?;
let slot = slot let slot = slot
@ -74,7 +90,7 @@ fn parse_play(i: &str) -> IResult<&str, GameAction> {
return Err(nom::Err::Error(NomError::new("", ErrorKind::IsA))); 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> { 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> { fn parse_drop(i: &str) -> IResult<&str, GameAction> {
let (i, _) = alt((tag("drop"), tag("d")))(i)?; let (i, _) = alt((tag("drop"), tag("d")))(i)?;
let (i, _) = space1(i)?; let (i, _) = space1(i)?;
let (i, card) = parse_card(i)?;
let (i, _) = space1(i)?;
let (i, slot) = parse_slot(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> { fn parse_hint(i: &str) -> IResult<&str, GameAction> {

View file

@ -13,6 +13,7 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use std::convert::TryFrom;
use std::fmt; use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
@ -150,11 +151,51 @@ impl From<Digit> for ColorDigit {
} }
} }
impl TryFrom<ColorDigit> for Digit {
type Error = Error;
fn try_from(cd: ColorDigit) -> Result<Digit, Self::Error> {
Ok(match cd {
ColorDigit::Digit(d) => d,
ColorDigit::Color(c) => return Err(Error::ParseDigitError(c.to_string())),
})
}
}
impl TryFrom<ColorDigit> for Color {
type Error = Error;
fn try_from(cd: ColorDigit) -> Result<Color, Self::Error> {
Ok(match cd {
ColorDigit::Color(c) => c,
ColorDigit::Digit(d) => return Err(Error::ParseColorError(d.to_string())),
})
}
}
/// A card /// A card
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Card { pub struct Card {
pub digit: Digit, pub digit: Digit,
pub color: Option<Color>, 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 /// Position in a player's hand
@ -197,8 +238,8 @@ impl fmt::Display for Slots {
/// Possible actions during the game /// Possible actions during the game
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum GameAction { pub enum GameAction {
PlayCard(Slot), PlayCard(Card, Slot),
DropCard(Slot), DropCard(Card, Slot),
ColorHint(Slots, Color), ColorHint(Slots, Color),
DigitHint(Slots, Digit), DigitHint(Slots, Digit),
} }
@ -215,8 +256,8 @@ impl From<(ColorDigit, Slots)> for GameAction {
impl fmt::Display for GameAction { impl fmt::Display for GameAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
GameAction::PlayCard(c) => write!(f, "play {}", c), GameAction::PlayCard(card, slot) => write!(f, "play {} {}", card, slot),
GameAction::DropCard(c) => write!(f, "drop {}", c), GameAction::DropCard(card, slot) => write!(f, "drop {} {}", card, slot),
GameAction::ColorHint(slots, c) => write!(f, "hint {} {}", c, slots), GameAction::ColorHint(slots, c) => write!(f, "hint {} {}", c, slots),
GameAction::DigitHint(slots, d) => write!(f, "hint {} {}", d, slots), GameAction::DigitHint(slots, d) => write!(f, "hint {} {}", d, slots),
} }