
Tetro TUI - Terminal Game
Tetro TUI is a terminal-based but modern tetromino-stacking game that is very customizable and runs cross-platform.

Ways to Run
Download & run
- Download a release for your platform (Linux/MacOS/Windows/...) if available.
- Navigate to the application (
tetro-tui/tetro-tui.exe/...) and run it
Compile from source
Tetro TUI is written in Rust and can be compiled as usual:
git clone https://github.com/Strophox/tetro-tui # Or otherwise download source code.
cd tetro-tui
cargo run
Install via cargo
Tetro TUI is available on crates.io. It can be installed via cargo:
cargo install tetro-tui
This makes tetro-tui available to run for your terminal.
Install on Arch Linux
Tetro TUI is available on aur.archlinux.org. It can be installed e.g. via yay or paru:
yay -S tetro-tui
FAQ
How does the base game work?
Tetro TUI is about tetromino pieces falling from the sky and stacking inside a 2D playing field. When a horizontal line is full it automatically clears away and everything 'stacked' above shifts down.
A skilled player may keep playing indefinitely. Different game modes will change up the gameplay while still using the same base mechanics.
How good is it in terms of customization / features?
We provide a solid amount of configuration options and features:
- Graphics: Unicode/ASCII/Electronika, color palettes, many effects and toggles.
- Gameplay and handling: Rotation systems, randomizers, preview, timings (DAS, ARR, SDF, LDC, ARE), IRS/IHS/IMS/ITS (*caveat).
- Game keybinds: to your heart's desire.
- Game mode miscellany: Swift ('40lines'), Classic ('Marathon'), Master, Puzzle, Cheese, Combo, Custom (select goal, initial gravity, toggle gravity progress, cmdline flags: start board, seed).
- Highscores, replays, statistics, ... - can can be accessed as well as backed up with a simple savefile.
New game/
- Swift: How fast can you clear 40 lines?
- Classic: Clear 150 lines at increasing gravity.
- (unlocked after Classic) Master: Clear 150 lines at instant gravity.
- Puzzle: Clear 24 hand-crafted puzzles.
- Cheese-20: Eat through lines like Swiss cheese. Limit∈[None, Some(10), Some(11), .., Some(20), ..]
- Combo-30: Get consecutive line clears. Limit∈[None, Some(10), Some(11), .., Some(30), ..]
- Ascent*: (experimental, requires 'Ocular'- + 180° rotation)
- Custom: [Del]=reset
- Initial fall delay = 1.0s (Gravity: 1.0 Hz)
- Progressive gravity ∈ [on, off]
- Limit ∈ [None, TimeElapsed(300s), .., PointsScored(200), .., PiecesLocked(100), .., LinesCleared(40), ..]
- Game save: (Only shows up after using
Ctrl+S)Settings/Adjust-Graphics/
- Slot ∈ [Default, Focus+, Guideline, Terminal compatibility, Elektronika 60, Blank slate, Custom I/II/..]
- Color Palette (modifiable presets) ∈ [Monochrome, ANSI, Standard, Okpalette, Gruvbox, Solarized, Terafox, Fahrenheit, The Matrix, Sequoia]
- TUI style ∈ [ASCII, Unicode, Elektronika 60]
- Mino textures ∈ [ASCII, Unicode, Elektronika 60]
- Hard drop effect ∈ [None, Particles ASCII, Streak ASCII, Beam ASCII, Beam]
- Lock effect ∈ [None, Transform ASCII, Pulse Unicode, White]
- Line clear effect ∈ [None, Instant, Left to right, Inward, Outward, Flash white, Blink, Pop out, Pop out (more), Sparks ASCII, Blast]
- Mini tetromino style ∈ [ASCII, Braille]
- Small tetromino style ∈ [ASCII, Blocks, Braille]
- Normalsize previews ∈ [unlimited, 1, 2 ..]
- Frames per second ∈ [5, 10, .., 60, ..]
- Show grid ∈ [on, off]
- Show piece shadow ∈ [on, off]
- Preview spawn when stack high ∈ [on, off]
- Color board tiles ∈ [on, off]
- Show left HUD ∈ [on, off]
- Show keybinds legend ∈ [on, off]
- Show active buttons ∈ [on, off]
- Show FPS counter ∈ [on, off]
Settings/Adjust-Keybinds/
- Slot (modifiable preset) ∈ [Default, Control+, Guideline, Vim, Custom I/II/..]
- MoveLeft, MoveRight
- RotateLeft, RotateRight, Rotate180
- DropSoft, DropHard
- TeleDown, TeleLeft, TeleRight
- HoldPiece
Settings/Adjust-Gameplay/
- Slot ∈ [Default, Finesse+, Guideline, NES, Gameboy, Custom I/II/..]
- Piece rotation system ∈ [Ocular, ClassicL, ClassicR, Super]
- Piece randomization ∈ [Completely random, 7-Bag, 14-Bag, .., Recency (^2.5), Recency (^2.6), .., Balance out]
- Piece preview count ∈ [0, 1, .., 4, ..]
- Delayed auto move (DAS) ∈ [0ms, 1ms, .., 167ms, ..]
- Auto move rate (ARR) ∈ [0ms, 1ms, .., 33ms, ..]
- Soft drop speedup (SDF) ∈ [0x, 0.25x, .., 15x, ..]
- Line clear duration (LCD) ∈ [0ms, 5ms, .., 200ms, ..]
- Spawn delay (ARE) ∈ [0ms, 5ms, .., 50ms, ..]
- Allow initial rotation/hold (IRS/IHS/IMS/ITS) ∈ [on, off]
- Convert double-tap to teleport ∈ [None, Some(5ms), Some(10ms), ..]
Settings/Advanced-Settings/
- Save contents ∈ ["--Nothing", "Only settings --No scores,replays", "Only settings,scores --No replays", "Everything (settings,scores,replays)"]
- Assume enhanced-key-events available ∈ [on, off]
- Blindfold gameplay ∈ [on, off]
- Pause on focus lost ∈ [on, off]
- Renderer selected ∈ [Standard, Legacy, Prototype, Twoxel, Braille]
Why do some gameplay settings (DAS/ARR/etc.) or registering Shift as keypress not work for me?
In short: If possible use an enhanced terminal like Kitty or Alacritty (also others) for flawless game handling. Otherwise e.g. timings might depend solely on how quickly your terminal sends key-repeat events.
- Unenhanced terminals cannot implement mechanics related to holding a key. This includes: DAS, ARR, SDF; holding Soft Drop not locking the piece; holding a Teleport button; hold-type IRS/IHS.
- Unenhanced terminals cannot recognize
Ctrl/[Shift]/[Alt]modifiers as individual keys (only in combination, e.g.[Ctrl+C]).The fundamental problem lies in how terminals usually send signals.
- Since most only send "key pressed" but not "key released again", this makes it impossible to implement mechanics such as: "If
[←]is pressed, move left with a certain speed until key is released again."- Modifiers like
CtrlandShiftcan only modify 'actual' text signals and aren't sent by themselves. These issues precisely are fixed with 'enhanced keyboard events' / 'progressive enhancement' / 'kitty protocol'.Some terminals e.g. on Windows do send key-release signals, without this being auto-detected: Use the 'Override' in Advanced Settings in this case.
Is there a table of all controls / keybinds?
Please refer to the tables below.
Keys ≈ Meaning ↓/↑,j/kNavigate up/down ←/→,h/lChange value Enter,eSelect Esc,q,Back,Go back Del,dDelete/reset 1/2/3...Quickselect option (in 'Start new game') Home/EndNavigate to top/bottom (in 'Scores & Replays') Alt+?Change value but differently (in 'Start new game'⇝['Combo','Game save','Custom'], in 'Gameplay settings'⇝'Tetromino generation') Alt+Del,Alt+dDelete replay (in 'Scores and Replays') Ctrl+U(For experienced/impatient players) unlock all game modes (in 'Start new game') Ctrl+CExit application (respects save preferences)
Key Action EscPause game ←Move left →Move right ARotate left (CCW) - Rotate around (180°) DRotate right (CW) ↓Soft drop ↑Hard drop - Teleport down - Teleport left - Teleport right SpaceHold piece
Key Special Action Ctrl+DForfeit game Ctrl+RRestart game mode (Caution: discards current game) Ctrl+LLoad game save (Caution: discards current game) Ctrl+SStore game save (accessible in 'Start new game'⇝'Game save' or '(live) Game'⇝ Ctrl+L)Ctrl+EStore seed (accessible in 'Start new game'⇝'Custom') Ctrl(+Alt)+GCycle through graphics settings slots Ctrl+Alt+BToggle on/off visibility of tiles ('Blindfolded') Ctrl+Alt+LRe-load from savefile (Caution: discards current save progress!) Ctrl+CExit application (respects save preferences)
Key Action Esc,q,BackExit replay SpacePause replay ↓/↑,j/kSpeed up / slow down replay by ±0.25x Alt+↓/↑,Alt+j/kSpeed up / slow down replay by ±0.05x -Reset replay speed to =1.0x ←/→,h/lSkip forward / backward 1s in time 1/2/3...Jump to 10%/20%/30%/... Home/EndJump to beginning/end .Skip forward one player input + pause Alt+.Skip forward one game state change* + pause (*might not work properly for modded games) Enter,eStart (live) Game from current replay position
Key Special Action Ctrl+LToggle replay looping Ctrl+SStore game save (accessible in 'Start new game'⇝'Game save' or '(live) Game'⇝ Ctrl+L)Ctrl+EStore seed (accessible in 'Start new game'⇝'Custom') Ctrl+I(Experimental) Toggle Instant Interactive Input Intervention Ctrl(+Alt)+GCycle through graphics settings slots Ctrl+Alt+LRe-load from savefile (Caution: discards current save progress!) Ctrl+CExit application (respects save preferences)
Where's the config file? Will it clutter my system?
The exact location of the config file is shown in the Advanced Settings menu and is based on
dirs::config_dir()(usuallyC:/User/yourname/AppData/Roaming/.tetro-tui_v1.0_savefile.jsonor/home/yourname/.config/.tetro-tui_v1.0_savefile.json).Savefile grows mostly with number/length of replays saved. If you end up with a lot of play time but can't/don't want to spare the kB / MB, you can:
- Delete some entries (// just their replay data) in Scores and Replays using
[Del](//[Alt+Del]).- Configure which categories of data get stored in the first place on program exit (see Advanced Settings).
- As a rule of thumb, 1min of gameplay with fast inputs adds ≈ 1 kB.
Experienced players: How extensive are the stacker mechanics exactly?
In terms of advanced game mechanics the engine aims to compare with other modern tetromino stackers. It should already incorporate many features desired by familiar/experienced players, such as:
- Available player actions:
- Move left/right,
- Rotate left/right/180°
- Drop soft/hard
- Teleport down(='Sonic drop') and left/right
- Hold piece,
- Tetromino randomizers: 'Uniform', 'Stock' (generalized Bag), 'Recency' (history), 'Balance-out',
- Piece preview (arbitrary size),
- Spawn delay (ARE),
- Spawn actions (IRS/IHS/IMS/ITS; by keeping rotate/hold pressed during spawn),
- Rotation systems: 'Ocular' (engine-specific, playtested), 'Classic', 'Super',
- Delayed auto-move (DAS),
- Auto-move rate (ARR),
- Soft drop factor (SDF),
- Customizable gravity/fall and lock delay curves (exponential and/or linear; also, '20G' (fall rate of ≥1200 Hz) just becomes ≤00083s fall delay),
- Ensure move delay less than lock delay toggle (i.e. DAS/ARR are automatically shortened when lock delay is very low),
- Allow lenient lock-reset toggle (i.e. reset lock delay even if rotate/move fails),
- Lock-reset cap factor (i.e. maximum time before lock delay cannot be reset),
- Line clear duration (LCD),
- Customizable win/loss conditions based on the time, pieces, lines, points,
- Score more points for larger lineclears, spins ('allspin'), perfect clear, combo,
- Game reproducibility (PRNG/determinism).
Experienced players: Does it actually play like familiar / industry-standard stacker games?
The customizability of Tetro TUI is put to good use and a handful of setting templates are provided to emulate e.g. common gameplay/keybinds/graphics. Note that some (handling limitations may apply to your terminal).
Keybinds:
- Default controls set to WASD + Arrow keys (this also works better due to terminal limitations).
- Dedicated binds possible for Rotate 180°, Teleport Down ('Sonic Drop'), even Teleport Left/Right.
Gameplay:
- Default use of the flexible/intuitive/symmetrical Ocular Rotation System (instead of the quirky/sometimes asymmetrical industry default).
- Default Recency (History) Randomizer (instead of 'overdeterministic' 7-Bag).
- Points (score) bonus system is currently kept custom and simple.
- '1pt for simple line clear, with increasing bonus for larger lineclears, combos, spins and perfect clears.'
- Note: 'Allspin' (instead of preoccupation with 'T-spins'), currently no 'minis'.
- Note: Combos (but no additional points for 'back to back' other than existing incentives for special maneuvers).
- Exact formula:
point_bonus = if is_perfect_clear{ 4 }else{ 1 } * if is_spin{ 2 }else{ 1 } * (lineclears * 2 - 1) + (combo - 1)- Different lock reset limit: 'max time = 10⋅current lock delay' (instead of 'max 15 moves with current lock delay').
- Speed/gravity/fall curve technically a customizable mix of exponential decay + linear decrease.
Experienced players: What is this 'Ocular Rotation System'?
The Ocular rotation system affords:
- Symmetric/mirrored situations should lead to symmetric/mirrored outcomes (e.g. no distinct but visually identical states).
- Rotation generally based on 'proximity where it looks like the piece should (be able to) go'.
- Pieces should prefer downwards placement, not 'teleport up' in general.
See this visual/'heatmap' comparison of industry default vs. Ocular rotation:
Terminal enthusiasts: How was this terminal game programmed (and why doesn't it use Ratatui)?
Ever since its inception as a proof-of-concept this terminal user interface (TUI) has directly used Crossterm for all I/O. The most complicated terminal interaction we currently implement is custom diff'ing so we render the minimum number of visual game changes (minimize flicker). Currently there appears no need to change this situation, though Ratatui will be reconsidered if necessary (e.g. language/localization...)
What is the background behind this project?
Out of curiosity I looked into the depths of this common type of Tetromino game: Basic versions are simple to code up, but it gets surprisingly nontrivial when it comes to comprehensively supporting of modern/advanced features and slews of QOL mechanics while dealing with terminal limitations!
I've given it my best effort to implement a most featureful and customizable version that not only remains totally faithful to the basic idea of the game, but also runs and looks nice within the confines of a mere terminal - Enjoy! ☻ L. Werner
License
Licensed under MIT.
Provenance
100% human-sourced spaghetti code
Color palettes used: Gruvbox, Solarized, Terafox, Fahrenheit, matrix, Sequoia Monochrome.
Acknowledgements
A big thank you to the AUR package maintainers:
Special Thanks:
- GrBtAce, KonSola5 and bennxt – for early support
- madkiwi – for advice regarding 4wide-6residual combo layouts
- Dunspixel – for inspiration regarding 'O'-spins
- Martín G – for inspiration regarding new line clear effect from his own PICO-8 game
- thehuglet – for inspiration regarding the potential of the terminal
- Akousoukos – for making Apotris
- and RayZN and ˗ˋˏthe One and Onlyˎˊ˗ – for advice regarding the Tetro logo







