From 8fe13caa1e0f30824365351c8d85ebeb3afdf147 Mon Sep 17 00:00:00 2001 From: Rhys Lloyd Date: Sat, 16 May 2026 10:31:28 -0700 Subject: [PATCH] find valid instruction --- src/main.rs | 144 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 114 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index b34547a..844bbb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,8 @@ pub type Rng = rand::rngs::ThreadRng; use card_game::{Card, Game, Pile, Session, Suit}; use klondike::{ - InstructionSrc, Klondike, KlondikeInstruction, KlondikePileId, KlondikePileStack, SkipCards, + InstructionSrc, Klondike, KlondikeInstruction, KlondikePileId, KlondikePileStack, + KlondikeState, SkipCards, }; use std::fmt::Display; @@ -89,32 +90,16 @@ impl Display for Klondike { #[derive(Debug)] struct Invalid; struct Parsed(T); -impl core::str::FromStr for Parsed { +struct NaiveInstruction { + src: KlondikePileId, + dst: KlondikePileId, +} +impl core::str::FromStr for NaiveInstruction { type Err = Invalid; fn from_str(s: &str) -> Result { let Parsed(src) = s.get(0..2).ok_or(Invalid)?.parse()?; let Parsed(dst) = s.get(3..5).ok_or(Invalid)?.parse()?; - Ok(Parsed(KlondikeInstruction { src, dst })) - } -} -impl core::str::FromStr for Parsed { - type Err = Invalid; - fn from_str(s: &str) -> Result { - Ok(Parsed(match s { - "st" => InstructionSrc::new(KlondikePileStack::Stock), - "t1" => InstructionSrc::new(KlondikePileStack::Tableau1(SkipCards::Zero)), - "t2" => InstructionSrc::new(KlondikePileStack::Tableau2(SkipCards::Zero)), - "t3" => InstructionSrc::new(KlondikePileStack::Tableau3(SkipCards::Zero)), - "t4" => InstructionSrc::new(KlondikePileStack::Tableau4(SkipCards::Zero)), - "t5" => InstructionSrc::new(KlondikePileStack::Tableau5(SkipCards::Zero)), - "t6" => InstructionSrc::new(KlondikePileStack::Tableau6(SkipCards::Zero)), - "t7" => InstructionSrc::new(KlondikePileStack::Tableau7(SkipCards::Zero)), - "f1" => InstructionSrc::new(KlondikePileStack::Foundation1), - "f2" => InstructionSrc::new(KlondikePileStack::Foundation2), - "f3" => InstructionSrc::new(KlondikePileStack::Foundation3), - "f4" => InstructionSrc::new(KlondikePileStack::Foundation4), - _ => return Err(Invalid), - })) + Ok(NaiveInstruction { src, dst }) } } impl core::str::FromStr for Parsed { @@ -145,7 +130,7 @@ enum SessionInstruction { Auto, Stock, Exit, - Klondike(KlondikeInstruction), + Klondike(NaiveInstruction), } impl core::str::FromStr for SessionInstruction { type Err = Invalid; @@ -157,14 +142,111 @@ impl core::str::FromStr for SessionInstruction { "auto" | "a" => Self::Auto, "exit" => Self::Exit, "s" => Self::Stock, - other => { - let Parsed(ki) = other.parse()?; - Self::Klondike(ki) - } + other => Self::Klondike(other.parse()?), }) } } +fn find_valid_instruction( + state: &Klondike, + naive_instruction: NaiveInstruction, +) -> Option { + const SKIP_LIST: [SkipCards; 13] = [ + SkipCards::Zero, + SkipCards::One, + SkipCards::Two, + SkipCards::Three, + SkipCards::Four, + SkipCards::Five, + SkipCards::Six, + SkipCards::Seven, + SkipCards::Eight, + SkipCards::Nine, + SkipCards::Ten, + SkipCards::Eleven, + SkipCards::Twelve, + ]; + let dst = naive_instruction.dst; + let src = match naive_instruction.src { + KlondikePileId::Tableau1 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau1(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Tableau2 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau2(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Tableau3 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau3(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Tableau4 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau4(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Tableau5 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau5(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Tableau6 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau6(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Tableau7 => { + for skip in SKIP_LIST { + let src = InstructionSrc::new(KlondikePileStack::Tableau7(skip)); + let instruction = KlondikeInstruction { src, dst }; + if state.is_instruction_valid(instruction) { + return Some(instruction); + } + } + return None; + } + KlondikePileId::Foundation1 => InstructionSrc::new(KlondikePileStack::Foundation1), + KlondikePileId::Foundation2 => InstructionSrc::new(KlondikePileStack::Foundation2), + KlondikePileId::Foundation3 => InstructionSrc::new(KlondikePileStack::Foundation3), + KlondikePileId::Foundation4 => InstructionSrc::new(KlondikePileStack::Foundation4), + KlondikePileId::Stock => InstructionSrc::new(KlondikePileStack::Stock), + }; + return Some(KlondikeInstruction { src, dst }); +} + fn main() -> Result<(), std::io::Error> { let mut session = Session::new(Klondike::new_random_default()); loop { @@ -197,8 +279,10 @@ fn main() -> Result<(), std::io::Error> { } } SessionInstruction::Stock => session.process_instruction(KlondikeInstruction::stock()), - SessionInstruction::Klondike(instruction) => { - if session.is_instruction_valid(instruction) { + SessionInstruction::Klondike(naive_instruction) => { + if let Some(instruction) = + find_valid_instruction(session.state(), naive_instruction) + { session.process_instruction(instruction); } else { println!("Invalid move!");