โ† All 22 apps

CandyTetris

๐ŸŽฎ CandyTetris

Tetris on the SugarCraft stack

inspired by Broderick-Westrope/tetrigo game tetris srs deterministic

CandyTetris code coverage

SugarCraft runtime, SugarStyle for rounded borders + per-piece colours, deterministic 7-bag RNG, ghost piece, hard drop, hold, level-driven gravity ramp, NES-style line-clear scoring. Full SRS wall-kicks via official Tetris Association tables, T-Spin detection via the centre-diagonal 3-corner rule, Back-to-Back (1.5ร—) and combo bonuses, and perfect-clear detection (+5000/level).

Install

composer require sugarcraft/candy-tetris

# or run the shipped binary from a clone:
composer install
./candy-tetris/bin/candy-tetris        # single player
./candy-tetris/bin/candy-tetris --vs   # VS the computer

Quickstart

./bin/candy-tetris

# Controls
# โ† / โ†’   Move left / right
# โ†‘ / x   Rotate clockwise
# z       Rotate counter-cw
# โ†“       Soft drop
# Space   Hard drop
# c       Hold piece
# p       Pause / resume
# r       Restart after game over
# q       Quit

What's in the box

SRS rotationFull Super Rotation System โ€” official Tetris Association kick tables for J/L/S/T/Z and I piece. Tries up to 5 offsets per rotation transition; the first that fits the board is used. The board y-axis is inverted exactly once, in Piece::rotationsWithKicks.
7-bag RNGDeterministic shuffle of the seven pieces; injectable RNG closure for reproducible tests. Value-semantic: next() returns the piece plus an advanced bag, peek() is a pure preview that consumes neither state nor draws.
Ghost pieceTranslucent preview at the hard-drop landing position.
Hard drop / holdSpace-bar drop; level-driven gravity speed-up at every 10 lines. Lock delay (500 ms window, 15-reset cap) in single player; VS boards lock on the grounding tick.
Line-clear scoringNES-style base points โ€” 1 โ†’ 40, 2 โ†’ 100, 3 โ†’ 300, 4 โ†’ 1200 โ€” multiplied by (level + 1); the T-Spin and B2B bonuses follow the modern Guideline.
T-Spin (3-corner rule)Guideline detection on the diagonals of the T's centre: 3+ filled corners (wall/floor count as filled) score a full T-Spin (400 ร— level+1); exactly 2 with one on the nub side score a Mini (100 ร— level+1); 2 back corners score nothing. A Mini clearing 2+ lines is promoted to full.
Back-to-Back (B2B)1.5ร— multiplier carried by consecutive difficult CLEARS (Tetris, or a full T-Spin that cleared lines). Resets on an ordinary 1โ€“3 line clear; a clear-less lock โ€” spin or quiet โ€” leaves the chain untouched.
Combo counterConsecutive line clears add combo ร— 10 ร— (level+1) bonus points; resets to 0 on a zero-line lock.
Perfect clearClearing the full board awards +5000 ร— (level+1) bonus โ€” detected via Board::isPerfectClear().
Pure-state classesTetromino, Piece, Board, Bag, Score, Game โ€” immutable value semantics throughout, each individually testable without booting the runtime.

Source

Try the quickstart โ†’

API

ClassMethodDescription
Tetrominocases() / color()Backed enum of the seven kinds; 256-colour code per kind
Piecerotated(delta) / moved(dx, dy)Immutable transforms (withX/withY for placement)
PiecerotationsWithKicks(board, delta)Candidate positions in SRS kick order (naive first)
Boardnew(rows)10-wide grid (4 hidden + 20 visible rows; dims fixed)
Boardplace(piece)Lock a piece's cells into the grid
Boardfits(piece) / dropPiece(piece)Legality gate and resting-position query
BoardclearLines() / isPerfectClear()Clear completed rows; true iff the grid ends empty
Bagnext()Returns [Tetromino, advanced Bag] โ€” value semantics
Bagpeek(n)Pure preview; mutates nothing and consumes no draws
ScorewithLines(count)New Score: NES base ร— (level+1), lines, level re-derived
Gamestart() / update(msg)TEA model: every message yields [Game, ?Cmd]
SrsKickTablekicks(piece, from, to)Return kick offsets for a rotation transition
SrsKickTableallKicks(piece)Return all transition tables for a piece
Scoring\TSpindetect(board, piece, wasRotated)Centre-diagonal 3-corner rule; returns TSpin(active, mini)
Scoring\TSpinT_SPIN_POINTS / T_SPIN_MINI_POINTSBase score constants (400 / 100, scaled by level+1)

Demos.

VHS-recorded GIFs of the shipped tapes. Regenerated automatically on every push that touches the source.

Play

Play

Full game with ghost piece, hard drop, level-driven gravity.
Hold demo

Hold

Piece hold and swap with the sidebar hold card.
VS computer

VS Computer

Split-screen match against the built-in AI opponent.
VS computer, simple

VS Computer (simple)

The same match at a gentler starting level.