The Ultimate Block Challenge โข A Modern Two-Player Tetris Variant
A sophisticated object-oriented implementation featuring C++20 modules, smart pointers, and design patterns
Features โข Installation โข Gameplay โข Commands โข Architecture โข Credits
- Overview
- Features
- Installation
- Getting Started
- Gameplay
- Commands
- Architecture
- Design Patterns
- Project Structure
- Development
- Credits
Biquadris is an advanced two-player Tetris variant developed as a CS246 course project. Built with modern C++ practices, it demonstrates sophisticated software engineering principles including design patterns, modular architecture, and clean code practices.
Unlike traditional Tetris, Biquadris introduces competitive multiplayer gameplay where clearing multiple rows triggers special effects that can sabotage your opponent. With five difficulty levels, dynamic block generation, and both text and graphical interfaces, Biquadris offers depth and replayability.
- ๐๏ธ Modern C++20 โ Utilizes C++20 modules for improved encapsulation and compilation
- ๐จ Dual Display Modes โ Beautiful X11 graphics or classic terminal text display
- โ๏ธ Competitive Multiplayer โ Special attacks and effects between players
- ๐ฒ Five Difficulty Levels โ From scripted sequences to challenging random generation
- ๐งฉ Extensible Design โ Clean architecture makes adding features straightforward
- ๐ฎ Rich Command System โ Intuitive command prefix matching and multipliers
- Two-Player Competitive Mode โ Race against your opponent on side-by-side boards
- Seven Classic Tetrominos โ I, J, L, O, S, Z, and T blocks with full rotation support
- Smooth Controls โ Move, rotate, and drop blocks with responsive commands
- Command Multipliers โ Execute commands multiple times (e.g.,
3left,5down) - Prefix Matching โ Type partial commands (e.g.,
lefโleft)
| Level | Description | Special Features |
|---|---|---|
| Level 0 | Scripted sequence from file | Perfect for testing and learning |
| Level 1 | Random with S/Z bias | S and Z blocks appear less frequently |
| Level 2 | Uniform random distribution | All blocks equally likely |
| Level 3 | Heavy blocks + S/Z boost | Blocks drop 1 extra row after moves, S/Z more common |
| Level 4 | Extreme challenge | Everything from Level 3 + center block drops every 5 turns |
Trigger special attacks by clearing 2+ rows at once!
- ๐ฒ Blind Effect โ Obscures opponent's board with
?characters (rows 3-12, columns 3-9) - โ Heavy Effect โ Makes opponent's blocks drop 2 extra rows after every move
- ๐ฏ Force Block โ Choose which block type your opponent receives next
Clean ASCII rendering perfect for terminals:
Level: 1 Level: 1
Score: 450 Score: 320
Hi Score: 1200 Hi Score: 1200
----------- -----------
T
TTT
J S
JJJ SS
IIII S Z
----------- -----------
Next: Next:
OO I
OO I
I
I
Beautiful arcade-style rendering with:
- ๐จ Colorful tetromino blocks with 3D shading
- ๐ Live score and statistics
- ๐๏ธ Next block preview panels
- ๐น Visual control indicators
- ๐น๏ธ Retro arcade machine aesthetic
- C++ Compiler with C++20 module support (GCC 11+ or Clang 15+)
- X11 Development Libraries (for graphical mode)
- macOS:
brew install xquartz - Ubuntu/Debian:
sudo apt-get install libx11-dev - Fedora:
sudo dnf install libX11-devel
- macOS:
# Clone the repository
git clone <your-repo-url>
cd Tetris
# Build the project
make
# Clean build (if needed)
make clean
makeThe project uses a custom Makefile that:
- Precompiles standard library headers for faster builds
- Compiles C++20 modules with
-fmodules-ts - Links X11 libraries for graphical display
- Generates the
biquadrisexecutable
# Launch with default settings (graphical mode)
./biquadris
# Text-only mode (no graphics)
./biquadris -text
# Set random seed for reproducibility
./biquadris -seed 12345
# Start at a specific level (0-4)
./biquadris -startlevel 3
# Use custom sequence files for Level 0
./biquadris -scriptfile1 sequence1.txt -scriptfile2 sequence2.txt| Option | Description | Example |
|---|---|---|
-text |
Text-only mode (no graphics) | ./biquadris -text |
-seed N |
Set random seed to N | ./biquadris -seed 42 |
-scriptfile1 FILE |
Player 1's Level 0 sequence file | ./biquadris -scriptfile1 custom.txt |
-scriptfile2 FILE |
Player 2's Level 0 sequence file | ./biquadris -scriptfile2 custom.txt |
-startlevel N |
Start at level N (0-4) | ./biquadris -startlevel 2 |
Reads block types from a file for deterministic gameplay. Perfect for:
- ๐งช Testing specific scenarios
- ๐ Learning block mechanics
- ๐ฏ Practicing specific moves
Progressive difficulty with different probability distributions:
- Level 1 reduces S/Z frequency (easier)
- Level 2 provides uniform distribution
- Heavy blocks that auto-drop after lateral moves
- Level 4 adds center block drops every 5 turns without row clears
- Requires strategic planning and quick reflexes
When you clear 2 or more rows simultaneously, you can choose a special effect:
Special Action! Choose effect:
1. blind - Obscure opponent's view
2. heavy - Make opponent's blocks heavier
3. force <T> - Force opponent to receive block type T
Effect Details:
- Blind: Lasts until opponent drops a block, covering center region with
? - Heavy: Blocks drop 2 extra rows after left/right/rotate (stackable with level heavy)
- Force: Immediately replaces opponent's current block with your choice (I/J/L/O/S/Z/T)
Points are awarded when blocks are placed:
Score = (level + number of rows cleared)ยฒ + (level + number of rows cleared)
Examples:
- Drop at Level 2, clear 1 row:
(2+1)ยฒ + (2+1) = 12 points - Drop at Level 3, clear 3 rows:
(3+3)ยฒ + (3+3) = 42 points - Drop at Level 0, clear 4 rows:
(0+4)ยฒ + (0+4) = 20 points
Bonus: Clearing multiple rows at higher levels yields exponentially more points!
- Opponent's board becomes full (a block can't spawn)
- High score persists across games in the current session
- Restart anytime to begin a new match
| Command | Shortcut | Multiplier | Description |
|---|---|---|---|
left |
lef |
โ | Move block one cell left |
right |
ri |
โ | Move block one cell right |
down |
d |
โ | Move block one cell down (soft drop) |
drop |
dr |
โ | Hard drop block to bottom |
Examples:
left # Move left once
3left # Move left three times
10down # Soft drop 10 cells
drop # Hard drop| Command | Shortcut | Multiplier | Description |
|---|---|---|---|
clockwise |
cw |
โ | Rotate 90ยฐ clockwise |
counterclockwise |
ccw |
โ | Rotate 90ยฐ counter-clockwise |
Examples:
cw # Rotate clockwise once
2ccw # Rotate counter-clockwise twice| Command | Shortcut | Description |
|---|---|---|
levelup |
levelu |
Increase difficulty by 1 level (max: 4) |
leveldown |
leveld |
Decrease difficulty by 1 level (min: 0) |
| Command | Description |
|---|---|
random |
Switch to random block generation (Levels 1-4) |
norandom FILE |
Read block sequence from FILE instead of random |
sequence FILE |
Execute commands from FILE |
restart |
Start a new game |
Replace the current block with a specific type (useful for testing):
I # Replace with I block (straight line)
J # Replace with J block
L # Replace with L block
O # Replace with O block (square)
S # Replace with S block
Z # Replace with Z block
T # Replace with T blockWhen prompted after clearing 2+ rows:
blind # Apply blind effect to opponent
heavy # Apply heavy effect to opponent
force I # Force opponent to receive an I block
force T # Force opponent to receive a T block| Command | Description |
|---|---|
help |
Display command reference |
Biquadris is built with modern software engineering principles, emphasizing separation of concerns, extensibility, and maintainability.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GAME LAYER โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Game: Orchestrates gameplay, manages turns, handles โ โ
โ โ player switching and win conditions โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ Board (P1) โ โ ScoreKeeper โ โ Displays โ
โ Board (P2) โ โ Level (P1) โ โ Commands โ
โ โ โ Level (P2) โ โ โ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ
โโโโโ Grid (Cell[][])
โโโโโ Current & Next Blocks
โโโโโ Active Effects
โโโโโ Observers (Display updates)
Each component is organized into interface (.cc) and implementation (-impl.cc) files:
- โ Enforces encapsulation
- โ Reduces compilation dependencies
- โ Represents modern C++ best practices
std::unique_ptrfor owned resources (blocks, levels, displays)- Eliminates memory leaks and dangling pointers
- Clear ownership semantics
Boardnotifies displays of state changes- Adding new display types requires no changes to game logic
- Text and graphical displays coexist seamlessly
Biquadris employs classic design patterns for flexibility and maintainability:
Used for: Display updates
ISubject (Board) โโnotifiesโโ> IObserver (TextDisplay, GraphicsDisplay)
Implementation: observer.cc, textdisplay.cc, graphicsdisplay.cc, board.cc
Used for: Difficulty levels and block generation
Level (abstract)
โโ Level0: Sequential from file
โโ Level1: Random with S/Z bias
โโ Level2: Uniform random
โโ Level3: Heavy blocks, S/Z boost
โโ Level4: + Center block drops
Implementation: level.cc, level-impl.cc
Used for: User input handling
CommandInterpreter
โโ Registry<string, Command>
โโ LeftCommand
โโ RightCommand
โโ DropCommand
โโ RotateClockwiseCommand
โโ ...
Implementation: command.cc, command-impl.cc
Used for: Tetromino blocks
Block (abstract)
โโ IBlock: โโโโ
โโ JBlock: โโ
โโ LBlock: โโ
โโ OBlock: โโ
โโ SBlock: โโโ
โโ ZBlock: โโโ
โโ TBlock: โโโ
โโ SingleBlock: โ (Level 4 center drop)
Implementation: block.cc, blocks.cc
Tetris/
โ
โโโ ๐ README.md โ You are here!
โโโ ๐ DESIGN_DOCUMENT.md โ Detailed architecture documentation
โโโ ๐ Makefile โ Build configuration
โโโ ๐ผ๏ธ BiquadrisLogo.png โ Project logo
โ
โโโ ๐ฎ Core Game Logic
โ โโโ main.cc โ Entry point and command-line parsing
โ โโโ game.cc / game-impl.cc โ Game orchestration and turn management
โ โโโ board.cc / board-impl.cc โ Board state and game rules
โ โโโ constants.cc โ Game constants and configuration
โ
โโโ ๐งฉ Block System
โ โโโ block.cc / block-impl.cc โ Abstract block interface
โ โโโ blocks.cc / blocks-impl.cc โ Concrete block implementations (I/J/L/O/S/Z/T)
โ
โโโ ๐ฒ Level System
โ โโโ level.cc / level-impl.cc โ Strategy pattern for difficulty levels
โ
โโโ โก Effects System
โ โโโ effect.cc โ Blind, Heavy, and Force effects
โ
โโโ ๐จ Display System
โ โโโ observer.cc โ Observer pattern interfaces
โ โโโ textdisplay.cc / textdisplay-impl.cc โ ASCII rendering
โ โโโ graphicsdisplay.cc / graphicsdisplay-impl.cc โ X11 graphics
โ โโโ window.cc / window-impl.cc โ X11 window wrapper
โ
โโโ โจ๏ธ Command System
โ โโโ command.cc / command-impl.cc โ Command pattern implementation
โ
โโโ ๐ Supporting Components
โ โโโ cell.cc โ Individual grid cell
โ โโโ scorekeeper.cc โ Score tracking
โ
โโโ ๐ Game Data Files
โ โโโ biquadris_sequence1.txt โ Default Player 1 Level 0 sequence
โ โโโ biquadris_sequence2.txt โ Default Player 2 Level 0 sequence
โ โโโ sequence1.txt โ Additional test sequence
โ โโโ sequence2.txt โ Additional test sequence
โ โโโ tests/
โ โโโ effect_test.txt โ Effect testing sequence
โ
โโโ ๐จ Build Output
โโโ biquadris โ Compiled executable (after make)
Using C++20 modules, code is organized as:
<component>.cc โ Module interface (declarations, exports)
<component>-impl.cc โ Module implementation (definitions)
The modular architecture makes extensions straightforward:
- Create class inheriting from
Blockinblocks-impl.cc - Implement
rotateClockwise()androtateCounterClockwise() - Add to
Level::createBlockFromType() - Update relevant level generation logic
No changes needed: Board, Cell, Display, or Command classes
- Create
Level5class inheriting fromLevel - Implement
generateBlock()andisHeavy() - Add instantiation to
Game::createLevels() - Update
MAX_LEVELinconstants.cc
No changes needed: Board, Display, or Command logic
- Create class inheriting from
Effect - Implement
isExpired()andupdate() - Add handling in
Board::addEffect()andBoard::updateEffects() - Add to special action prompt in
Game::drop()
No changes needed: Other game components
- Create class inheriting from
Command - Implement
execute()and optionallycanMultiply() - Register in
CommandInterpreter::registerCommands()
No changes needed: Parsing logic or other commands
The project includes sequence files for deterministic testing:
# Use custom test sequences
./biquadris -scriptfile1 tests/effect_test.txt -startlevel 0
# Execute command sequences
# In game: sequence tests/effect_test.txtTest Sequence Format:
I
drop
J
left
left
drop
...
Precompiled Headers: The Makefile precompiles standard library headers for faster builds:
HEADERS = chrono vector utility map memory algorithm iostream cstdlib fstream random cctype stringModule Cache:
GCC stores module cache in gcm.cache/. Clean it if you encounter module issues:
make cleanX11 Linking: The project links against X11 for graphical display:
LDFLAGS = -L/opt/X11/lib -lX11On macOS, ensure XQuartz is installed and in the expected path.
Biquadris was developed as the final project for CS246: Object-Oriented Software Development (Fall 2025) at the University of Waterloo.
- Matthew Mo (mzmo)
- Marcus Ng (mcng)
- James Cai (j239cai)
- ๐ C++20 Modules โ cppreference.com
This project was developed for academic purposes as part of CS246 coursework.
