Image source: By Mark Goadrich, Public Domain
In Cuckoo, players are dealt one card from a shuffled deck. On a player’s turn, they can either keep their card or try to swap it with their clockwise neighbor. If the neighbor has a King, the swap is denied, otherwise it must be accepted. The last player can swap with a random card from the deck, but must keep their card if the random card is a King. The player with the lowest card at the end of the game loses the game.
These rules are summarized from https://www.pagat.com/cuckoo/cuckoo.html.
The diagram above visualizes information flow in Cuckoo 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).

The figure above illustrates the branching factor (y-axis) for each decision point (x-axis) of Cuckoo, summarized over 100 random games. We define a decision point as a specific moment at which a player must choose from a set of possible actions. Following this definition, a player can be part of multiple distinct decision points during one of their turns, resulting in successive actions.

The figure above illustrates the normalized spread (y-axis) for each decision point (x-axis) of Cuckoo, summarized over 100 games with all MCTS players. At each decision point, a player evaluates the potential moves in terms of their potential final score. The spread is the difference between the best estimated move and the worst estimated move. This value is then divided by the highest spread found during the game to calculate the normalized spread.

The figure above illustrates the normalized average lead history (y-axis) for each decision point (x-axis) of Cuckoo, summarized over 100 games with all MCTS players. At each decision point, a player evaluates the potential moves in terms of their potential final score. For the best estimated move, they record the estimated score for all players, assigning them normalized rank estimates, where 1 is first place, and 0 is last place. Across 100 games, these histories are grouped according to final game rank, and then averaged.
The rules for Cuckoo are coded in RECYCLE, a card game description language, to encourage standardized implementations across different systems.
You can also Download the code.
;; Cuckoo
;; https://www.pagat.com/cuckoo/cuckoo.html
(game
(setup
(create players 6)
(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 the values for the cards
(set (game points PRECEDENCE)
(((RANK : K) 13) ((RANK : Q) 12) ((RANK : J) 11)
((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 : TWO) 2)
((RANK : A) 1)))
;; Shuffle the deck, give each player one card in their hand
(shuffle (game iloc STOCK))
(all player 'P
(move (top (game iloc STOCK)) (top ('P iloc HAND))))))
;; Everyone gets a turn
(stage player
(end (all player 'P (== ('P str STATE) DONE)))
;; Manage cards passed for trade
(do (
((and (> (size ((current player) iloc PASSED)) 0)
(!= (cardatt RANK (top ((current player) iloc HAND))) K))
(do (
(move (top ((current player) iloc HAND))
(top ((previous player) iloc HAND)))
(move (top ((current player) iloc PASSED))
(top ((current player) iloc HAND))))))
((and (> (size ((current player) iloc PASSED)) 0)
(== (cardatt RANK (top ((current player) iloc HAND))) K))
(do (
(move (top ((current player) iloc PASSED))
(top ((previous player) iloc HAND)))
(move (top ((current player) iloc HAND))
(top ((current player) vloc HAND))))))))
;; Potentially trade with the next player
(choice (
;; pass with neighbor if not last player
((and (!= ((next player) str STATE) DONE)
(> (size ((current player) iloc HAND)) 0))
(move (top ((current player) iloc HAND))
(top ((next player) iloc PASSED))))
;; pass with deck if last player
((and (== ((next player) str STATE) DONE)
(> (size ((current player) iloc HAND)) 0))
(do (
(move (top ((current player) iloc HAND))
(top (game iloc PASSED)))
(move (top (game iloc STOCK))
(top ((current player) iloc HAND)))
;; if the deck revealed a K, swap the card back
((== (cardatt RANK (top ((current player) iloc HAND))) K)
(do (
(move (top ((current player) iloc HAND))
(top (game vloc CUT)))
(move (top (game iloc PASSED))
(top ((current player) iloc HAND)))))))))
;; if you already revealed a K, or if you just want to, you pass
(turn pass)))
;; Mark the end of your turn
(do (
(set ((current player) str STATE) DONE))))
(do (
;; Turn all the cards face up
(all player 'P
((!= (size ('P iloc HAND)) 0)
(move (top ('P iloc HAND)) (top ('P vloc HAND)))))
;; If your card is the smallest, you get a point
(all player 'P
((== (score (top ('P vloc HAND)) using (game points PRECEDENCE))
(scoremin (union (all player 'EP ('EP vloc HAND)))
using (game points PRECEDENCE)))
(inc ('P sto SCORE))))))
(scoring min ((current player) sto SCORE)))