diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fb991a8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,44 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project + +`kostky` is a Czech-language terminal CLI game — a Farkle/"tisícovky" dice game variant for multiple players. Single runtime dependency: `tabulate` (for the final results table). + +## Commands + +```bash +pip install -e ".[dev]" # editable install with mypy + ruff +kostky # run the game (after install) +python -m kostky # run without installing (requires tabulate) +mypy # type-check (strict mode, see pyproject.toml) +ruff check . # lint +``` + +There are no tests in this repository. + +## Architecture + +The entire game lives in `kostky/kostky.py` as a single module with module-level mutable state (no classes): + +- `hodnoty: dict[str, int]` — scoring table, loaded at import time from `kostky/hodnoty.csv` via `importlib.resources`. Keys are sorted-digit strings representing dice combos (e.g. `"111"` = three ones), values are point totals. +- `players: dict[str, list[int]]` — per-player history of per-turn scores (insertion order == turn order). +- `aggr: dict[str, int]` — per-player running total, used for win checks and the results table. +- `pointer` / `first` — current player's name / the player who started the round (used to detect when a full round has completed in `next_player`/`check_win`). +- `score` — points accumulated *within the current turn*, reset on bust or on banking (`k`). +- `h_bool` — guards re-rolling: you can't roll again until you've banked at least one scoring combination in the current roll sequence. + +Control flow is a manual state machine driven by tuples, not exceptions or return codes: + +- `evaluate(inp, count, throw)` parses a single line of user input against the current dice state and returns a `data` tuple whose first element is a tag: `"count"` (continue turn with N remaining dice and a throw string), `"msg"` (show an error/message, possibly re-prompting), `"win"`, or `"exit"`. +- `game(data)` is the main loop: it pattern-matches on `data[0]`, prints state, prompts for input, and calls `evaluate` again to get the next `data` tuple. This loop is how every turn — and the whole game — progresses. +- Dice picks are entered as letters (`a`-`f` mapped to position 1-6 via `ord(x)-96`), not digit values; `evaluate` converts letters to positions internally before checking the picked dice values against `hodnoty`. +- Bust detection (`check_value`) checks whether *any* key in `hodnoty` is a substring of the sorted current throw — not a full combinatorial scoring check, so this is the single source of truth for "is this throw dead." +- Win condition (`check_win`) only fires once `pointer` cycles back to `first`, i.e. checked once per full round rather than once per turn, and only declares a winner if exactly one player is alone at/above `final_score`. + +`kostky/__main__.py` and the `kostky` console-script entry point (in `pyproject.toml`) both call `kostky.kostky.main()`. + +## Scoring data + +`kostky/hodnoty.csv` (digit-string-of-dice-values → points) is the single source of truth for scoring and is also documented in tables in `README.md`. If you change one, update the other.