Metadata-Version: 2.5
Name: magmacrunch-scandinavian-stud
Version: 0.1.1
Summary: Sökö, Scandinavian stud poker, against three computers. Terminal version.
Project-URL: Homepage, https://magmacrunch.com/arcade/scandinavian-stud/
Author: magmacrunch media
License-Expression: PolyForm-Noncommercial-1.0.0
License-File: LICENSE
License-File: NOTICE
Keywords: arcade,cards,games,poker,stud,terminal,tui
Requires-Python: >=3.10
Requires-Dist: magmacrunch>=0.17.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: websockets>=14.0; extra == 'dev'
Provides-Extra: online
Requires-Dist: websockets>=14.0; extra == 'online'
Description-Content-Type: text/markdown

# Sökö (terminal)

Sökö, Scandinavian stud poker, against the page's three computers, Mikko,
Liisa and Jussi, in a terminal. It is the second version of the game, beside
`web/`. It runs on the [magmacrunch](https://github.com/magmacrunch-media/magmacrunch)
engine's terminal backend, either as a cabinet in the magmacrunch arcade or as
its own command, and plays the same either way.

```
pipx install magmacrunch-scandinavian-stud
soko                    # the title
soko --play --seed 7    # straight to the table, the same shuffles every time
soko --online           # PLAY ONLINE (needs the [online] extra)
```

PLAY ONLINE, a prototype, plays people instead, through the page's own
server: `pipx install "magmacrunch-scandinavian-stud[online]"`.

For working on it, from this folder, once the website's `shared/` is linked
in beside `web/` (`node tools/link-shared.mjs` from the repository's root),
which the oracle test needs:

```
pip install -e ".[dev]"
python -m stud
```

## Keys

| key | |
|---|---|
| `←` `→` | choose among the actions the page would offer |
| `ENTER` | take it; at the end of a hand, deal the next |
| `C` `R` `F` | check or call, raise, fold |
| `N` | a new table |
| `Esc` | the title (and from there, the arcade) |
| `Q` | quit |

The three computers sit above, you below. Your cards are all shown, your hole
card first; theirs show their face-up cards and a `▓▓` for the hole card
until a showdown. Each seat says its chips, its bet this round, and when it
has folded or gone all-in; your hand is named as the page names it, Finnish
and English. The labels are the page's own pairs: *Sekötä / check*, *Maksaa /
call*, *Nostaa / raise*, *Luovuttaa / fold*. The computers keep the page's
clock: one decides 0.8 seconds after its turn comes, and a finished round of
betting deals the next street after 0.6.

Win every chip the computers have and the table is yours, and it goes on
the high-score table as the page scores it: your chips per hand it took,
x100, so the faster the clear, the higher. A
player with no chips sits every hand out after; when that is you, the table
is lost and the next is a new one.

Needs a 78x24 terminal.

## It is the browser's game, and the browser's opponents

`stud/rules.py` is `web/js/config.js`, `hand-eval.js` and `game.js`, with the
deck and its shuffle from the website's `shared/adenosine-cards.js` and the
turn-taking of `main.js`, function for function. The shuffle is the only
random thing in the game: the computers decide by rule. Two tests hold the
port to the page:

- **`tests/test_oracle.py`.** `tools/js_oracle.mjs` loads those files
  unmodified, with a seeded `Math.random`, and plays 40 tables of 80 hands
  through `SokoGame`'s own API in `main.js`'s order: 3,200 hands, about 55,000
  actions. Half have a random player in your seat, half a calling station. The
  test shuffles the same decks through the port and requires the same state
  after every action: every player's chips, cards, bet and hand, the pot, the
  bet to match, the street, whose turn, the raises and who has acted, the
  phase and the winner, and starts a new table where the page does. Moving
  a style's mark, or dealing in a player with no chips again, fails it within
  the first table.
- **`tests/test_rules.py`.** It sets up by hand the cases worth pinning,
  including the page's own rules below, so that fixing one shows as a change.

## The page's rules

The page's betting, side pots, ties and computers were fixed in
scandinavian-stud#3, and the port with them. Two places where it is still not
poker, kept because the oracle requires them:

- **A tie is not split.** The pot goes to the tied player nearest the
  dealer's left. Each pot is its own: an all-in player wins only the part
  they matched, and the rest goes to the best hand among those who matched it.
- **A conservative or moderate computer with nothing never calls.** High card
  scores 0, under their call marks, so they check when they can and fold to
  any bet. The aggressive one calls anything.

## Online, a prototype

PLAY ONLINE meets two to four people, in terminals or browsers, in a room on
the arcade's own server, `web/server.py`, the one behind the page's
Multiplayer button. One creates the room and says its four-letter code, the
others join with it, and the host deals. `--server ws://host:8767` points at
another server, a Pi on the same network say.

The server keeps the game: it deals, says whose turn it is and what they may
do, and sends the whole table after every action. `stud/online.py` keeps that
latest table and sends the action chosen; `stud/online_scenes.py` draws it
with the same table screen as the computers, you below and the others above
in the server's order from you. Hand after hand anyone at the table deals the
next with ENTER, until one player holds every chip.

`tests/test_online.py` runs the real server in-process and plays real
clients against it over real sockets. Three players take seeded random
actions through a whole table to a table won, and after every
action every client's table is the server's view for that player. Two terminal sessions also
play a hand by keys. Making the client ignore the server's `hand_started`
frames fails both. A terminal session has also played three hands against
the page in Chromium through `web/server.py` run as the Pi runs it, the two
agreeing on every chip.

**Each player is sent only their own hole card.** The server builds the
table again for each player as it sends a frame: their own hole card, and
everyone's still in once a hand goes to a showdown; a hand won by a fold
shows nobody's. A spectator sees what a player sees of the others. It used
to send one frame to the whole room with every hole card and hand in it,
which the page and this client drew face down but anyone reading the frames
could see. `tests/test_online.py` searches every frame of a table played to
showdowns and folds, by three players and a spectator, for anything else,
and fails against the old server.

The server plays the page's rules. A raise is always the street's step,
whatever amount a client sends, and a player who resigns or leaves folds the
hand and sits out every one after it while the rest play on.

## Licence

PolyForm Noncommercial 1.0.0, as for the rest of this repository. See `LICENSE`
and `NOTICE`.
