logo

Babylon.js Market

Unlock

Install with the CLI:

bjs download PokerTableDirector

PokerTableDirector

PokerTableDirector is the match state machine for a Texas Hold'em table: it turns a deck, a seating plan, a betting machine, a set of AI seats, and a card renderer into a played game, talking to each only over the EventBus. It is to poker what PongDirector is to Pong — the glue, and nothing but the glue.

What it does

A poker hand is a sequence on a clock: deal, reveal, bet, flop, bet, turn, bet, river, bet, showdown. The director owns that clock and that sequence; the pieces it drives own everything else.

On attach it builds the seat layout — from a sibling PokerSeating entity if one is in the scene, otherwise derived from the variant counts — restores the chip carry-forward, wires the AI personalities into PokerBetting, and deals the first hand. Each frame it advances a game clock and steps the scheduled phases: flip the player's hole cards, pause for the betting round, flip the flop/turn/river, request the showdown. When the showdown resolves (or everyone but one seat folds), it awards the pot, snapshots stacks, and ends the hand. Between hands it runs a delay timer and re-arms; when one seat owns every chip it freezes on game-over until a reset.

Every phase result leaves the director as an event. It never reads another component's fields and never touches the renderer — the CardFan, DeckDealer, PokerBetting, and PokerHandEval systems do the drawing, dealing, money, and ranking.

All of the bookkeeping — variant configs, the game-flow scheduler, the between-hands lifecycle, the announcement queue, deal-reset, the strategy plan, and the chip carry-forward — lives in PokerTableDirector.core and is deterministic: the same inputs produce the same state. The System is the part that talks to the bus and to a localStorage seam for stack persistence.

Use it in a scene

Drop the director on its own entity alongside the table it conducts: a DeckDealer + PokerSeating dealer, a PokerBetting + PokerHandEval table, a CardFan for the player's hand, and one AI personality per NPC seat.

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Fastest path

bjs download scene PokerTableDirector

Pulls this exact scene into your project and runs it — no copy-paste. Add --all to grab the components and assets it needs too.

Or build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add PokerTableDirector
    bjs download PokerTableDirector

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Match": {
    "components": {
      "PokerTableDirector": {
        "variant": "texasHoldem",
        "startingStack": 500,
        "delayBetweenHands": 4,
        "strategyNames": ["Randy", "Bill", "Cali"]
      }
    }
  }
}

See example.scene.json for the full playable table — player seat, three NPC seats, an ArcCamera, a DirectionalLight with shadows, and the dealer/betting/fan/AI siblings the director conducts.

The director deals the first hand automatically. Confirm each later hand by emitting pokerTable.deal (wire it to a Space key); reset the whole session with pokerTable.matchReset.

Props

PropTypeDefaultNotes
variant'texasHoldem' | 'omaha' | 'fiveCardStud' | 'sevenCardStud' | 'fiveCardDraw''texasHoldem'Which built-in variant to run. An unknown name falls back to Hold'em.
startingStacknumber500Chips every seat starts the session with.
delayBetweenHandsnumber4Seconds the table waits after a showdown before re-arming.
dealAnimnumber1.0Deal-flight duration used to time the first phase.
strategyNamesstring[][]NPC personalities by name (Randy, Bill, Surge, Cali), in seat order. Empty rotates through the built-in roster.

Events

Output (PokerTableDirectorEvents):

NameWhenPayload
pokerTable.handStartedA hand is armed and dealt{ handNumber, activeIds }
pokerTable.handEndedA hand resolves (showdown or fold-out){ winnerIds, stacks }
pokerTable.gameOverOne seat owns every chip{ winnerId }
pokerTable.awaitingDealThe table is idle, waiting for the next deal{}
pokerTable.strategiesThe NPC seat plan, for a HUDRecord<seatId, { name, initial, color }>
pokerTable.flipA non-player group's card reveal (npc/river){ group, indices, interval }

Input (PokerTableDirectorInputEvents):

NameEffectPayload
pokerTable.dealConfirm the next hand should be dealt{}
pokerTable.matchResetRestore every seat to the starting stack and re-arm{}

The director also listens to the betting and showdown systems — poker.currentTurn, poker.chips, poker.handOver, poker.showdown.resolved — and the deck's deck.dealt, and emits deck.dealRequest/deck.resetRequest, poker.dealRequest, cardfan.deal/cardfan.flip, and poker.showdown.request to drive them. NPC reveals it relays as poker.actionTaken (PokerBetting's output name), distinct from the poker.turnAction input a seat submits.

Dependencies

  • DeckDealer — shuffles and deals; its deck.dealt events fill the director's card slots so the showdown ranks real hands.
  • PokerSeating — the static seat geometry + deal plan; the director reads its layout when present.
  • PokerBetting — owns the chips and the betting round; the director injects the AI strategies into it via setStrategies and pauses its clock for the round.
  • PokerHandEval — ranks the seated hands at the showdown.
  • CardFan — renders the player's hand; the director sends it cardfan.deal and cardfan.flip.
  • PokerAIRandy, PokerAIBill, PokerAISurge, PokerAICali, PokerAIShark, PokerAITilt — the NPC personalities. Name them in strategyNames, or seat the components directly for the state-bound brains (Shark, Tilt).

Notes

  • AI wiring is loose-coupling. The director calls PokerBetting.setStrategies with the stateless personality callbacks (randy, bill, surge, cali) keyed per NPC seat — the betting machine never imports a brain. The state-bound personalities (Shark's opponent model, Tilt's mood) self-register from their own components when you seat them.
  • One betting round per hand. PokerBetting opens a single round when a hand deals. The director pauses its clock for that round and resumes on the round's completion (poker.currentTurn with a null seat); later betting phases pass straight through, so the flow still reaches the flop/turn/river flips and the showdown.
  • The CardFan renders one hand. In a single-seat scene the CardFan holds the player's two cards, so only the player group's reveal maps onto its slots. NPC and river reveals ride pokerTable.flip for a richer multi-hand renderer; the minimal fan never sees an out-of-range index.
  • Persistence is a seam, not the core. Stacks survive reload through a typeof-guarded localStorage store. Swap it with setStackStore(...) to inject a different store (or a test double); the carry-forward math itself stays pure in the core.

More like this

CardFan
DeckDealer
PokerAIBill
PokerAICali
PokerAIRandy
PokerAIShark
PokerAISurge
PokerAITilt
PokerBetting
PokerHUD
PokerHandEval
PokerInput
PokerMultiplayer
PokerSeating
PokerTableCards
TurnPacer
BallReset
GameConfig
Goal
MissionDirector
PokerAI
SoccerDirector
WaveDirector

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search