From 35931fc0dc1a0372acda8b66b6e39b7b3f4e4ba4 Mon Sep 17 00:00:00 2001 From: Rhys Lloyd Date: Sat, 16 May 2026 18:12:49 -0700 Subject: [PATCH] get_good_move function --- klondike-cli/src/main.rs | 90 ++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/klondike-cli/src/main.rs b/klondike-cli/src/main.rs index c91d229..4873412 100644 --- a/klondike-cli/src/main.rs +++ b/klondike-cli/src/main.rs @@ -195,6 +195,50 @@ fn find_valid_instruction( .then_some(instruction) } +fn get_good_move(state: &Klondike) -> Option { + fn useless_moves(instruction: &KlondikeInstruction) -> bool { + !matches!( + instruction, + // foundation -> foundation is a useless move + KlondikeInstruction::DstFoundation(DstFoundation { + src: KlondikePile::Foundation(_), + .. + }) + ) + } + fn instruction_priority(state: &Klondike, instruction: &KlondikeInstruction) -> usize { + // 1 Move into foundation + // 2 T->T Move to reveal new card (moving a non-king to reveal empty tableau also counts) + // 3 Move from stock + // 4 Rotate stock + // 5 T->T Move not revealing new card + // 6 Move from foundation + match instruction { + KlondikeInstruction::DstFoundation(_) => 1, + &KlondikeInstruction::DstTableau(dst_tableau) => match dst_tableau.src { + KlondikePileStack::Tableau(TableauStack { + tableau, + skip_cards: SkipCards::Skip0, + }) if !state.state().is_tableau_face_down_empty(tableau) + || state + .state() + .card(dst_tableau.src) + .is_some_and(|card| card.value() != CardValue::KING) => + { + 2 + } + KlondikePileStack::Stock => 3, + _ => 5, + }, + KlondikeInstruction::RotateStock => 4, + } + } + state + .possible_instructions() + .filter(useless_moves) + .min_by_key(|ins| instruction_priority(state, ins)) +} + fn main() -> Result<(), std::io::Error> { let mut session = Session::new(Klondike::new_random_default()); let mut input = String::new(); @@ -221,51 +265,7 @@ fn main() -> Result<(), std::io::Error> { } } SessionInstruction::Auto => { - fn useless_moves(instruction: &KlondikeInstruction) -> bool { - !matches!( - instruction, - // foundation -> foundation is a useless move - KlondikeInstruction::DstFoundation(DstFoundation { - src: KlondikePile::Foundation(_), - .. - }) - ) - } - fn instruction_priority( - state: &Klondike, - instruction: &KlondikeInstruction, - ) -> usize { - // 1 Move into foundation - // 2 T->T Move to reveal new card (moving a non-king to reveal empty tableau also counts) - // 3 Move from stock - // 4 Rotate stock - // 5 T->T Move not revealing new card - // 6 Move from foundation - match instruction { - KlondikeInstruction::DstFoundation(_) => 1, - &KlondikeInstruction::DstTableau(dst_tableau) => match dst_tableau.src { - KlondikePileStack::Tableau(TableauStack { - tableau, - skip_cards: SkipCards::Skip0, - }) if !state.state().is_tableau_face_down_empty(tableau) - || state - .state() - .card(dst_tableau.src) - .is_some_and(|card| card.value() != CardValue::KING) => - { - 2 - } - KlondikePileStack::Stock => 3, - _ => 5, - }, - KlondikeInstruction::RotateStock => 4, - } - } - if let Some(instruction) = session - .possible_instructions() - .filter(useless_moves) - .min_by_key(|ins| instruction_priority(session.state(), ins)) - { + if let Some(instruction) = get_good_move(session.state()) { session.process_instruction(instruction); } else { println!("No valid moves!");