Schwimmen

Summary

In Schwimmen, a Piquet deck is shuffled and each player is dealt three cards. Three additional cards are placed face down in the middle of the table. The dealer decides if they want to exchange their hand for the three face-down cards. Then, these table cards are turned face-up, and play begins. On a player’s turn, they can exchange their whole hand with the face-up cards, or exchange an individual card, or pass. If all players have passed, and cards remain in the deck, then three new cards are dealt face-up to the table and play resumes, otherwise the game ends. After making their choice, a player could decide to close, and all other players have one more opportunity to exchange. Certain high-scoring card combinations must be revealed, and when they are the game will end. Players are awarded points based on the highest sum of one suit, and the player with the most points wins.

Rules of Play

These rules are summarized from https://www.pagat.com/commerce/schwimmen.html.

Variants Used

Because RECYCLE requires the use in integers, the score values calculated in Schwimmen are doubled when calculated at the end of the game.

Schwimmen is a commerce or exchange game. Other games similar to Schwimmen include Brag and Kemps.

Information Flow

Card Movement Graph

The diagram above visualizes information flow in Schwimmen 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 Schwimmen are coded in RECYCLE, a card game description language, to encourage standardized implementations across different systems.

You can also Download the code.

;; Schwimmen
;; https://www.pagat.com/commerce/schwimmen.html
;; Scoring is doubled to keep scores integers

(game
 (declare 5 'NUMP)
 (setup
  (create players 'NUMP)

  ;; Create the deck source, 32 card piquet pack
  (create deck (game iloc STOCK) 
   (deck (RANK (SEVEN, EIGHT, NINE, TEN, J, Q, K, A))
         (COLOR (RED (SUIT (HEARTS, DIAMONDS)))
                (BLACK (SUIT (CLUBS, SPADES)))))))
 (do (
  (shuffle (game iloc STOCK))

  ;; give everyone 3 cards, put 3 aside on the table
  (all player 'P 
   (repeat 3 (move (top (game iloc STOCK))
                   (top ('P iloc HAND)))))
  (repeat 3 (move (top (game iloc STOCK))
                  (top (game iloc EXTRA))))
                
  ;; set the scores for the cards
  (set (game points SCORE)
   (((RANK : A)    11) ((RANK : K)    10) ((RANK : Q)   10) 
    ((RANK : J)    10) ((RANK : TEN)  10) ((RANK : NINE) 9) 
    ((RANK : EIGHT) 8) ((RANK : SEVEN) 7)))))

 ;; dealer can swap their hand if they want with the extra
 (choice (
  (swap ((current player) iloc HAND) (game iloc EXTRA))

  (turn pass)))

 ;; flip what is left in EXTRA to the MIDDLE for everyone to see
 (do (
  (repeat all (move (top (game iloc EXTRA))
                    (top (game vloc MIDDLE))))))

 ;; play the game until there are no more cards, 
 ;; someone closes and all have a turn, or someone has high score
 (stage player 
  (end (or (< (size (game iloc STOCK)) 3)
           (> (game sto CLOSE) 'NUMP)
           (any player 'P 
            (or (any (partition RANK ('P iloc HAND)) 'RP 
                     (== (sum 'RP using (game points SCORE)) 33))
                (any (partition SUIT ('P iloc HAND)) 'RP
                     (== (sum 'RP using (game points SCORE)) 31))))))
    
  ;; play a round until everyone passes,
  ;; someone closes and all have a turn, or someone has high score
  (stage player 
   (end (or (== (game sto PASS) 'NUMP)
            (> (game sto CLOSE) 'NUMP)
            (any player 'P 
             (or (any (partition RANK ('P iloc HAND)) 'RP 
                      (== (sum 'RP using (game points SCORE)) 33))
                 (any (partition SUIT ('P iloc HAND)) 'RP
                      (== (sum 'RP using (game points SCORE)) 31))))))

   ;; exchange or pass
   (choice (
    ;; pass
    (inc (game sto PASS))
                
    ;; exchange all cards with the middle
    (do (
     (swap ((current player) iloc HAND) (game vloc MIDDLE))
     (set (game sto PASS) 0)))

    ;; exchange one card in hand for one card on table
    (any ((current player) iloc HAND) 'HC
     (any (game vloc MIDDLE) 'MC 
      (do (
       (swap 'HC 'MC)
       (set (game sto PASS) 0)))))))

   ;; possibly close the game
   (choice (
    ((== (game sto CLOSE) 0)
     (do (
      (set (game sto CLOSE) 1)
      (set (game sto PASS) 0))))

    (turn pass)))

   ;; if someone has ended the game, increment the counter
   (do (
    ((!= (game sto CLOSE) 0)
     (inc (game sto CLOSE))))))

   ;; when everyone passed, discard the MIDDLE 
   ;; and deal out 3 more cards
   (do (
    (set (game sto PASS) 0)
    ((>= (size (game iloc STOCK)) 3)
     (do (
      (repeat all (move (top (game vloc MIDDLE))
                        (top (game vloc DISCARD))))
      (repeat 3 (move (top (game iloc STOCK))
                      (top (game vloc MIDDLE))))))))))

 ;; calculate the scores (times 2 for simplicity)
 (stage player 
  (end (all player 'P (== (size ('P iloc HAND)) 0)))
  (do (

   ;; best score in one suit is kept
   (all (partition SUIT ((current player) iloc HAND)) 'RP 
    (let (sum 'RP using (game points SCORE)) 'RS 
     ((> 'RS ((current player) sto SCORE))
      (set ((current player) sto SCORE) (* 2 'RS)))))

   ;; Feuer (fire): a hand of three aces is only 32
   ((any (partition RANK ((current player) iloc HAND)) 'RP
         (and (== (size 'RP) 3)
              (== (cardatt RANK (top 'RP)) A)))
    (set ((current player) sto SCORE) 64))

   ;; Other three of a kind scores 30.5
   ((any (partition RANK ((current player) iloc HAND)) 'RP
         (and (== (size 'RP) 3)
              (!= (cardatt RANK (top 'RP)) A)))
    (set ((current player) sto SCORE) 61))

   (repeat all (move (top ((current player) iloc HAND))
                     (top (game vloc DISCARD)))))))

 (scoring max ((current player) sto SCORE)))