diff --git a/klondike-cli/src/main.rs b/klondike-cli/src/main.rs index 6641eab..314d071 100644 --- a/klondike-cli/src/main.rs +++ b/klondike-cli/src/main.rs @@ -229,24 +229,35 @@ fn main() -> Result<(), std::io::Error> { src: KlondikePile::Foundation(_), .. }) - // Tableau -> Tableau when not revealing a new card is _usually_ a useless move - | KlondikeInstruction::DstTableau(DstTableau { - src: KlondikePileStack::Tableau(TableauStack { - skip_cards: SkipCards::Skip1 - | SkipCards::Skip2 | SkipCards::Skip3 - | SkipCards::Skip4 | SkipCards::Skip5 - | SkipCards::Skip6 | SkipCards::Skip7 - | SkipCards::Skip8 | SkipCards::Skip9 - | SkipCards::Skip10 | SkipCards::Skip11 - | SkipCards::Skip12, - .. - }), - .. - }) ) } - if let Some(instruction) = - session.possible_instructions().filter(useless_moves).next() + fn instruction_priority( + state: &Klondike, + instruction: &KlondikeInstruction, + ) -> usize { + // 1 Move into foundation + // 2 T->T Move to reveal new card + // 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) => 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)) { session.process_instruction(instruction); } else { diff --git a/klondike/src/lib.rs b/klondike/src/lib.rs index b123439..d86b63a 100644 --- a/klondike/src/lib.rs +++ b/klondike/src/lib.rs @@ -316,6 +316,17 @@ impl KlondikeState { pub const fn tableau7(&self) -> &Pile<6, 13> { &self.tableau7 } + pub fn is_tableau_face_down_empty(&self, tableau: Tableau) -> bool { + match tableau { + Tableau::Tableau1 => self.tableau1.face_down().is_empty(), + Tableau::Tableau2 => self.tableau2.face_down().is_empty(), + Tableau::Tableau3 => self.tableau3.face_down().is_empty(), + Tableau::Tableau4 => self.tableau4.face_down().is_empty(), + Tableau::Tableau5 => self.tableau5.face_down().is_empty(), + Tableau::Tableau6 => self.tableau6.face_down().is_empty(), + Tableau::Tableau7 => self.tableau7.face_down().is_empty(), + } + } pub fn card(&self, src: KlondikePileStack) -> Option<&Card> { match src { KlondikePileStack::Tableau(TableauStack {