From 408978dd4f0eb79b2b03b1a18513d65f67ee4e42 Mon Sep 17 00:00:00 2001 From: Arthur Roberts Date: Sat, 8 Mar 2025 02:05:04 +0000 Subject: [PATCH] Added code to push to foundation Need to write some tests. I have no idea if it works --- card_stuffs/src/lib.rs | 80 +++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/card_stuffs/src/lib.rs b/card_stuffs/src/lib.rs index 8797129..3c0a568 100644 --- a/card_stuffs/src/lib.rs +++ b/card_stuffs/src/lib.rs @@ -131,7 +131,7 @@ pub enum StackingError { } impl Card { - pub fn can_be_placed_on_top_pile(&self, top: &Card) -> Result<(), StackingError> { + pub fn can_be_placed_on_pile(&self, top: &Card) -> Result<(), StackingError> { // Can't be the same Colour if self.suit.colour() == top.suit.colour() { return Err(StackingError::SameColour); @@ -145,7 +145,7 @@ impl Card { Ok(()) } - pub fn can_be_placed_on_top_foundation(&self, top: &Option) -> Result<(), StackingError> { + pub fn can_be_placed_on_foundation(&self, top: &Option) -> Result<(), StackingError> { match top { None => { if self.value == Value::Ace { @@ -212,11 +212,12 @@ pub struct CardAndPosition { pos: CardPosition, } +#[derive(PartialEq)] pub enum CardPosition { Deck, // I don't think this will need to be used TopWaste, // I don't think we'd ever interact with anything other than the top of the Waste - Pile(u8, u8), // (PileNumber, Index) - Foundation(u8) + Pile(usize, usize), // (PileNumber, Index) + Foundation(usize) } #[derive(Debug, Copy, Clone)] @@ -266,24 +267,71 @@ impl Klondike { } } - pub fn move_card(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) { + pub fn move_card(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool { // TODO raise errors properly + assert!(source_card.card.is_some()); assert_eq!(source_card.card.unwrap().visible, true); source_card.pos.is_valid_source(); dest_card.pos.is_valid_dest(); + // Maybe TODO - check the .cards is the actual card in that position + match dest_card.pos { CardPosition::Pile(_, _) => self.move_card_to_pile(&source_card, &dest_card), - CardPosition::Foundation(_) => self.move_card_to_foundation(source_card, dest_card), + CardPosition::Foundation(_f) => self.move_card_to_foundation(source_card, dest_card), CardPosition::Deck | CardPosition::TopWaste => unreachable!() } } - pub fn move_card_to_foundation(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) { - + pub fn move_card_to_foundation(mut self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool { + // TODO Check whether the card is the top of a pile / waste - it needs to be + // TODO actually learn Rust properly so I can figure out why I need to clone the whole struct to check a value + if source_card.pos != CardPosition::TopWaste || !self.clone().is_card_top_of_pile(&source_card.pos) { + return false; + } + if source_card.card.unwrap().can_be_placed_on_foundation(&dest_card.card).is_err() { + return false; + } + // TODO actually move the cards - it should be possible from here + // There really must be a better way to extract an enum "value" than this... + if let CardPosition::Foundation(foundation_index) = dest_card.pos { + match source_card.pos { + CardPosition::TopWaste => { + let card = self.waste.pop().unwrap(); + self.foundation[foundation_index].push(card); + }, + CardPosition::Pile(pile_index, _) => { + let card = self.piles[pile_index].pop().unwrap(); + self.foundation[foundation_index].push(card); + }, + CardPosition::Deck | CardPosition::Foundation(_) => unreachable!(), + } + } + unreachable!(); } - pub fn move_card_to_pile(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) { + pub fn move_card_to_pile(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool { + true + } + + fn is_card_top_of_pile(self, pos: &CardPosition) -> bool { + // TODO consider, at which point the Pos::Pile() ranges etc are correct + match pos { + CardPosition::Pile(pile_index, card_index) => { + match self.piles.get(*pile_index) { + Some(pile_index) => { + // TODO - this is the correct palce to put a - 1 + if *card_index == (pile_index.len() - 1) { + true + } else { + false + } + } + None => false + } + }, + CardPosition::Deck | CardPosition::TopWaste | CardPosition::Foundation(_) => false + } } } @@ -291,15 +339,15 @@ impl CardPosition { // Unsure this is "correct" to just panic - but it really shouldn't happen fn is_valid_dest(&self) { match self { - CardPosition::Deck => unreachable!("You can't move cards to deck"), - CardPosition::TopWaste => unreachable!("You can't move cards to waste"), + CardPosition::Deck => panic!("You can't move cards to deck"), + CardPosition::TopWaste => panic!("You can't move cards to waste"), CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (), } } fn is_valid_source(&self) { match self { - CardPosition::Deck => unreachable!("You can't move cards from deck"), + CardPosition::Deck => panic!("You can't move cards from deck"), CardPosition::TopWaste | CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (), } } @@ -350,25 +398,25 @@ mod tests { value: Value::Six, ..Default::default() }; - assert_eq!(testing_card.can_be_placed_on_top_pile(&bad_same_suit), Err(StackingError::SameColour)); + assert_eq!(testing_card.can_be_placed_on_pile(&bad_same_suit), Err(StackingError::SameColour)); let bad_same_colour = Card { suit: Suit::Diamond, value: Value::Six, ..Default::default() }; - assert_eq!(testing_card.can_be_placed_on_top_pile(&bad_same_colour), Err(StackingError::SameColour)); + assert_eq!(testing_card.can_be_placed_on_pile(&bad_same_colour), Err(StackingError::SameColour)); let should_stack_card = Card { suit: Suit::Club, value: Value::Six, ..Default::default() }; - assert_eq!(testing_card.can_be_placed_on_top_pile(&should_stack_card), Ok(())); + assert_eq!(testing_card.can_be_placed_on_pile(&should_stack_card), Ok(())); let value_too_high = Card { suit: Suit::Club, value: Value::Seven, ..Default::default() }; - let not_adj_error = testing_card.can_be_placed_on_top_pile(&value_too_high); + let not_adj_error = testing_card.can_be_placed_on_pile(&value_too_high); if let Err(e) = not_adj_error { match e { StackingError::NotAdjacent(_, _) => assert!(true),