A desktop falling-block marathon written in Rust, with an indigo interface, bright beveled blocks, an outlined ghost, animated clears, original sound cues, and saved personal records.
Install a Rust toolchain with Cargo and provide a working desktop display. Linux builds use native X11/OpenGL and ALSA libraries.
From this directory:
cargo run --locked --release
For a reproducible piece sequence and isolated preferences:
cargo run --locked --release -- --seed 424242 --data-dir artifacts/manual-profile
Build once with cargo build --locked --release -j 4, then launch target/release/prism-stack. The font is embedded, so the executable can run from a different working directory. --help prints launch options without opening a window. Random play is the default; seeded sequences are reproducible with the retained Cargo.lock.
| Input | Action |
|---|---|
| Left / Right | Move; hold for automatic repeat |
| Down | Soft drop |
| Up or X | Rotate clockwise |
| Z | Rotate counterclockwise |
| Space | Hard drop and lock |
| C or either Shift | Hold |
| Esc or P | Pause / resume; return from settings |
| R | Restart from pause or game over |
| M | Toggle sound |
| F11 | Toggle fullscreen |
| Up / Down, Enter | Select and activate menu actions |
| Mouse | Hover and click menu buttons |
Horizontal repeat begins after 150 ms and repeats every four simulation ticks, approximately 33 ms. The last pressed horizontal direction wins when both are held. Releasing it returns control to the other held direction. Rotation, hold, and hard drop respond to press edges.
Losing window focus pauses an active game. Returning focus leaves it paused until you resume. Held movement must be released before it acts again.
- The board has 10 columns and 20 visible rows, plus four hidden spawn rows. Logical X increases rightward and Y increases downward. Visible rows are
0..19; hidden rows are-4..-1. - All seven tetrominoes use SRS orientations and wall kicks, with the separate I kick table and stationary O geometry. Pieces spawn with their template origin at
(3, -1). - Each shuffled seven-piece bag contains I, O, T, S, Z, J, and L once. Five upcoming pieces are visible. Preview and hold use the same sequence.
- Hold is available once per active piece. Retrieved pieces return to their spawn position and orientation.
- The ghost shows the greatest legal downward displacement. Hard drop locks there immediately and awards two points per traversed row.
- Simulation runs at 120 Hz. Gravity is
max(0.05, 0.8^(level - 1))seconds per row. Soft drop accelerates to at least 30 rows per second and awards one point per player-accelerated row. - A grounded piece locks after 500 ms. Successful grounded moves or rotations can reset the timer up to 15 times. Failed actions do not reset it. Becoming airborne suspends grounded timing without restoring the reset allowance.
- Completed rows remain visible for a 150 ms clear phase, then compact simultaneously. Gameplay inputs during that phase do not manipulate the successor.
- Level starts at 1 and increases every ten cleared lines. A clear is scored at the level before it advances progression.
- A colliding spawn ends the run. A newly locked piece also ends it if all its surviving cells remain above the visible board after any clear and compaction. Partial hidden occupancy alone does not end play; a completely cleared piece has no surviving cells to lock out.
These are this clone's documented marathon rules.
Base clear points are multiplied by the current level:
| Clear | Base points |
|---|---|
| Single / double / triple / four-line clear | 100 / 300 / 500 / 800 |
| Full T-spin with 0 / 1 / 2 / 3 lines | 400 / 800 / 1200 / 1600 |
| Mini T-spin with 0 / 1 / 2 lines | 100 / 200 / 400 |
A T-spin requires a qualifying successful rotation and at least three occupied pivot corners. Both forward corners make it full; otherwise it is mini, with the final SRS kick candidate promoting it to full. Automatic gravity preserves rotation history. Successful lateral movement and positive-distance player drops clear it. A zero-distance hard drop preserves it, and failed inputs do not replace the last successful action.
Consecutive eligible line clears—four-line clears or T-spin line clears—receive a 1.5× back-to-back multiplier after the first. Ordinary one-to-three-line clears break that chain. Locks without clears preserve the chain. Consecutive clearing locks also award 50 × combo_index × level; the first clear has index zero, and a nonclearing lock resets the combo. Drop points are separate from these multipliers.
Settings provides volume, mute, reduced motion, and high contrast. Reduced motion disables ambient movement and most particles. High contrast strengthens the grid, block borders, and ghost, and adds piece letters.
The interface uses a 1280 × 800 design layout with a 320 × 640 board. Resizing scales it uniformly; at 960 × 640 it uses a 960 × 600 layout with letterboxing. Smaller windows retain the complete interface through proportional scaling.
By default, preferences and records use the platform application data directory. --data-dir PATH selects another directory. The versioned settings.json contains schema_version, high_score, best_lines, and settings; settings contains master_volume, muted, reduced_motion, and high_contrast. Records update at game over. Preferences save when changed.
Missing settings use defaults. Malformed, unsupported, or unreadable settings produce a nonblocking warning and preserve the original file. Saving stays disabled for that load to avoid overwriting it. Normal saves use an exclusively created settings.json.tmp sibling followed by replacement. A write failure leaves the valid in-memory profile available.
Original short sound cues are synthesized once at startup. If the audio backend cannot initialize, the game reports the problem and continues graphical play.
Run the deterministic checks from this directory:
python3 tools/check_source_layout.py
cargo fmt --all -- --check
cargo test --locked --all-targets -j 4
cargo clippy --locked --all-targets -j 4 -- -D warnings
cargo build --locked --release -j 4
The regression suite covers piece geometry and SRS kicks, collision and compaction, bags, hold, ghost and drop behavior, lock timing, scoring and spin history, top-out, input timing, screen lifecycle, persistence failures, audio synthesis, and seeded marathon invariants. tests/layout.rs directly checks that horizontal coordinates increase rightward and logical rows increase downward through the actual Macroquad camera matrix.
The successful native interface session retained its application captures under artifacts/native-final/, including active gameplay, pause, and game over. The native line-clear session retained its compacted board capture under artifacts/native-line-clear/. The interactive results, screenshot descriptions, recovery history, and qualification limits are recorded in docs/manual-test-report.md. Native input, OCR, and pixel comparisons passed; direct visual inspection of the PNGs remains unverified. Older captures under artifacts/screenshots/ are preserved as troubleshooting evidence.
src/game/ owns deterministic rules and exposes immutable views and domain events. src/play_session.rs owns game and screen transitions. src/input.rs handles simulation input; src/native_input.rs adapts native window events. src/render/ reads game state and owns presentation only. Audio, storage, and clocks have separate boundaries. src/app.rs connects those components, and src/main.rs configures the window. Production Rust files are limited to 500 lines.
The embedded DejaVu Sans font and its license are retained in assets/fonts/DejaVuSans.ttf and assets/licenses/DejaVu-Fonts.txt. Visual geometry and sound cues are generated by the application.