gin_rummy_engine/action.rs
1//! The decisions a [`Strategy`](crate::Strategy) can make
2//!
3//! Each phase of a round has its own action type, so an action that is
4//! structurally illegal for its decision point cannot be expressed.
5
6use gin_rummy::{Card, Melds};
7
8/// Response to the initial upcard offer
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum UpcardAction {
11 /// Take the upcard into hand
12 Take,
13 /// Decline the upcard, passing the offer on
14 Pass,
15}
16
17/// Where to draw at the start of a normal turn
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub enum DrawAction {
20 /// Draw the hidden top of the stock
21 Stock,
22 /// Take the top of the discard pile
23 TakeDiscard,
24}
25
26/// How to end a turn from an 11-card hand
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum TurnAction {
29 /// Shed a card and pass the turn
30 Discard(Card),
31 /// Shed a card and knock, spreading the given arrangement
32 ///
33 /// The arrangement decides what the defender may lay off, so it is
34 /// chosen explicitly; `best_melds(hand - discard.into())` recovers the
35 /// deadwood-minimizing choice.
36 Knock {
37 /// The card to shed
38 discard: Card,
39 /// The arrangement of the remaining ten cards to spread
40 melds: Melds,
41 },
42 /// Declare big gin with all 11 cards arranged and no discard
43 BigGin(Melds),
44}
45
46/// One layoff onto the knocker's spread
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48pub struct Layoff {
49 /// The card to lay off
50 pub card: Card,
51 /// The index of the target meld in [`View::spread`](crate::View::spread)
52 /// enumeration order
53 ///
54 /// Indices are stable across layoffs, so chained run extensions address
55 /// the same meld.
56 pub meld: usize,
57}