Piecewise is a Domain-Specific Language (DSL) for defining and playing deterministic, turn-based board games on rectangular grids.
A game author describes the board, players, pieces, actions, initial setup, and
end conditions in a readable .game file. Piecewise parses and validates that
definition, creates an immutable game state, and runs it through a shared
engine. The same definition can then be played from the command line or through
the Tkinter graphical interface.
In its simplest form:
Write the rules of a supported board game in a
.gamefile and Piecewise turns them into a playable application.
The project was developed for the Advanced Software Engineering course (2025/2026) and focuses on language design, parsing, semantic validation, immutable state, modular architecture, and automated testing.
| Game | Main mechanics | CLI | GUI |
|---|---|---|---|
| Tic-Tac-Toe | Empty-cell placement, alignment, full-board draw | Yes | Yes |
| Connect Four | Column input, downward gravity, four-piece alignment | Yes | Yes |
| Checkers | Setup, movement, mandatory captures, capture chains, promotion | Yes | Yes |
The bundled Checkers definition implements the simplified rule set supported by the current DSL. It is not intended to reproduce every official regional variant.
| Checkers move selection | Connect Four victory |
|
|
- external DSL parsed with Lark;
- immutable, typed AST and runtime snapshots;
- cumulative semantic diagnostics with stable codes and model paths;
- direct placement, gravity placement, relocation, capture, chained capture, and promotion;
- legal-move generation and mandatory-capture enforcement;
- alignment, board-full, no-pieces-left, and no-moves-left conditions;
- interactive CLI with aligned boards, compact symbols, contextual help, and optional ANSI colours;
- responsive Tkinter interface with game selection, move highlighting, restart, and Checkers source selection;
- one shared engine used by both interfaces;
- 261 collected pytest cases covering the complete processing pipeline.
.game source
-> Lark parser
-> Parse tree
-> AST transformer
-> GameDefinition
-> SemanticValidator
-> GameInitializer
-> GameSession
-> LegalMoveGenerator
-> MoveExecutor
-> ConditionEvaluator
-> CLI or Tkinter GUI
Parsing, transformation, validation, execution, and presentation have separate responsibilities. The engine consumes the typed model and does not need to know how the original DSL text was written.
| Technology | Purpose |
|---|---|
| Python 3.10+ | Application and domain model |
| Lark | LALR grammar parsing and tree transformation |
| dataclasses and enums | Typed, immutable AST and runtime state |
| Tkinter | Desktop graphical interface |
| ANSI terminal sequences | Optional CLI colours |
| pytest | Unit, integration, negative, and end-to-end tests |
- Python 3.10 or newer;
- Git, when cloning the repository;
- Tkinter, normally included with standard Python installations.
git clone https://github.com/Reiver56/Piecewise.git
cd Piecewise
python -m venv .venvActivate the virtual environment.
Windows PowerShell:
.venv\Scripts\Activate.ps1macOS or Linux:
source .venv/bin/activateInstall the dependencies:
python -m pip install -r requirements.txtStart the game selector:
python -m guiChoose Tic-Tac-Toe, Connect Four, or Checkers. The interface displays the current player, legal destinations, selected Checkers pieces, final results, and restart controls.
Read the graphical-interface guide for controller behaviour, symbols, theme, and tests.
Tic-Tac-Toe is the default:
python -m cliSelect a definition explicitly:
python -m cli games/tictactoe.game
python -m cli games/connectfour.game
python -m cli games/checkers.gameThe CLI enables colours automatically when output is connected to a compatible terminal. Disable them when necessary:
python -m cli games/checkers.game --no-color| Action type | Input |
|---|---|
| Direct placement | row column |
| Gravity placement | column |
| Relocation or capture | source_row source_column destination_row destination_column |
| Exit | quit |
Read the CLI guide for input rules, colour behaviour, and programmatic use.
Definitions use domain concepts rather than Python code:
game TicTacToe {
board {
size: 3x3
playable_cells: all
}
players {
player X
player O
turn_order: X, O
}
piece Mark {
owner: X, O
place: any_empty_cell
}
win_conditions {
align: 3 same_row -> win
align: 3 same_col -> win
align: 3 diagonal -> win
board_full: no_winner -> draw
}
}
The language deliberately exposes a bounded set of reusable mechanics. Adding a new game that combines existing mechanics is mainly a modelling task; adding a new kind of mechanic requires coordinated grammar, AST, validation, and engine changes.
Read Defining a Game in Piecewise for the complete syntax, semantic rules, examples, and extension checklist.
The root README is a project overview. Detailed documentation lives beside the code it describes:
| Area | Documentation |
|---|---|
| Game definitions | games/games_README.md |
| Formal grammar | grammar/grammar_README.md |
| Parser, transformer, and AST | parser/parser_README.md |
| Semantic validation | validation/validation_README.md |
| Runtime engine | engine/engine_README.md |
| Command-line interface | cli/cli_README.md |
| Graphical interface | gui/gui_README.md |
| Test strategy and coverage | tests/tests_README.md |
Run the complete suite from the repository root:
python -m pytest -vThe documented final run collected and passed 261 cases. They cover syntax, AST transformation, semantic validation, initialization, immutable state, execution, move generation, game conditions, rendering, CLI interaction, GUI controller behaviour, and complete Checkers scenarios.
See the testing guide for the test groups, fixtures, levels, and focused commands.
Piecewise currently targets local, deterministic, turn-based games on rectangular boards. It does not yet provide arbitrary movement scripts, cards, dice, hidden information, saved matches, AI opponents, online multiplayer, or complete official rule sets for every Checkers variant.
These are deliberate boundaries of the current language rather than claims that every board game can be represented without extending the implementation.




