> ## Documentation Index
> Fetch the complete documentation index at: https://hedgeem-api.qeetoto.com/llms.txt
> Use this file to discover all available pages before exploring further.

# F004 — Game Stages

## Business Rule

A game of Texas HedgeEm progresses through five stages in a fixed sequence. The player cannot skip or reverse stages.

1. **Pre-deal** — The table is idle. Only the Deal button is visible. No cards are shown.
2. **Hole (PRE-FLOP)** — Two hole cards are dealt to each hand. All hole cards are face-up. Five community card positions are visible as face-down card backs. Betting is open on all live hands.
3. **Flop (POST-FLOP)** — Three community cards are turned face-up. Betting remains open.
4. **Turn** — A fourth community card is turned face-up. Betting remains open.
5. **River** — The fifth and final community card is turned face-up. Betting closes. All bets are resolved and winnings paid out. The Deal button reappears for the next game.

The player advances from Hole → Flop → Turn → River by clicking the Advance button once per stage.

### Stage naming (design document vs implementation)

The game concept document uses these stage names:

| Design doc name | HedgeEm `dealStatus` | Cards visible at betting open |
| --------------- | -------------------- | ----------------------------- |
| ANTE-BET        | Pre-deal (−1)        | None — not yet implemented    |
| PRE-FLOP        | Hole (0)             | Hole cards only               |
| POST-FLOP       | Flop (1)             | Hole + 3 community            |
| TURN            | Turn (2)             | Hole + 4 community            |
| *(no betting)*  | River (3)            | All 5 community               |

The design doc states the **default configuration is POST-FLOP only** (single betting stage). The reference implementations use all three betting stages (PRE-FLOP / POST-FLOP / TURN) — this is an operator configuration choice. See F014 for multi-stage betting and F032 for operator configuration.

***

## Technical Design

### State representation

| Stage    | `dealStatus` | `GameStateEnum`     |
| -------- | ------------ | ------------------- |
| Pre-deal | -1           | —                   |
| Hole     | 0            | `STATUS_HOLE = 6`   |
| Flop     | 1            | `STATUS_FLOP = 10`  |
| Turn     | 2            | `STATUS_TURN = 11`  |
| River    | 3            | `STATUS_RIVER = 12` |

`GameStateEnum` values match the original C# server `enum_game_state` — they are stored in `HandStageInfo.enumGameState` in every game record.

### State transitions (TypeScript — GameEngine)

```typescript theme={null}
advance(): boolean {
  if (this.dealStatus >= 3) return false; // already at river
  this.dealStatus++;
  return true;
}

get isGameOver(): boolean {
  return this.dealStatus >= 3;
}
```

`advance()` returns `false` at river so the caller knows not to update UI.

### Deal flow (`GameScene._onDeal`)

```
click Deal button
  → engine.loadLocalGame() or engine.loadApiGame()
  → engine.advance()       // dealStatus: -1 → 0 (hole)
  → _render()
  → advanceBtn.setVisible(true)
  → dealBtn.setVisible(false)
```

### Advance flow (`GameScene._onAdvance`)

```
click Advance button
  → engine.advance()       // dealStatus: N → N+1
  → _render()
  → if engine.isGameOver:
      → engine.resolveBets()
      → advanceBtn.setVisible(false)
      → dealBtn.setVisible(true)
      → _render()           // re-render to show WIN / final state
```

### Community card reveal schedule

```typescript theme={null}
const communityReveal = [0, 3, 1, 1]; // cards revealed per stage: pre→hole→flop→turn→river
let revealed = 0;
for (let s = 0; s <= dealStatus; s++) revealed += communityReveal[s];
// dealStatus 0 (hole):  revealed = 0  — all face-down
// dealStatus 1 (flop):  revealed = 3  — flop 1,2,3 face-up
// dealStatus 2 (turn):  revealed = 4  — + turn face-up
// dealStatus 3 (river): revealed = 5  — all face-up
```

### Hole card reveal rule

```typescript theme={null}
// HEDGE-135: all hole cards face-up once dealt
const faceUp = true;
```

All hole cards for all hands are face-up at the hole stage (and remain so). This matches the JS reference client which reveals all cards via `CC_DEAL_CARDx` states before opening the betting window.

*Note: an earlier version of this doc stated only hand 0 was revealed at hole. That was incorrect and was fixed by HEDGE-135.*

### HandStageInfo indexing

`GameRecord.handStageInfoList` is a flat array of `n × 4` entries (n = number of hands, 4 stages).
The entry for a given (stage, hand) is at index `dealStatus * n + handIndex`.

```typescript theme={null}
private _infoAt(hand: number): HandStageInfo | undefined {
  if (this.dealStatus < 0) return undefined;
  const n = this.record.numberOfHands;
  return this.record.handStageInfoList[this.dealStatus * n + hand];
}
```

***

## Acceptance Criteria

* [ ] On page load, only the Deal button is visible; no cards or hand panels are shown
* [ ] Clicking Deal transitions to hole stage: cards appear, Advance button visible, Deal button hidden
* [ ] At hole stage: all hole cards (all hands) are face-up (HEDGE-135)
* [ ] At hole stage: all 5 community card slots show face-down card backs
* [ ] Clicking Advance at hole → flop: 3 community cards revealed face-up; all hole cards now face-up
* [ ] Clicking Advance at flop → turn: 4th community card revealed; 5th still face-down
* [ ] Clicking Advance at turn → river: all 5 community cards face-up; Deal button reappears
* [ ] `advance()` returns `false` at river and does not increment `dealStatus` beyond 3
* [ ] `isGameOver` is `true` only at `dealStatus === 3`
* [ ] `resolveBets()` is called exactly once, after the river advance

***

## Version Parity

| Version    | Status            | Notes                                                                   |
| ---------- | ----------------- | ----------------------------------------------------------------------- |
| JavaScript | ⬜ Not yet audited | Reference implementation at hedgeem.qeetoto.com                         |
| TypeScript | ✅ Implemented     | `GameEngine.advance()`, `GameScene._onDeal()`, `GameScene._onAdvance()` |
| UMA        | ✅ Verified        | `tests/features/F004-game-stages.spec.ts` — AC1–AC6 pass (2026-04-15)   |

***

## Known Discrepancies

None documented yet.

***

## Test Coverage

Playwright spec: `tests/features/F004-game-stages.spec.ts` — AC1–AC6, all passing for UMA (2026-04-15). Run with `VERSION=uma npx playwright test tests/features/F004-game-stages.spec.ts --project=features --workers=1`

Existing partial coverage in `standalone_reference_client/tests/e2e/smoke.spec.ts`:

* `screenshot: full game cycle — deal → flop → turn → river` — covers stage transitions visually
* `betting: full cycle` — asserts `dealStatus === 3` and `gameOver === true` at river

Unit test coverage in `standalone_reference_client/tests/unit/GameEngine.test.ts`:

* `advances to hole (0) on first advance()`
* `advances through all four stages`
* `returns false from advance() when already at river`
* `isGameOver is true at river`
