Golf Six

Summary

In Golf, the deck is shuffled, and then 6 cards are dealt face-down to each player in a 3x2 grid. One card is turned face-up to begin the discard pile. On a player’s turn, they can either draw the top card from the discard pile, or the top of the remaining deck. The player can then decide to replace one of their cards, either face-down or face-up, with the drawn card, keeping the new card face-up. Play continues until one player has all face-up cards in their grid. Duplicate card ranks in columns are removed, and then players score for their remaining cards. The player with the lowest score wins.

Rules of Play

These rules are summarized from https://www.pagat.com/draw/golf.html.

Golf is a draw-and-discard game. Other games in this genre include Sam Sip and Knock Poker, and is the basis for commercial games like Skyjo and Rat a TatCat.

Information Flow

Card Movement Graph

The diagram above visualizes information flow in Golf Six using a single random rollout in CardStock. Visibility is attached to card locations, so all cards in a location share the same visibility; information is revealed or concealed as cards move between locations and ownership changes.

Public locations are shown in green, hidden locations in yellow, private locations in blue, and memory locations in light gray. Locations containing cards with distinct backs are indicated with bold borders. Rectangles denote ownership (players or table), and directed edges show card movement between locations and resulting visibility changes. Taken information is shown with red dotted edges (public to private/hidden), and shared information with blue dashed edges (private cards transferred to another player).

RECYCLE Code

The rules for Golf Six are coded in RECYCLE, a card game description language, to encourage standardized implementations across different systems.

You can also Download the code.

;; Golf
;; https://www.pagat.com/draw/golf.html

(game
 (declare (range 1..6) 'PLOCS)
 (setup
  (create players 4)
  (create deck (game iloc STOCK) 
   (deck (RANK (A, TWO, THREE, FOUR, FIVE, SIX, 
                SEVEN, EIGHT, NINE, TEN, J, Q, K))
         (COLOR (RED (SUIT (HEARTS, DIAMONDS)))
                (BLACK (SUIT (CLUBS, SPADES)))))))
 (do (
  ;; set scoring points for the cards
  (set (game points POSITIVE)
   (((RANK : Q)    10) ((RANK : J)    10) ((RANK : TEN)  10)
    ((RANK : NINE)  9) ((RANK : EIGHT) 8) ((RANK : SEVEN) 7)
    ((RANK : SIX)   6) ((RANK : FIVE)  5) ((RANK : FOUR)  4)
    ((RANK : THREE) 3) ((RANK : A)     1)))
  (set (game points NEGATIVE)
   (((RANK : TWO) 2)))

  ;; Shuffle the deck, give each player one card in each of their locations
  (shuffle (game iloc STOCK))    
  (all player 'P
   (all 'PLOCS 'L
    (move (top (game iloc STOCK)) 
          (top ('P hloc LOC 'L)))))

  ;; Start the discard pile
  (move (top (game iloc STOCK))
        (top (game vloc DISCARD)))))
 
 ;; each player turns over two spots
 (stage player
  (end (all player 'P (== (size (union (all 'PLOCS 'L ('P hloc LOC 'L)))) 4)))
  (choice (
   (any 'PLOCS 'L
    ((!= (size ((current player) hloc LOC 'L)) 0) 
     (move (top ((current player) hloc LOC 'L))   
           (top ((current player) vloc LOC 'L)))))))

  (choice (
   (any 'PLOCS 'L
    ((!= (size ((current player) hloc LOC 'L)) 0) 
     (move (top ((current player) hloc LOC 'L))   
           (top ((current player) vloc LOC 'L))))))))

 ;; play the game until one player has all faceup cards
 (stage player
  (end (any player 'P (== (size (union (all 'PLOCS 'L ('P hloc LOC 'L)))) 0)))

  ;; Draw a card
  (choice (
   ((> (size (game iloc STOCK)) 0)
    (move (top (game iloc STOCK)) 
          (top((current player) iloc HAND))))

   ((> (size (game vloc DISCARD)) 0)
    (do (
     (move (top (game vloc DISCARD)) 
           (top((current player) iloc HAND)))
     (set ((current player) str DRAWFROM) DISCARD))))))
        
  ;; Play a card
  (choice (
   ((!= ((current player) str DRAWFROM) DISCARD)
    (move (top ((current player) iloc HAND)) 
     (top (game vloc DISCARD))))
          
   (any 'PLOCS 'L
    (do (
     ((== (size ((current player) hloc LOC 'L)) 0) 
      (move (top ((current player) vloc LOC 'L))   
            (top (game vloc DISCARD))))
     ((!= (size ((current player) hloc LOC 'L)) 0) 
      (move (top ((current player) hloc LOC 'L))   
            (top (game vloc DISCARD))))
     (move (top ((current player) iloc HAND)) 
           (top ((current player) vloc LOC 'L))))))))
        
  ;; Forget if you drew from the discard pile
  (do (
   (set ((current player) str DRAWFROM) NONE))))

 ;; Calculate your scores
 (stage player
  (end (all player 'P (== ('P str FINISHED) TRUE)))

  (do (
   ;; turn all cards face up
   (all 'PLOCS 'L 
    (repeat all (move (top ((current player) hloc LOC 'L))
                      (top ((current player) vloc LOC 'L)))))

   ;; throw away column matches
   (all (range 1..3) 'L
    ((== (cardatt RANK (top ((current player) vloc LOC 'L)))
         (cardatt RANK (top ((current player) vloc LOC (+ 3 'L)))))
     (do (
      (move (top ((current player) vloc LOC 'L))
            (top (game vloc DISCARD)))
      (move (top ((current player) vloc LOC (+ 3 'L)))
            (top (game vloc DISCARD)))))))

   ;; then add up cards for pos, subtract neg
   (set ((current player) sto SCORE) 
        (sum (union (all 'PLOCS 'L ((current player) vloc LOC 'L))) 
             using (game points POSITIVE)))
   (dec ((current player) sto SCORE) 
        (sum (union (all 'PLOCS 'L ((current player) vloc LOC 'L)))
             using (game points NEGATIVE)))

   ;; end the scoring turn
   (set ((current player) str FINISHED) TRUE))))

 (scoring min ((current player) sto SCORE)))