# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash python3 -m venv .venv && .venv/bin/pip install -r requirements.txt # pygame .venv/bin/python das_tetris_gui.py # run the game .venv/bin/python -m unittest discover -s tests -v # all tests (headless, SDL dummy driver) .venv/bin/python -m unittest tests.test_game.TetrisGameTest.test_clear_lines_scoring # single test .venv/bin/pyinstaller das_tetris_gui.spec # build executable into dist/ (local spec, git-ignored; equivalent: pyinstaller --onefile das_tetris_gui.py) ``` Smoke-run headless: `SDL_VIDEODRIVER=dummy timeout -s KILL 5 .venv/bin/python das_tetris_gui.py`. Use SIGKILL: SDL turns SIGTERM into `pygame.QUIT`, which opens the "exit?" dialog and waits forever. ## Architecture - `das_tetris_gui.py` – entry point. `TetrisGame` (field, falling piece, scoring, speed, input), `TetrisRenderer` (pygame drawing), `show_question_dialogue` (modal Yes/No loop that runs its own event loop), `main()` loop at 60 FPS. - `tetris_config.py` – `load_config()` overwrites module-level globals (`KEY_CONFIG`, `COLORS`, `BLOCK_TYPE`, `STORE_WIDTH`, `BLOCK_SIZE`, `HIGH_SCORE_INC_SPEED`, …). The game module calls it **at import time** and copies most globals into its own names, but reads `cfg.HIGH_SCORE_INC_SPEED` live. The hard-coded `BlockType` enum in this file is only the source for `store_config()`; at runtime `BLOCK_TYPE` is rebuilt dynamically from JSON. - `Serializer.py` – `EnumSerializer`: JSON ⇄ Python with `__type__` tags (`PygameKey` stored by name, `tuple`/`list`/`set`, `EnumClass`, `EnumInstance`). Used for `config.json`; block files are read with plain `json`. ### Config files (`configs/`) - `config.json`, `blocks.json`, `blocks_ADD.json` – local/working configs. If one is missing, `_000.json` (committed defaults) is used. Paths are resolved next to the script, or next to the executable when frozen. - Blocks from `blocks.json` (`ALL_BLOCKS.members`) and `blocks_ADD.json` (`ADDITIONAL_BLOCKS.members`, optional) are merged; a later key overrides an earlier one. Each block: `name`, `color` `[r,g,b]`, `min_score` (block appears only once score reaches it; at least one must be 0), `shapes` – list of rotations (clockwise), each a 0/1 matrix drawn from the top-left. - Field cells store `index in list(BLOCK_TYPE) + 1`, so block order matters for rendering. Blocks with identical values become Enum aliases and disappear from `list(BLOCK_TYPE)`. - `high_score_inc_speed` (optional, default false): `fall_speed` is the drop interval in seconds, so `true` makes the game **slower** above 5000/10000/15000 points, `false` makes it faster. - `tetris_config.store_config()` overwrites `config.json`/`blocks.json` from the hard-coded values – do not call it casually. ### Misc - `other/` (git-ignored) holds early prototypes and translations of other Tetris implementations; not used by the game. - PyInstaller spec bundles no data files: the built executable needs a `configs/` folder beside it.