!["Tetro TUI logo"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro_logo_glow.png?raw=true) # Tetro TUI - Terminal Game [![Crates.io](https://img.shields.io/crates/v/tetro-tui.svg)](https://crates.io/crates/tetro-tui) [![License](https://img.shields.io/crates/l/tetro-tui)](https://github.com/Strophox/tetro-tui#license) Tetro TUI is a terminal-based but modern tetromino-stacking game that is customizable and cross-platform. !["tetro-tui demo GIF"](https://github.com/Strophox/tetro-tui/blob/15d6f8a13d146d2655f80559e0aee0430527f1c9/demo_assets/tetro-tui-v3.5.0_demo.gif?raw=true) >
> > 6 more demo images available; > > > !["tetro-tui coolretroterm-monochrome-classic-elektronika"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro-tui-v3.0.0_coolretroterm-monochrome-classic-elektronika.png?raw=true) > > !["tetro-tui alacritty-terafox-combo-advc"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro-tui-v3.0.0_alacritty-terafox-combo-advc.png?raw=true) > > !["tetro-tui gnome-solarized-cheese-monochromeboardgrid"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro-tui-v3.0.0_gnome-solarized-cheese-monochromeboardgrid.png?raw=true) > > !["tetro-tui gnome-standard-replay-harddrop"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro-tui-v3.0.0_gnome-standard-replay-harddrop.png?raw=true) > > !["tetro-tui kitty-okpalette-puzzle-ascii"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro-tui-v3.0.0_kitty-okpalette-puzzle-ascii.png?raw=true) > > !["tetro-tui wezterm-gruvbox-swift-default"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/tetro-tui-v3.0.0_wezterm-gruvbox-swift-default.png?raw=true) > >
## Ways to Run ### Download & Run 1. [Download a release]() for your platform (Linux/MacOS/Windows/...) if available. 2. Navigate to the application binary (`tetro-tui`/`tetro-tui.exe`/...) and run it in a terminal ### Quick Install #### Cargo ([crates.io]()): ```bash cargo install tetro-tui # tetro-tui ``` #### Arch Linux ([aur.archlinux.org]()): ```bash yay -S tetro-tui # Or paru, etc. # tetro-tui ``` ### Compile from source Tetro TUI is written in [Rust 1.95.0]() and can be compiled as usual: ```bash git clone https://github.com/Strophox/tetro-tui cd tetro-tui cargo run ``` ## 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 horizontal lines are filled they automatically clear away and everything 'stacked' above moves 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 configuration / features? > We provide a solid amount of customization options / features for casual and (potentially) experienced players alike: > - **Graphics:** Unicode/ASCII/Elektronika styles, old-terminal-compatible or very modern designs, 10 color palettes, hard drop/piece lock/line clear effects and much more. > - **Game keybinds:** to your heart's desire. > - **Gameplay/handling:** Various rotation systems, piece randomizers, adjustable preview, timings (DAS¹, ARR¹, SDF¹, LCD, ARE), IRS/IHS/.. ([¹caveat](#why-do-some-gameplay-preferences-dasarrsdf-or-some-keybinds-ctrlshiftalt-not-work-for-me)). > - **Game mode miscellany:** Regular ('Marathon'), Swift ('40-Lines'), Classic & Master (unlocked after Regular), Puzzle, Cheese, Combo, Custom (*select:* win condition, initial gravity, *toggle:* gravity progress, no top out, *cmdline flags:* start board, seed). > - **Highscores, replays, statistics, ...** - can be viewed as well as backed up with a simple **savefile**. > > Visuals can be customized together with your underlying terminal settings. > E.g. one can set a bigger font to scale the game, or use cool-retro-term for a nostalgic look etc. > >
> > See also: Big overview of actual Tetro TUI v3.5 menus: > > > **- Title screen -** > - New Game > - Settings > - Scores and Replays > - All-Time Stats > - About > - Quit > *[←↓↑→/Enter/Esc/Del] or Vim, Press [?] to view keybinds anytime* > > **+ Start New Game +** > - Regular: Clear 160 lines as gravity increases. > - Swift: How quickly can you clear 40 lines? > - *(unlocked after Regular)* Classic (lvl 0+)(*): 'NES' Gameplay/Graphics settings recommended. > - *(unlocked after Regular)* Master: Clear 320 lines at instant gravity. > - Puzzle: Clear 24 hand-crafted puzzles (feat. the Ocular rotation system) > - Cheese-40: Efficiently eat through some lines. Limit∈[None, Some(10), Some(11), .., Some(40), ..] > - Survival: Lines regenerate as you place more pieces. > - Combo-30: Get consecutive line clears. Limit∈[None, Some(10), Some(11), .., Some(30), ..] > - *(unlocked with Ctrl+U)* Placement: Practice placing pieces. > - *(unlocked with Ctrl+U)* Ascent: Experimental gamemode (requires 180° rot.) > - Custom: [Del]=reset > * Initial fall delay = 1.000000000s (Gravity: 1.00 Hz) > * Progressive gravity ∈ [on, off] > * Limit ∈ [None, TimeElapsed(300s), .., PointsScored(200), .., PiecesLocked(100), .., LinesCleared(40), ..] > - *(available after using `Ctrl+S`)* Game save > > **# Graphics Settings #** > * Slot ∈ [Default, Guideline, Terminal compatibility, Focus+, Minimal, I⠐⢷⠗ Braille, Elektronika 60, NES; Custom I/II/..] > * Tile colors ∈ [Terminal default, Just white, ANSI, Tetro Pastel, Guideline, Gruvbox, Solarized, Terafox, Fahrenheit, Matrix, Sequoia, Just amber, NES levels] > * UI colors ∈ [Terminal default, Just black/white, Tetro Dark, Gruvbox Dark, Solarized Light, Matrix, Sequoia, Just amber, NES, OneHalfDark] > * UI style ∈ [ASCII, Frame UTF8, Rounded frame UTF8, No frame UTF8, No hold/next-frame, Braille, Elektronika 60] > * Hard drop effect ∈ [None, Particle trail ASCII, Particle trail 2 ASCII, Particle beam ASCII, Colored beam UTF8, White beam UTF8, Braille helix] > * Lock effect ∈ [None, Flash white, Transforming ASCII, Pulsing block UTF8, Spiraling Braille] > * Line clear effect ∈ [None, Disappear halfway, Disappear instantly, Blink, Flash white, Clear left-to-right, Clear outward, White clear inward, Burn outward, Pop, Pop (more), Confetti (gratuitous), Stardust, Blast, Sparks, Sparks Braille, Sparks ASCII] > * Tile/Tetromino symbols ∈ [ASCII, Blocks UTF8, Braille, NES simulacra, Elektronika 60] > * Small tetromino symbols ∈ [Dots ASCII, Blocks UTF8, Braille] > * Mini tetromino symbols ∈ [Letters, Braille] > * Normalsized tetromino previews ∈ [unlimited, 1, 2 ..] > * Frames rendered per second ∈ [5, 10, .., 60, ..] > * Grid ∈ [on, off] > * Piece shadow ∈ [on, off] > * Upcoming spawn preview (if stack high) ∈ [on, off] > * Uniform locked tiles ∈ [on, off] > * Main HUD ∈ [on, off] > * Include basic keybinds HUD ∈ [on, off] > * Show active/held buttons ∈ [on, off] > * Lock delay visualizer ∈ [on, off] > * FPS counter ∈ [on, off] > > **@ Game Keybinds @** > * Slot (modifiable preset) ∈ [Default, Guideline, Control+, Terminal finesse, Vim; Custom I/II/..] > * MoveLeft, MoveRight; > * RotateLeft, RotateRight, Rotate180; > * DropSoft, DropHard; > * TeleDown, TeleLeft, TeleRight; > * HoldPiece. > > **Settings/Adjust-Gameplay/** > * Slot ∈ [Default, Guideline, Finesse+, Elektronika 60, Gameboy, NES; Custom I/II/..] > * Piece rotation ∈ [Ocular, ClassicL, ClassicR, Super] > * Piece randomization ∈ [Uniformly random, Classic (Reroll 1x), Rerollx 2x, .., 7-Bag, 14-Bag, .., Balance out, Recency (^2.5), Recency (^2.6), ..] > * Piece preview count ∈ [0, 1, .., 4, ..] > * Delayed auto move (DAS) ∈ [0ms, 1ms, .., 167ms, ..] > * Auto repeat rate (ARR) ∈ [0ms, 1ms, .., 33ms, ..] > * Delayed soft drop ∈ [None, Some(5ms), Some(10ms), .., Some(100ms), ..] > * Soft drop rate (SDF) ∈ [raise gravity to 30 Hz, ..; 0x gravity, 0.25x gravity, .., 15x, .., inf x gravity] > * Line clear duration (LCD) ∈ [0ms, 5ms, .., 200ms, ..] > * Spawn delay (ARE) ∈ [0ms, 5ms, .., 50ms, ..] > * Allow spawn manipulation (hold-IRS/IHS/IMS/ITS) ∈ [on, off] > * Convert double-tap to teleport ∈ [None, Some(5ms), Some(10ms), ..] > > **§ Advanced Settings §** > * Save ∈ ["--Nothing", "Only settings,stats --No scores,replays", "Only settings,stats,scores --No replays", "Everything (settings,stats,scores,replays)"] > * Renderer used ∈ [Main, Halfblock, Braille] > * Pause on focus lost ∈ [on, off] > * 'Blindfold' game ∈ [on, off] > * Assume enhanced-key-events available ∈ [on, off] > >
### Why do some gameplay preferences (DAS/ARR/SDF...) or some keybinds (Ctrl/Shift/Alt/...) not work for me? > It is likely that your current terminal provides **too little input information** to enable custom timings¹ or those special keys. > (¹Instead, DAS/ARR/SDF will be determined by how quickly your *terminal* sends key-repeat events.) > If possible use an **enhanced terminal** like Kitty or Alacritty (also others) for flawless game handling. > >
> > Explanation: > > > The fundamental problem lies in how terminals usually send input signals. > - Due to historical reasons, most will 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*." > * Affected mechanics: Generally unable to actually 'hold' any buttons; DAS & ARR & SDF determined by terminal (& holding Soft Drop may 'accidentally' lock the piece), unable to hold Teleport, unable to hold for IRS/IHS/IMS/ITS. > * Note that some terminals e.g. on Windows *do* send key-release signals, without this being auto-detected: > Use the override in *Advanced Settings* for such cases. > - Also due to history, modifier keys can only modify 'actual' text signals and are never sent by themselves. > * Affected mechanics: Cannot register modifier `Ctrl`/`Alt`/`Shift`/`Win`/`⌘`/... as individual key presses. > > Precisely these issues are fixed with ['enhanced keyboard events' / 'kitty keyboard protocol'](). > >
### Where's the config file? Will it clutter my system? >
> > The application will not store anything by default and 'Keep save file' needs to be opted in; > > > The exact location of the config file is shown in the *Advanced Settings* menu and is based on `dirs::config_dir()`: > - Usually `/home/yourname/.config/.tetro-tui_v1.0_savefile.json` > - or `C:/User/yourname/AppData/Roaming/.tetro-tui_v1.0_savefile.json` > > Savefile grows primarly due to number/length of saved replays. > As a rule of thumb, 1min of gameplay with fast inputs adds ≲ 1 kB. > 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*). > >
### *Experienced players:* How does it compare to (or deviate from) common stacker games? > At the time of writing we implement all the most common mechanics found in the wild (and then some). > Groups of (e.g. gameplay) settings are bundled in a 'slot'(= settings template/profile) which allows us to provide common presets as well as our suggested defaults. > >
> > See list of notable differences: > > > **Keybinds:** > - Default controls suggested to be **WASD + Arrow keys** (reasoning: We prefer to assign movement and rotation to separate hands instead of mixing; do not use Shift key due to common [terminal limitations](#why-do-some-gameplay-preferences-dasarrsdf-or-some-keybinds-ctrlshiftalt-not-work-for-me)). > - Dedicated buttons supplied for **Rotate 180°**, **Teleport Down** ('Sonic Drop') and Teleport Left/Right. > > **Gameplay:** > - Default rotation system suggested to be the [**Ocular Rotation** System](#experienced-players-what-is-this-ocular-rotation-system) (reasoning: Ocular is designed to be symmetrical, intuitive and flexible (in different ways) compared to the quirky / sometimes asymmetrical 'Super' Rot.Sys.). > - Default piece randomizer suggested to be a **Recency Randomizer** (reasoning: 'Recency' is biased toward 'fairly' choosing less recent pieces but still technically allowing arbitrary piece sequences, compared to the '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' without 'minis' (reasoning: we are not preoccupied with just 'T-spins'). > - *Note:* Combos, without 'back-to-back' (reasoning: Back-to-back incentivizes playing special maneuvers, but those already yield disproportionate score bonus by themselves). > - Exact formula: `point_bonus = lineclears*lineclears * if is_spin{ 4 }else{ 1 } * if is_perfect{ 4 }else{ 1 } + (combo - 1)` > - **Time-based lock reset limit** (reasoning: Providing a 'hard time limit before lock'(= `N`⋅current lock delay) seems more flexible/natural than 'hard move limit before lock'(=`N` 'moves'). > - Default speed/gravity/fall curve is slightly less aggressive but very close to standard (reason: We use a simpler formula). > > **Graphics:** > - Default palette is more pastel (reasoning: Uniform perceptual brightness, 'looks pretty'). > >
> >
> > See list of core game engine mechanics: > > > - 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 manipulation** (IRS/IHS/IMS/ITS; by keeping rotate/hold/move/teleport pressed during spawn), > - **Rotation systems**: 'Ocular' (engine-specific, playtested), 'Classic', 'Super', > - **Delayed auto-move** (DAS), > - **Auto-move rate** (ARR), > - **Soft drop rate** (SDF), > - **Delayed soft drop** ('DAS but for Soft drop'), > - **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:* What is the 'Ocular Rotation System'? >
> > An extensive attempt at better tetromino rotation with regards to symmetry and visual intuition; > > > 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 the 'industry default' rotation system vs. Ocular rotation: > > !["super rotation system heatmap"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/rotation-system-heatmap_srs.png?raw=true) > > !["ocular rotation system heatmap"](https://github.com/Strophox/tetro-tui/blob/b66590cb461d34c95e988ef41b6d8b7d7783f37b/demo_assets/rotation-system-heatmap_ocular.png?raw=true) > >
### *Programmers / Terminal enthusiasts:* Can you provide some insight into the programming of this terminal game? >
> > This project handles a handful of aspects to try and provide excellent user experience for a classic game. It also aims to maintain a decently high quality in code. The scope of this project consists of: > > > - A **fully-featured [Tetromino game engine/backend]()** featuring: > * Several dozens of **configurable, advanced and important options**. > * Provided pre-implementations of extremely common **standard mechanics**. > * Decoupled core game loop ('interpreter') with ergonomic API (hopefully). > * Basic but functional **modding functionality** with ergonomic API (hopefully). > - **Different and interesting game modes**, including special game modes that rely on engine modding. > - **Extensive TUI menus** to allow modifying all relevant configuration options without being forced to edit the save file manually: * **Graphics** options, **Configurable keybinds**, **Gameplay settings**. > * Providing many **curated configuration templates** for everything, inspired by existing standards and games. > * *Sidenote:* Ever since its inception as a proof-of-concept the terminal user interface (TUI) has directly and only relied on [Crossterm](). Currently there appears no need to change this situation, though a full TUI library like [Ratatui]() might be reconsidered e.g. to handle UI translation (displaying other languages) etc. > - A competent **input-update-render game loop**. > - Implementing **game replays**. > - **Savefile** storage: > * In particular **replay data serialization and compression**. > - **Scoreboard** and **statistics**. > - Game **graphics renderer** that handles all of the **effects** and dozens of graphics settings, efficiently. > * Custom **buffer diff'ing** so we can guarantee we only send the minimum number of required changes to the terminal (this minimizes flicker), see . > - Miscellaneous: > * Commandline arguments. > * Terminal limitations, all the time... > * Doing all of the above as simply, ergonomically and as correctly as possible while providing feedback to the user when something doesn't work as expected... > * Rust code quality. > >
### What is the motivation behind this project? >
> > Tetro TUI started as a passion project from someone who loves programming, minimalistic games and ASCII art; > > > Out of curiosity I snuck a peek to see how deep the mechanics of such a universal game can go: > Basic versions are simple to code up, but it gets surprisingly complex when it comes to supporting all the modern/advanced features (especially while dealing with terminal limitations)! > > To the best of my abilities I have implemented a most featureful & customizable version that still remains faithful to the essential idea and also looks/runs nicely within a 'mere' terminal - Enjoy! > ☺ [L.C.Werner]() > >
## License Licensed under MIT. ## Provenance 100% human-sourced spaghetti code Color palettes featured: [Gruvbox](), [Solarized](), [Terafox](), [Fahrenheit](), [matrix](), [Sequoia Monochrome](), [OneHalfDark](). ## Acknowledgements A big thank you to the [AUR package](#arch-linux-aurarchlinuxorg) maintainers! - [wcasanova](), [druxorey]() and Dominiquini Thank you to many sources of inspiration: - Dunspixel – regarding ['O'-spins]() - Martín G / mg1399 – regarding particle-based line clear effects from his own PICO-8 game - thehuglet – regarding the [potential of terminal graphics]() - Akousoukos – regarding the [customizability of Apotris]() - DoktorOcelot – regarding the addition of [Survival Zen mode in Tetr.js Enhanced]() Special Thanks - GrBtAce, KonSola5 and bennxt – help during early dev/research - madkiwi – help with 4-wide-6-residual combo layouts - mathmaster13 and Kitaru – help with retro mechanics - RayZN and ˗ˋˏthe One and Onlyˎˊ˗ – help with *Tetro* logo choice - and Alexey Leonidovich Pajitnov – for discovering this universal genre of game