find valid instruction

This commit is contained in:
2026-05-16 10:31:28 -07:00
parent 0e522f7154
commit 8fe13caa1e
+114 -30
View File
@@ -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>(T);
impl core::str::FromStr for Parsed<KlondikeInstruction> {
struct NaiveInstruction {
src: KlondikePileId,
dst: KlondikePileId,
}
impl core::str::FromStr for NaiveInstruction {
type Err = Invalid;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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<InstructionSrc> {
type Err = Invalid;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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<KlondikePileId> {
@@ -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<KlondikeInstruction> {
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!");