Image source: By Mark Goadrich, Public Domain
Agram is a simple trick-taking card game. Players are dealt six cards from a reduced French deck, and play six tricks. To win a trick, players must follow the suit of the lead player with a higher card; there is no trump suit. The object of the game is to win the last trick.
These rules are summarized from https://www.pagat.com/last/agram.html.
Agram is a last-trick solo trick taking game. Other games in this genre include Toepen and Spar.
The diagram above visualizes information flow in Agram 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 rules for Agram are coded in RECYCLE, a card game description language, to encourage standardized implementations across different systems.
You can also Download the code.
;; Agram
;; https://www.pagat.com/last/agram.html
(game
(setup
(create players 3)
;; Create the deck source
(create deck (game iloc STOCK)
(deck (RANK (THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN))
(COLOR (RED (SUIT (HEARTS, DIAMONDS)))
(BLACK (SUIT (SPADES, CLUBS))))))
(create deck (game iloc STOCK)
(deck (RANK (ACE))
(COLOR (RED (SUIT (HEARTS, DIAMONDS)))
(BLACK (SUIT (CLUBS)))))))
;; Shuffle and deal each player 6 cards
(do (
(shuffle (game iloc STOCK))
(set (game str LEAD) NONE)
(all player 'P
(repeat 6 (move (top (game iloc STOCK))
(top ('P iloc HAND)))))))
;; players play a round 6 times
(stage player
(end (all player 'P (== (size ('P iloc HAND)) 0)))
;; players play a hand once
(stage player
(end (all player 'P (> (size ('P vloc TRICK)) 0)))
(choice (
;; if first player, play any card,
;; remember it in the lead spot
((== (game str LEAD) NONE)
(any ((current player) iloc HAND) 'AC
(do (
(move 'AC (top ((current player) vloc TRICK)))
(set (game str LEAD)
(cardatt SUIT (top ((current player) vloc TRICK))))))))
;; if following player cannot follow SUIT
;; play any card
((and (!= (game str LEAD) NONE)
(== (size (filter ((current player) iloc HAND) 'C
(== (cardatt SUIT 'C) (game str LEAD)))) 0))
(any ((current player) iloc HAND) 'AC
(move 'AC (top ((current player) vloc TRICK)))))
;; if following player and can follow SUIT
;; play any card that follows SUIT
(any (filter ((current player) iloc HAND) 'T
(== (cardatt SUIT 'T) (game str LEAD))) 'C
((!= (game str LEAD) NONE)
(move 'C (top ((current player) vloc TRICK))))))))
;; after players play hand, computer wraps up trick
(do (
;; solidfy card recedence
(set (game points PRECEDENCE)
(((SUIT : (game str LEAD)) 100)
((RANK : ACE) 14) ((RANK : TEN) 10)
((RANK : NINE) 9) ((RANK : EIGHT) 8)
((RANK : SEVEN) 7) ((RANK : SIX) 6)
((RANK : FIVE) 5) ((RANK : FOUR) 4)
((RANK : THREE) 3)))
;; determine who won the hand, set them first next time
(cycle next (owner (max (union (all player 'P ('P vloc TRICK)))
using (game points PRECEDENCE))))
(all player 'P
(move (top ('P vloc TRICK))
(top (game vloc DISCARD))))
(set (game str LEAD) NONE)
;; if that was the last round, give the winner a point
((all player 'P (== (size ('P iloc HAND)) 0))
(inc ((next player) sto SCORE))))))
(scoring max ((current player) sto SCORE)))