A blazing-fast CLI that generates completely random soccer matches on the spot — or run scripted matches with the .tsrc (Tiny Soccer Sim Rust C) language.
Find a file
2026-09-25 10:23:38 -04:00
.cargo Add custom formatter and hybrid/situation mode 2026-09-24 23:27:43 -04:00
docs Update docs, add tests for SITUATION #define flag 2026-09-24 23:40:17 -04:00
src Make the code formatter take its own medicine 2026-09-25 10:23:38 -04:00
tests Update docs, add tests for SITUATION #define flag 2026-09-24 23:40:17 -04:00
.gitignore Initial Commit 2026-09-24 18:04:07 -04:00
.rustfmt.toml Code Cleanup for my preferred format 2026-09-24 22:27:47 -04:00
Cargo.lock Add goal scripting, as well as unit testing for the app. 2026-09-24 21:05:10 -04:00
Cargo.toml Add custom formatter and hybrid/situation mode 2026-09-24 23:27:43 -04:00
defines-test-match.tsrc Add docs, new define directive and ASCII table output as an option 2026-09-24 22:59:45 -04:00
gnu-bsd-soccer.tsrc Add docs, new define directive and ASCII table output as an option 2026-09-24 22:59:45 -04:00
LICENSE Add docs, new define directive and ASCII table output as an option 2026-09-24 22:59:45 -04:00
README.md Add custom formatter and hybrid/situation mode 2026-09-24 23:27:43 -04:00
scripted_match.tsrc Add docs, new define directive and ASCII table output as an option 2026-09-24 22:59:45 -04:00
situation-demo.tsrc Add custom formatter and hybrid/situation mode 2026-09-24 23:27:43 -04:00
STYLE.md Add custom formatter and hybrid/situation mode 2026-09-24 23:27:43 -04:00
test_match.tsrc Add docs, new define directive and ASCII table output as an option 2026-09-24 22:59:45 -04:00

tssr — Tiny Soccer Simulator Rust

A blazing-fast CLI that generates completely random soccer matches on the spot — or run scripted matches with the .tsrc (Tiny Soccer Sim Rust C) language.

Author

Mark Robillard Jr (MARKMENTAL)

Build

cargo build --release

The binary will be at target/release/tssr.

Usage

./tssr                             # random match (Unicode table)
./tssr --json                      # random match (JSON)
./tssr --script match.tsrc         # scripted match (table)
./tssr --script match.tsrc --json  # scripted match (JSON)
./tssr --help                      # show usage info

Shebang

#!/usr/bin/env tssr
string home = "Team A";
string away = "Team B";
match(home, away);
chmod +x match.tsrc
./match.tsrc

Output Modes

Mode How to enable
Unicode table Default (no flag, no #define)
ASCII table #define ASCII_TABLE in script
JSON --json CLI flag or #define JSON in script

The --json CLI flag always takes priority over #define.

Unicode table (default)

╔════════════════════════════════════════╗
║         TSSR MATCH RESULT              ║
╠════════════════════════════════════════╣
║  Man Page City        2 - 1  Libre Pool║
╠════════════════════════════════════════╣
║                                        ║
║  Shots              10           8     ║
║  On Target           4           3     ║
║  Possession         55%         45%    ║
║                                        ║
╠════════════════════════════════════════╣
║  Goals:                                ║
║  Man Page City: Marco Smith (23')      ║
║  Libre Pool: Dan Garcia (45')          ║
╚════════════════════════════════════════╝

ASCII table (#define ASCII_TABLE)

+--------------------------------------------+
|            TSSR MATCH RESULT               |
+--------------------------------------------+
|  Man Page City        2 - 1  Libre Pool    |
+--------------------------------------------+
|                                            |
|  Shots              10           8         |
|  On Target           4           3         |
|  Possession         55%         45%        |
+--------------------------------------------+

JSON (--json or #define JSON)

{
  "home": {
    "team": "Man Page City",
    "score": 2,
    "shots": 10,
    "shots_on_target": 4,
    "possession": 55,
    "scorers": [
      {"player": "Marco Smith", "minute": 23}
    ]
  },
  "away": {
    "team": "Libre Pool",
    "score": 1,
    "shots": 8,
    "shots_on_target": 3,
    "possession": 45,
    "scorers": [
      {"player": "Dan Garcia", "minute": 45}
    ]
  }
}

Scripting with .tsrc

.tsrc (Tiny Soccer Sim Rust C) is a minimal C-like DSL for defining teams, players, goals, and output mode.

Quick example

#!/usr/bin/env tssr
#define ASCII_TABLE

string home = "GNU United";
string away = "BSD Athletic";

players["Richard Stallman"] = home;
players["Brian Fox"] = home;
players["Theo de Raadt"] = away;

goal(12, home, "Richard Stallman");
goal(34, away, "Theo de Raadt");
goal(78, "BSD Athletic", "Theo de Raadt");

match(home, away);

Language syntax

Statement Purpose
string var = "Team"; Declare a team variable
players["Player"] = var; Assign player to team (variable or literal)
goal(min, team, "Player"); Script a goal at a specific minute
match(home, away); Select teams for the match (required)
#define JSON / ASCII_TABLE / UNICODE_TABLE Set output mode

When goal() is used, the score becomes deterministic — goals, minutes, and scorers are exact. Shots are floored at the goal count. Without goal(), everything is fully randomized.

The parser is strict: any inconsistency produces a clear error and exits immediately.

See docs/tsrc-language/README.md for the full language reference.

Formatting

This project uses a custom style (Anti-GNU, Anti-1TBS) — see STYLE.md. rustfmt is disabled.

A custom formatter binary is provided:

cargo fmt-tssr            # format all .rs files in src/ and tests/
cargo fmt-tssr path/to/file.rs   # format a specific file
cargo fmt-tssr src/ dir/         # format specific directories

Testing

cargo test

19 integration tests covering:

  • Goal validation (player on team, minute range, duplicates, undefined variables)
  • Script validation (undefined variables, same team, missing match, no players, duplicate variables)
  • #define directive (all modes, duplicate, unknown)
  • Happy paths (valid scripts, variable references, full scripted match)

Documentation

Document Description
docs/tsrc-language/README.md Full .tsrc language reference, grammar, validation rules
docs/engine/README.md Engine internals: random generation, scripted override, output formatting

Performance

  • Single runtime dependency (rand)
  • Release profile uses LTO, single codegen unit, panic=abort, symbol stripping
  • Sub-second cold compilation
  • Binary size: ~340KB stripped

License

This project is licensed under the GNU General Public License v3.0 — see LICENSE.