klondike instruction validation

This commit is contained in:
2026-05-15 08:01:06 -07:00
parent 4ffd2a338f
commit 25d3c3aae4
2 changed files with 75 additions and 1 deletions
+20
View File
@@ -27,7 +27,27 @@ impl Suit {
self as u8 & 0b10 != 0
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct CardValue(u8);
impl CardValue {
pub fn checked_add(self, offset: u8) -> Option<CardValue> {
let new_value = self.0.checked_add(offset)?;
if 13 < new_value {
None
} else {
Some(CardValue(new_value))
}
}
pub fn checked_sub(self, offset: u8) -> Option<CardValue> {
let new_value = self.0.checked_sub(offset)?;
if new_value < 1 {
None
} else {
Some(CardValue(new_value))
}
}
}
/// An identifier which specifies the deck id, suit, and card value.
/// 2 bits for deck ID
/// 2 bits for suit ID
+55 -1
View File
@@ -86,7 +86,61 @@ impl Game for Klondike {
vec![].into_iter()
}
fn validate_instruction(&self, instruction: Self::Instruction) -> bool {
todo!()
match instruction {
// Stock -> Stock draws a card or resets the stock
KlondikeInstruction {
src: KlondikePileId::Stock,
dst: KlondikePileId::Stock,
} => {
// cannot move stock when stock is empty
!self.pile(KlondikePileId::Stock).is_empty()
}
// cannot move cards to stock
KlondikeInstruction {
src: _,
dst: KlondikePileId::Stock,
} => false,
// moving to foundation has special rules
KlondikeInstruction { src, dst }
if matches!(
dst,
KlondikePileId::Foundation0
| KlondikePileId::Foundation1
| KlondikePileId::Foundation2
| KlondikePileId::Foundation3
) =>
{
// get the top cards
if let Some(src_card) = self.pile(src).face_up().last()
&& let Some(dst_card) = self.pile(dst).face_up().last()
// suit matches?
&& src_card.suit() == dst_card.suit()
// value is +1?
&& dst_card.value().checked_add(1) == Some(src_card.value())
{
true
} else {
false
}
}
// other = move to tableau
KlondikeInstruction { src, dst } => {
// get the top cards
if let Some(src_card) = self.pile(src).face_up().last()
&& let Some(dst_card) = self.pile(dst).face_up().last()
// red-ness is opposite?
&& src_card.is_red() != dst_card.is_red()
// value is -1?
&& dst_card.value().checked_sub(1) == Some(src_card.value())
{
true
} else {
false
}
}
}
}
fn process_instruction(&mut self, instruction: Self::Instruction) {
let card = self.pile_mut(instruction.src).pop().unwrap();