TriPeaks solitaire roguelike with Balatro full system stack — Godot 4.6 / GDScript. The spatial Balatro.
Find a file
Alan Gaudet ca989f8ef0
Some checks are pending
export / export · Godot 4.6.3 · linux + windows + web (push) Waiting to run
tests / gdUnit4 · Godot 4.6.3 · headless (push) Waiting to run
docs: state §8's next milestone in the form the loop reads
The autonomous roadmap is exhausted at m18 and everything left in §8 is a
verification ask or a taste call. Saying that explicitly lets the loop exit
clean rather than pause looking for a milestone that was never planned.

milestone-cycle v1.12.0 writes one canonical marker and re-parses it before
committing, so this file is now round-trip clean against the loop's own parser.
2026-07-25 13:49:42 -04:00
.forgejo/workflows feat(m17b): CI export workflow — desktop + web artifacts, content smoke + upload (GitHub + Forgejo) 2026-06-07 09:53:08 -04:00
.github/workflows feat(m17b): CI export workflow — desktop + web artifacts, content smoke + upload (GitHub + Forgejo) 2026-06-07 09:53:08 -04:00
addons/gdUnit4 feat(M0): scaffold — Godot 4.6.3 project, gdUnit4, CI, deterministic RNG/Card/Deck (0.0.1) 2026-06-06 21:10:07 -04:00
app feat(audio): economy cues — buy / sell / use / reroll now make a sound 2026-06-08 09:11:56 -04:00
assets feat(m14e): credits screen renders ATTRIBUTION.md (gate 3) 2026-06-07 07:08:22 -04:00
content/data feat(gold): reprice shop to the gold scale 2026-06-07 19:36:38 -04:00
core feat(jokers): the overlay shows a scaling joker's current accrued value 2026-06-08 10:03:08 -04:00
docs docs: state §8's next milestone in the form the loop reads 2026-07-25 13:49:42 -04:00
presentation feat(run-end): show the build you finished with (the "one more run" hook) 2026-06-08 10:12:29 -04:00
tests feat(run-end): show the build you finished with (the "one more run" hook) 2026-06-08 10:12:29 -04:00
.gitignore chore: gitignore CGC-generated .cgcignore (local index tool, not project state) 2026-06-07 02:10:51 -04:00
AGENTS.md docs: make AGENTS.md the real context file, symlink CLAUDE.md and GEMINI.md 2026-07-25 03:08:57 -04:00
BETA_TESTING.md feat(run-end): show the build you finished with (the "one more run" hook) 2026-06-08 10:12:29 -04:00
CHANGELOG.md docs(closeout): finalize Phase-3 as a tester-ready beta (0.18.0) 2026-06-08 10:55:13 -04:00
CLAUDE.md docs: make AGENTS.md the real context file, symlink CLAUDE.md and GEMINI.md 2026-07-25 03:08:57 -04:00
export_presets.cfg feat(m17a): export presets + content-survival include filter + --smoke self-check 2026-06-07 09:51:18 -04:00
GEMINI.md docs: make AGENTS.md the real context file, symlink CLAUDE.md and GEMINI.md 2026-07-25 03:08:57 -04:00
LICENSE docs: loop-ready doc set (ROADMAP M0–M17 + SESSION_NOTES + CHANGELOG + promoted strategy + seeds) 2026-06-06 18:55:35 -04:00
play.sh fix(phase3): isolate "Settings Close does nothing" to XWayland pointer misrouting + native-Wayland launcher 2026-06-07 12:35:37 -04:00
project.godot feat(M0): scaffold — Godot 4.6.3 project, gdUnit4, CI, deterministic RNG/Card/Deck (0.0.1) 2026-06-06 21:10:07 -04:00
README.md docs(closeout): finalize Phase-3 as a tester-ready beta (0.18.0) 2026-06-08 10:55:13 -04:00
ROADMAP.md chore(release): 0.18.0 — gold-wager unify (Phase 3) 2026-06-07 20:07:12 -04:00
run_tests.sh feat(M0): scaffold — Godot 4.6.3 project, gdUnit4, CI, deterministic RNG/Card/Deck (0.0.1) 2026-06-06 21:10:07 -04:00
TODOS.md docs(closeout): finalize Phase-3 as a tester-ready beta (0.18.0) 2026-06-08 10:55:13 -04:00

Peakjoker

License Engine Status

A TriPeaks solitaire roguelike that grafts Balatro's full system stack onto the TriPeaks card-clearing loop. Clear chains of rank-adjacent cards to build a chips × mult score, beat rising blind thresholds across antes, and spend money in a shop on jokers, consumables, deck upgrades, and vouchers — chasing emergent, run-defining combos.

The defining adaptation: a streak is a "hand." Clearing rank-adjacent cards in a row builds the streak (each clear adds chips and pumps mult); drawing from the stock banks the streak and starts a new one. "Push the streak vs. bank it and draw" is the core tension — the direct analog of Balatro's limited hands.

The strategy is "the spatial Balatro": board geometry (which peak, how deep, what a card covers, the order you free it) is a first-class scoring and build surface — the axis Balatro structurally can't touch, because its cards have no position.

Status

M0M17 complete + Phase-3 polish arc complete — 0.18.0, a tester-ready beta. The full game is built: a complete TriPeaks-roguelike run (board → blinds → shop → jokers / consumables / vouchers → boss → ante escalation), meta-progression + versioned save, daily seed + run-share, mid-run save/resume, a win-gated stakes ladder, modding, and controller / Steam-Deck support — 743 headless tests green. The game was built by the autonomous /milestone-cycle loop across the M0M17 arc in ROADMAP.md; a subsequent Phase-3 polish arc — in-game QA plus a 19-commit "clear the invisibility gaps" sweep that surfaced everything the engine computes but no screen showed — brought it to a tester-ready beta. Remaining work is tester-feedback-driven (feel / difficulty tuning), tracked in docs/SESSION_NOTES.md; the beta-tester guide is BETA_TESTING.md.

Tech stack

Area Choice
Engine Godot 4.6.3 stable, Compatibility renderer (2D, keeps web export cheap)
Language GDScript (headless-testable; no C# toolchain weight)
Tests gdUnit4 (headless, CI-wired from M0)
Scoring Fixed-point integer math (cross-platform deterministic)
Cards Adrian Kennard SVG deck (CC0) · icons Kenney.nl (CC0) — see assets/ATTRIBUTION.md
CI GitHub Actions (gate) + Codeberg/Forgejo (best-effort)

Architecture (in one breath)

A decoupled deterministic core + data-driven content. The core/ is pure GDScript (RefCounted/Resource only) and never touches the scene tree — it is a deterministic state machine with a single mutation entry, apply(action) → [events]. Presentation observes events and renders; it never mutates the core. Same seed + same actions[] ⇒ bit-identical result, every run — so a replay is a unit test. Content (jokers, bosses, consumables, vouchers, …) is authored as validated, read-only Resource .tres files composed from a small effect-primitive vocabulary. See the design spec §3 for the full layout.

res://
├── core/          # pure GDScript: rng, card, deck, board_state, score_engine, run_state, shop, blind, game_controller
├── content/       # data-driven content: defs/ (Resource classes), effects/ (hooks), data/ (.tres instances)
├── presentation/  # Godot scenes/nodes — observe the core, never mutate it
├── app/           # autoloads: Game, Save, Assets, Audio
└── tests/         # gdUnit4 — seeded, headless

Build & test

# build the import cache once (required before headless tests)
godot --headless --import

# run the headless test suite — canonical local runner (exit 0 = pass)
./run_tests.sh                  # CI uses ./addons/gdUnit4/runtest.sh -a res://tests under xvfb

# play it (windowed)
godot --path .

License

Peakjoker is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). See LICENSE.

Bundled art assets are licensed separately under their own permissive terms (CC0 / CC BY) — see assets/ATTRIBUTION.md.