use std::fmt;
use std::cmp::Ordering;
use cards::types::*;
#[macro_export]
macro_rules! card {
($rank:ident, $suit:ident) => (PlayerCard::Card(Card::new(Rank::$rank, Suit::$suit, false)));
($rank:ident, $suit:ident, $reverse:expr) => (PlayerCard::Card(Card::new(Rank::$rank, Suit::$suit, $reverse)));
}
#[macro_export]
macro_rules! wildcard {
($rank:ident, $suit:ident) => (PlayerCard::Wildcard(Card::new(Rank::$rank, Suit::$suit, false)));
($rank:ident, $suit:ident, $reverse:expr) => (PlayerCard::Wildcard(Card::new(Rank::$rank, Suit::$suit, $reverse)));
}
#[derive(Clone, Debug, PartialEq, Copy, PartialOrd, Serialize, Deserialize, Eq, Ord)]
pub enum PlayerCard {
Card(Card),
Wildcard(Card),
Joker(u64)
}
impl PlayerCard {
pub fn to_card(&self) -> Card {
match *self {
PlayerCard::Card(c)|PlayerCard::Wildcard(c) => c,
PlayerCard::Joker(_) => panic!("Joker must be specified as Wildcard(Card)!")
}
}
pub fn reverse(&self) -> PlayerCard {
match *self {
PlayerCard::Card(c) => PlayerCard::Card(c.reverse()),
PlayerCard::Wildcard(c) => PlayerCard::Wildcard(c.reverse()),
c => c
}
}
}
#[derive(Clone, Debug, PartialEq, Copy, Serialize, Deserialize, Eq, Ord)]
pub struct Card{
pub rank: Rank,
pub suit: Suit,
pub colour: Colour,
pub reversed: bool
}
impl Card {
pub fn new(rank: Rank, suit: Suit, reversed: bool) -> Card {
let colour = match suit {
Suit::Diamonds | Suit::Hearts => Colour::Red,
_ => Colour::Black
};
Card{suit: suit, rank: rank, colour: colour, reversed: reversed}
}
pub fn previous_rank(&self) -> Option<Rank>{
match self.reversed {
false => previous_rank(&self.rank),
true => next_rank(&self.rank)
}
}
pub fn next_rank(&self) -> Option<Rank>{
match self.reversed {
false => next_rank(&self.rank),
true => previous_rank(&self.rank)
}
}
pub fn alternate_colour(&self) -> Colour{
if self.colour == Colour::Red {
Colour::Black
} else {
Colour::Red
}
}
pub fn reverse(&self) -> Card{
Card::new(self.rank, self.suit, !self.reversed)
}
}
impl PartialOrd for Card {
fn partial_cmp(&self, other: &Card) -> Option<Ordering> {
if self.reversed {
match other.rank.partial_cmp(&self.rank) {
Some(Ordering::Equal) => other.suit.partial_cmp(&self.suit),
x => x
}
} else {
match self.rank.partial_cmp(&other.rank) {
Some(Ordering::Equal) => self.suit.partial_cmp(&other.suit),
x => x
}
}
}
}
impl fmt::Display for Card {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let card = format!("{}{}", self.suit, self.rank);
write!(f, "{}", card)
}
}
fn previous_rank(rank:&Rank) -> Option<Rank> {
match *rank {
Rank::Three => None,
Rank::Four => Some(Rank::Three),
Rank::Five => Some(Rank::Four),
Rank::Six => Some(Rank::Five),
Rank::Seven => Some(Rank::Six),
Rank::Eight => Some(Rank::Seven),
Rank::Nine => Some(Rank::Eight),
Rank::Ten => Some(Rank::Nine),
Rank::Jack => Some(Rank::Ten),
Rank::Queen => Some(Rank::Jack),
Rank::King => Some(Rank::Queen),
Rank::Ace => Some(Rank::King),
Rank::Two => Some(Rank::Ace),
}
}
fn next_rank(rank:&Rank) -> Option<Rank> {
match *rank {
Rank::Three => Some(Rank::Four),
Rank::Four => Some(Rank::Five),
Rank::Five => Some(Rank::Six),
Rank::Six => Some(Rank::Seven),
Rank::Seven => Some(Rank::Eight),
Rank::Eight => Some(Rank::Nine),
Rank::Nine => Some(Rank::Ten),
Rank::Ten => Some(Rank::Jack),
Rank::Jack => Some(Rank::Queen),
Rank::Queen => Some(Rank::King),
Rank::King => Some(Rank::Ace),
Rank::Ace => Some(Rank::Two),
Rank::Two => None,
}
}