1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
use std::fmt::{Debug, Display, Error, Formatter}; use crate::{Card, CardCollection, Suit, ACE}; //const FOUNDATION_MAX_SIZE: usize = 13; /// A stack of cards of one suit, ordered from Ace upwards. /// /// See struct Foundations. pub type Foundation = Vec<Card>; /// Four stacks of cards, where each stack contains only cards of one suit, going from Ace upwards. /// /// # Rules /// /// There exists one foundation for each of the four suits. /// Cards can only be put on the foundation corresponding to their suit. /// /// An Ace can be put on the foundation of the appropriate suit iff there is no other card on that /// foundation. /// This is always the case in a valid game state. /// /// Any other card *c* can be put on the foundation of the appropriate suit iff the top card on that /// foundation has a rank exactly one lower than card *c*. /// /// This means a foundation can hold at most 13 cards: /// The cards from Ace to King of one suit in order of their ranks, the Ace being on the bottom and /// the King being on top. /// The game ends in a victory when all four foundations reach this state. /// /// Once a card is on a foundation, it can never be removed. /// /// # Usage /// /// The position of the Foundation in the array determines which suit it holds. /// Eg. `foundations[1]` may only hold spade cards, since Suit::Spade equals 1. /// TODO [high priority] explain more thoroughly /// /// # Examples /// /// ``` /// // TODO [high priority] /// ``` #[derive(Clone, Default, Eq, Hash, PartialEq)] pub struct Foundations(pub [Foundation; 4]); impl Foundations { /// Creates empty foundations pub fn new() -> Foundations { Foundations([Vec::new(), Vec::new(), Vec::new(), Vec::new()]) } /// Returns the foundation of the given suit pub fn foundation(&self, suit: Suit) -> &Foundation { &self.0[suit as usize] } } impl CardCollection for Foundations { /// Attempts to put a card on the foundation of the appropriate suit. /// /// An Ace can be put on a foundation iff there is no other card on the foundation of that suit. /// This is always the case in a valid game state. /// /// Any other card *c* can be put on a foundation iff the top card on the foundation of that /// suit has a rank exactly one lower than card *c*. fn add_card(&self, card: Card) -> Result<Self, ()> { // check whether the card can be put on any foundation if self.foundation(card.suit).is_empty() { // only Aces can be put on an empty foundation if card.rank != ACE { return Err(()); } } else if // Aces can only be put on an empty foundation card.rank == ACE || // Other cards can only be put on a foundation if it is one rank higher than the // currently topmost card on the foundation self.foundation(card.suit).last().unwrap().rank + 1 != card.rank { return Err(()); } let mut clone = self.clone(); clone.0[card.suit as usize].push(card); Ok(clone) } /// Always returns an empty Vec, since cards cannot be removed from foundations. fn pop_card(&self) -> Vec<(Self, Card)> { Vec::new() } } impl Display for Foundations { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { let foundation_strings: Vec<String> = self.0.iter().map( |foundation| if foundation.is_empty() { "Empty".to_string() } else { format!("Up to {}", foundation.last().unwrap().to_string()) } ).collect(); write!(f, "Foundations: {}", foundation_strings.join(", ")) } } impl Debug for Foundations { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "Foundations:")?; for foundation in &self.0 { if !foundation.is_empty() { write!(f, " {:?}", foundation.last().unwrap())?; } } Ok(()) } }