clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

feat/app-decomposition
puzzletea / README.md
README.md 14.4K rendered
1# PuzzleTea23A terminal-based puzzle game collection built with [Bubble Tea](https://github.com/charmbracelet/bubbletea).45Fifteen puzzle games, multiple difficulty modes, daily and weekly deterministic challenges, XP progression, 365 theme options, and an explicit built-in registry plus metadata catalog for adding new games.67![PuzzleTea menu](vhs/menu.gif)89## Features1011- **15 puzzle games** -- Fillomino, Netwalk, Nonogram, Nurikabe, Ripple Effect, Shikaku, Sudoku, Sudoku RGB, Spell Puzzle, Word Search, Hashiwokakero, Hitori, Lights Out, Takuzu, Takuzu+12- **Daily puzzles** -- A unique puzzle generated each day using deterministic seeding. Same date, same puzzle for everyone. Streak tracking rewards consecutive daily completions.13- **Weekly gauntlet** -- Each ISO calendar week has a shared 99-puzzle ladder. The current week unlocks sequentially from `#01` to `#99`; past weeks can be reviewed from completed saves only.14- **XP and leveling** -- Per-category levels based on victories. Harder modes yield more XP. Daily puzzles grant 2x XP, and weekly puzzles add slot-based bonus XP.15- **Stats dashboard** -- Profile level, daily streak status, weekly completion progress, victory counts, and XP progress bars per category.16- **365 color themes** -- Live-preview theme picker with WCAG-compliant contrast enforcement. Dark and light themes included.17- **Mouse support** -- Drag interactions in Nonogram, Nurikabe, Shikaku, Spell Puzzle, and Word Search; click-to-focus in Fillomino, Hashiwokakero, Hitori, Sudoku, Sudoku RGB, Takuzu, and Takuzu+; click-to-rotate in Netwalk; click-to-toggle in Lights Out.18- **Seeded puzzles** -- Share a seed string to generate identical puzzles across sessions and machines.19- **Save/load persistence** -- Games auto-save to SQLite. Resume any in-progress game by name.2021## Games2223| Game | Description | Modes |24|------|-------------|-------|25| **Fillomino** | Grow numbered regions to their exact sizes | Mini 5x5 through Expert 12x12 |26| **Nonogram** | Fill cells to match row and column hints | 10 named modes from 5x5 `Mini` to 20x20 `Massive` |27| **Nurikabe** | Build islands while keeping one connected sea | 5 modes from 5x5 to 12x12 |28| **Ripple Effect** | Place digits in cages without violating ripple distance | Mini 5x5 through Expert 9x9 |29| **Shikaku** | Divide grid into rectangles matching cell counts | Mini 5x5 through Expert 12x12 |30| **Sudoku** | Classic 9x9 grid | Beginner, Easy, Medium, Hard, Expert, Diabolical |31| **Sudoku RGB** | Fill a 9x9 grid with three symbols so each row, column, and box contains three of each | Beginner, Easy, Medium, Hard, Expert, Diabolical |32| **Spell Puzzle** | Connect letters to reveal crossword words and bonus anagrams | Beginner, Easy, Medium, Hard |33| **Word Search** | Find hidden words in a letter grid | Easy 10x10, Medium 15x15, Hard 20x20 |34| **Hashiwokakero** | Connect islands with bridges | 12 modes across 7x7 to 13x13 grids |35| **Hitori** | Shade cells to eliminate duplicates | 6 modes from 5x5 to 12x12 |36| **Lights Out** | Toggle lights to turn all off | Easy (3x3) to Extreme (9x9) |37| **Netwalk** | Rotate network tiles until every computer reaches the server | Mini 5x5 through Expert 13x13 |38| **Takuzu** | Fill grid with two symbols | 7 modes from 6x6 to 14x14 |39| **Takuzu+** | Fill grid with symbols plus `=` and `x` relation clues | 7 modes from 6x6 to 14x14 |4041## Install4243### Homebrew (macOS / Linux)4445```bash46brew install FelineStateMachine/homebrew-tap/puzzletea47```4849### AUR (Arch Linux)5051```bash52yay -S puzzletea53```5455### WinGet (Windows)5657```powershell58winget install FelineStateMachine.puzzletea59```6061### From release binaries6263Download the latest binary for your platform from the [Releases](https://github.com/FelineStateMachine/puzzletea/releases) page.6465### From source6667Requires Go 1.24+.6869```bash70go install github.com/FelineStateMachine/puzzletea@latest71```7273Or clone and build:7475```bash76git clone https://github.com/FelineStateMachine/puzzletea.git77cd puzzletea78just # or: go build -o puzzletea79```8081## Usage8283Launch the interactive menu:8485```86puzzletea87```8889The Play menu includes:9091- `Create` for a new puzzle by category and mode92- `Continue` for saved games93- `Daily` for the shared deterministic daily puzzle94- `Weekly` for the current or historical weekly gauntlet95- `Seeded` for a custom deterministic seed9697Weekly gauntlets use the ISO week-year format shown in the menu, for example98`Week 10-2026 # 7`. The `#` value is the currently active weekly challenge for99that week. Current-week puzzles unlock one at a time; older weeks are review-only.100101Start a new game directly:102103```bash104puzzletea new nonogram classic105puzzletea new fillomino "Hard 10x10"106puzzletea new ripple-effect "Medium 7x7"107puzzletea new sudoku hard108puzzletea new ripeto expert109puzzletea new spell beginner110puzzletea new lights-out111puzzletea new netwalk "Easy 7x7"112puzzletea new hashi "Easy 7x7"113```114115Mode names are matched case-insensitively after normalizing spaces, hyphens,116and underscores. Multi-word mode titles usually need quotes.117118Resume and manage saved games:119120```bash121puzzletea list # show saved games122puzzletea list --all # include abandoned games123puzzletea continue amber-falcon # resume by name124```125126Use seeds for deterministic puzzle generation:127128```bash129# Deterministically selects game, mode, and puzzle from one seed.130puzzletea new --set-seed myseed131132# Deterministically generates a puzzle within a chosen game/mode.133puzzletea new nonogram epic --with-seed myseed134```135136Export printable puzzle sets to JSONL:137138```bash139# Stream JSONL to stdout (redirect if desired)140puzzletea new nonogram mini --export 2 > nonogram-mini-set.jsonl141142# Single mode export143puzzletea new nonogram mini -e 6 -o nonogram-mini-set.jsonl144145# Mixed modes within a category (deterministic with --with-seed)146puzzletea new sudoku --export 10 -o sudoku-mixed.jsonl --with-seed zine-issue-01147```148149Render one or more JSONL packs into a print PDF:150151```bash152puzzletea export-pdf nonogram-mini-set.jsonl -o issue-01.pdf --shuffle-seed issue-01 --volume 1 --title "Catacombs & Pines"153```154155`--title` sets the pack subtitle (title page, and outside cover when enabled), and `--volume` sets the volume number.156`half-letter` renders a plain booklet interior with no cover block.157`duplex-booklet` automatically includes the 4-page black-ink cover block with blank inside covers, and the actual cover color comes from the physical stock you print on.158When `duplex-booklet` is enabled, the title page shifts to logical page 3 so the first two and last two pages stay on cover stock.159Page count is always auto-padded to a multiple of 4 for booklet printing.160161Use `--sheet-layout duplex-booklet` to emit a landscape US Letter PDF with two portrait half-letter booklet pages per sheet side:162163```bash164puzzletea export-pdf nonogram-mini-set.jsonl -o issue-01-duplex.pdf --shuffle-seed issue-01 --volume 1 --title "Catacombs & Pines" --sheet-layout duplex-booklet165```166167`duplex-booklet` is meant for duplex printing without printer-side booklet mode. Print landscape on short edge.168169Font license note (Atkinson Hyperlegible Next):170171- Follow the SIL OFL 1.1 requirements in `pdfexport/fonts/OFL.txt`.172- Do not sell the font files by themselves.173- If redistributing fonts with software, include the copyright notice and OFL text.174- Modified font versions must keep OFL terms, and modified names must respect Reserved Font Name rules.175176`Lights Out` is currently excluded from export because it does not translate cleanly to paper workflows.177178Override the color theme:179180```bash181puzzletea --theme "Catppuccin Mocha"182```183184Flag aliases on the root command also work:185186```bash187puzzletea --new nonogram:classic188puzzletea --continue amber-falcon189```190191### CLI Aliases192193Several shorthand names are accepted for games: `polyomino`/`regions` for Fillomino, `hashi`/`bridges` for Hashiwokakero, `lights` for Lights Out, `network` for Netwalk, `islands`/`sea` for Nurikabe, `ripple` for Ripple Effect, `spell`/`spellpuzzle` for Spell Puzzle, `rgb sudoku`/`ripeto`/`sudoku ripeto` for Sudoku RGB, `binairo`/`binary` for Takuzu, `takuzu plus`/`binario+`/`binario plus` for Takuzu+, `words`/`wordsearch`/`ws` for Word Search, and `rectangles` for Shikaku.194195## Controls196197### Global198199| Key | Action |200|-----|--------|201| `Enter` | Select |202| `Escape` | Return to the menu or go back |203| `Ctrl+R` | Reset puzzle |204| `Ctrl+H` | Toggle full help |205| `Ctrl+C` | Quit |206207### Navigation208209Arrow keys, WASD, and Vim bindings (`hjkl`) are supported for grid movement across all games.210211### Mouse212213Nonogram, Nurikabe, Shikaku, Spell Puzzle, and Word Search support drag interactions. Fillomino, Hashiwokakero, Hitori, Sudoku, Sudoku RGB, Takuzu, and Takuzu+ support mouse focus or click-to-cycle interactions. Netwalk supports click-to-rotate and right-click lock toggles. Lights Out supports click to toggle. See each game's help for details.214215## Game Persistence216217Games are automatically saved to `~/.puzzletea/history.db` (SQLite). Navigating away saves progress; quitting with `Ctrl+C` marks the game as abandoned. Completed games are preserved and can be revisited.218219Daily and current-week weekly puzzles keep a single deterministic save per seed/week slot. Completed weekly puzzles from prior weeks reopen in review mode and are not modified when viewed again.220221## Previews222223### Fillomino224Grow numbered regions so each connected region reaches its exact size.225226![Fillomino](vhs/fillomino.gif)227228[Game details and controls](fillomino/README.md)229230### Ripple Effect231Place digits in cages while keeping matching values outside each other’s ripple distance.232233![Ripple Effect](vhs/rippleeffect.gif)234235[Game details and controls](rippleeffect/README.md)236237### Nonogram238Fill cells to match row and column hints.239240![Nonogram](vhs/nonogram.gif)241242[Game details and controls](nonogram/README.md)243244### Nurikabe245Build islands from clues while keeping one connected sea.246247![Nurikabe](vhs/nurikabe.gif)248249[Game details and controls](nurikabe/README.md)250251### Shikaku252Divide the grid into rectangles, where each rectangle contains exactly the number of cells shown in its clue.253254![Shikaku](vhs/shikaku.gif)255256[Game details and controls](shikaku/README.md)257258### Sudoku259Classic 9x9 number placement puzzle.260261![Sudoku](vhs/sudoku.gif)262263[Game details and controls](sudoku/README.md)264265### Sudoku RGB266Fill the grid with three symbols so every row, column, and box contains `{1,1,1,2,2,2,3,3,3}`.267268![Sudoku RGB](vhs/sudokurgb.gif)269270[Game details and controls](sudokurgb/README.md)271272### Word Search273Find hidden words in a letter grid.274275![Word Search](vhs/wordsearch.gif)276277[Game details and controls](wordsearch/README.md)278279### Spell Puzzle280Connect letters from a fixed bank to reveal a crossword and score bonus words.281282[Game details and controls](spellpuzzle/README.md)283284### Hashiwokakero285Connect islands with bridges.286287![Hashiwokakero](vhs/hashiwokakero.gif)288289[Game details and controls](hashiwokakero/README.md)290291### Hitori292Shade cells to eliminate duplicate numbers.293294![Hitori](vhs/hitori.gif)295296[Game details and controls](hitori/README.md)297298### Lights Out299Toggle lights to turn all off.300301![Lights Out](vhs/lightsout.gif)302303[Game details and controls](lightsout/README.md)304305### Netwalk306Rotate network tiles until every computer reaches the server in one loop-free tree.307308![Netwalk](vhs/netwalk.gif)309310[Game details and controls](netwalk/README.md)311312### Takuzu313Fill the grid with two symbols following three simple rules.314315![Takuzu](vhs/takuzu.gif)316317[Game details and controls](takuzu/README.md)318319## Building and Testing320321[just](https://github.com/casey/just) is used as the command runner:322323```bash324just # build325just run # build and run326just test # run tests (go test ./...)327just test-short # run tests, skipping slow generator tests328just lint # run golangci-lint329just fmt # format with gofumpt330just tidy # go mod tidy331just install # install to $GOPATH/bin332just clean # remove build artifacts333just vhs # generate all VHS GIF previews334```335336Run a single package's tests:337338```bash339go test ./nonogram/340go test ./sudoku/ -run TestGenerateGrid341```342343All code must pass `gofumpt` and `golangci-lint` before committing. CI runs both on every PR.344345## Adding a New Puzzle346347PuzzleTea uses an explicit built-in registry plus a metadata catalog. To add a new puzzle type:348349### 1. Create the game package350351Create a directory (e.g., `mypuzzle/`) with these files:352353| File | Purpose |354|------|---------|355| `gamemode.go` | Mode structs embedding `game.BaseMode`, `Modes`, `ModeDefinitions`, package-level `Definition`, and the built-in `Entry` |356| `model.go` | `Model` struct implementing `game.Gamer` |357| `export.go` | `Save` struct, `GetSave()`, `ImportModel()` for persistence |358| `keys.go` | Game-specific `KeyMap` struct |359| `style.go` | lipgloss styling and rendering helpers |360| `generator.go` | Puzzle generation logic (if applicable) |361| `grid.go` | Grid type and serialization (for grid-based games) |362| `help.md` | Embedded rules/help content wired into the runtime entry |363| `print_adapter.go` | Optional printable export adapter for JSONL/PDF support |364| `mypuzzle_test.go` | Tests (table-driven, save/load round-trip, generator validation) |365| `README.md` | Game docs: rules, controls table, modes table, quick start examples |366367Use `gameentry.BuildModeDefs(Modes)` and `gameentry.NewEntry(...)` so the368package exposes both metadata and its validated runtime wiring.369370### 2. Wire it into the built-in registry371372Edit the built-in registry once:373374- **`registry/registry.go`**: Import the package and add its exported `Entry` to `all` (maintain alphabetical order).375376The game package's `Definition` owns:377378- canonical name379- description380- aliases381- menu modes382- daily-eligible modes383- help content384- save/import function385386The `catalog` package is built from the registered entries and remains the pure387metadata index for names, aliases, and daily-mode lookup.388389### 3. Add a VHS preview390391- Create `vhs/<game>.tape` following the format in existing tapes.392- Add the tape to the `vhs` target in the `justfile`.393394### 4. Verify395396```bash397just fmt398just lint399just test-short400```401402See any existing game package (e.g., `nonogram/`) for the full pattern, and `AGENTS.md` for detailed conventions.403404## License405406[MIT](LICENSE)407408## Built With409410- [Bubble Tea](https://github.com/charmbracelet/bubbletea) - TUI framework411- [Lip Gloss](https://github.com/charmbracelet/lipgloss) - Terminal styling412- [Bubbles](https://github.com/charmbracelet/bubbles) - TUI components413- [Cobra](https://github.com/spf13/cobra) - CLI framework414- [modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite) - Pure-Go SQLite