◀ Channel guide
● LIVECH 01CH ▶

Tonight on DBA 2

DBA2

A simulated NBA league that lives in Discord
Friends run the front offices. The game sims every possession and lets them watch it happen.
SEG 1

Live from the sim

One real game from the engine, shown the way the bot posts it in Discord. The buttons work like the real ones.

DEN @ OKC — game 412thread in #games
DBA 2BOT
Speed

This is game 412, simulated offline by the real engine from a fixed seed (6). The embed text, glyphs, buttons, colors and the pager come from the bot's own formatting code, run on that game and saved as data. The ratings are real 2025 NBA player ratings. The names are invented. In Discord this game plays out over about 10 minutes, one edit per play. Layout widths are approximate.

SEG 2

Tonight's rundown

The five systems that make the league feel alive.

  1. 7:00

    The Engine

    A possession-by-possession sim. Pick-and-roll, pick-and-pop, post-ups, turnovers that turn into loose-ball scrambles, and blocks credited to the right defender. Same seed, same game, every time.

  2. 7:12

    The Front Office

    Rule-based GMs with their own priorities. They counter trade offers, talk through deals, remember who burned them, and handle players who ask out or hold out.

  3. 7:24

    The Newsroom

    Media personas cover hot streaks, revenge games, rivalries and trade fallout. Before a story posts, every number it cites has to match a real stat. If it doesn't, the story is rejected and rewritten.

  4. 7:36

    The Real Players

    30 seasons of NBA data (1996–2025) translated into the sim's own ratings. It passes the eye test: John Stockton grades out at 99 passing vision and Rudy Gobert at 99 screen-setting.

  5. 7:48

    Court Viewer

    A Discord Activity. Open it in a voice channel and watch the game play out on an animated court, without leaving Discord. It is the third tab above.

SEG 3

Replay booth

Straight from the league's Discord server.

SIGNAL PENDING
/watch play-by-play
SIGNAL PENDING
Standings & ticker
SIGNAL PENDING
Court Viewer activity
SEG 4

Why I built it

“The first version needed a paid AI call for every trade and every headline. I wanted a league that thinks for itself and costs nothing to run.”

DBA 1 worked, but the GMs, the media and the trade logic all leaned on a paid AI API, and it had nowhere cheap to live. DBA 2 is a from-scratch rebuild. The intelligence comes from layered rules instead: GMs with motives, writers with voices, players with moods.

The hardest part was proving it plays like basketball. Each phase ends at a gate: simulate 3 different leagues for 5 seasons each, then check every stat against real NBA ranges. A phase closes only when all of them pass. Phase 3 closed at 32 out of 32.

How it's builtstack · architecture · hard problems
Pythondiscord.pyPostgreSQLAlembicaiohttpCloudflare Tunnelballdontlie APIpytestDiscord Activity (canvas)

Architecture

  • Headless simulation core, built and validated before any Discord code existed.
  • Phase-based league state machine: preseason → regular season → offseason, with every phase change made by the commissioner.
  • Deterministic: every random draw comes from a seeded stream, so any game or season can be replayed and debugged exactly.
  • The presentation layer returns plain panel objects. One small adapter turns them into Discord embeds, so the demo above runs the same formatting code offline.
  • Real cap rules: hard cap, dead cap, contract structures.

Problems worth mentioning

  • Fact-gated media. Each number a story cites is tied to a type of claim and checked against the box score before it can post.
  • Real data, messy API. Season totals silently included playoff games (Jokić showed 89 games in an 82-game season), and advanced stats only exist from 2012-13 on. Both were caught by spot-checking known players and fixed.
  • Tuning without cheating. Validation ranges come from separate runs, never from the run being graded.
  • No spoilers. A game's box score stays hidden until its broadcast has finished. Try /box in the demo before the game ends.

1,355 commits · 19,259 test cases · private repo