# Rollin' Ace Game Guide

> **Purpose**: this file is a **public document** for players and AI integrators — the **full edition** of the game guide (every mode, the basic controls, the item system and each scene).
> For a more compact edition, see the wiki pages: `basics.html` (Basics), `strategy.html` (Strategy), `nav.html` (Page guide).
> Chinese original: `skills/rollin-ace-game-guide.md` (kept in sync with this file).

> This document gives agents a complete operations guide to the Rollin' Ace baseball-dice web app, covering every mode, the basic controls, the item system and each scene.

---

## 1. Overview

Rollin' Ace is a **baseball-dice web app**. The core loop recreates **one half-inning** of a famous real-world baseball situation (usually "the bottom of the 9th"); the player is the **offence** and comes from behind through the "swing / lay off" choice in ball/strike plate appearances plus item play.

### Core mechanics

- **Server-authoritative**: every die roll probability, state transition, clear check, item deduction and reward is executed on the server; the front end only renders and sends requests
- **The ball/strike duel**: each plate appearance starts with a "swing / lay off" call, then the pitcher-gear die and (on contact) the hit die (including the two-option decision), plus the tactical game of 6 items

---

## 2. Basic controls

### 2.1 Ball/strike plate appearances (lay off / swing · the only mode)

**The only mode** (since 2026-09-21: the plain die roll was removed; the ball/strike toggle and the global preference were **deleted outright**, and it **cannot be turned off** in any mode). Every new plate appearance enters the ball/strike phase, the player no longer taps a separate "Roll" button, and instead chooses "swing" or "lay off" on every pitch:

1. The player chooses "swing" or "lay off"
2. The server rolls **that gear's pitch die** (6 faces; the five pitcher-style gears are in 2.3.1), and the face distribution is decided by the current pitcher-style gear; the six faces hold **5 pitch types**, each with a fixed swing / lay-off resolution (see 2.3):
   - "Swing": resolved by that pitch type's **whiff rate** (no whiff means contact, which switches to the hit die)
   - "Lay off": resolved by the ball/strike family (a strike-family face read wrong = strike +1 / a ball-family face read right = ball +1)
3. **Plate-appearance resolution** (see 2.3): strikes ≥3 → strikeout; balls ≥4 → walk; contact → switch to **that pitch type's** hit die; otherwise → choose swing / lay off again

### 2.2 The two-option decision

When the hit die shows the `Choose` face, the player picks one of two options:

**Option A: "Take the 1B" (conservative)**
- A single is granted outright and the batter reaches base safely
- Higher hit rate (about **48.7%** with the Balanced gear, up to 58.8% against a strike-heavy gear)

**Option B: "Roll the second die" (aggressive)**
- Rolls a second baseball die and enters a high-risk, high-reward branch:

| Face | Weight | Result |
|---|---|---|
| DP (double play) | 1 | Batter + the runner closest to home are out (before 2 outs); after 2 outs only the batter is out |
| BB (walk) | 1 | Batter to first, runners advance one base |
| 2B (double) | 2 | Batter to second, runners advance two bases |
| 3B (triple) | 1 | Batter to third, runners advance three bases |
| HR (home run) | 1 | All runners + the batter score, the bases are cleared |

**Normalised probabilities**: DP 16.67%, BB 16.67%, 2B 33.33%, 3B 16.67%, HR 16.67%.

**How to choose (one line)**: **with 0 outs always "take the 1B"; with 1 out check whether third base is occupied; with 2 outs always "roll the second die",
the only exception being "runner on third only".** For the reasoning and per-situation gaps see Strategy Guide §2 — note that 2 outs is *not* the conservative spot:
after 2 outs the double play only retires the batter (the DP row above), so the extra penalty is gone ❌ the old line "with 2 outs take the 1B to avoid the double play" is wrong.

### 2.3 Pitch types and their swing / lay-off resolutions

The plate-appearance flow is in 2.1. The six faces of the pitch die hold **5 pitch types**, each with a fixed swing / lay-off resolution:

| Pitch type | Result when swinging | Result when laying off |
|---|---|---|
| Dead-center (`s0`) | whiff 10% / contact 90% → hit die | read wrong → strike +1 |
| Strike (`s1`) | whiff 20% / contact 80% → hit die | read wrong → strike +1 |
| Nasty strike (`s2`) | whiff 50% / contact 50% → hit die | read wrong → strike +1 |
| Ball (`b1`) | whiff 40% / contact 60% → hit die | read right → ball +1 |
| Wide (`b2`) | whiff 80% / contact 20% → hit die | read right → ball +1 |

> **Whiff rate**: swinging is no longer "always make contact on a dead-center, always miss on a wide" — all five pitch types carry a whiff probability
> (dead-center 10% / strike 20% / nasty 50% / **ball 40%** / wide 80% — ball changed from 20% on 2026-09-27); no whiff means contact. Laying off is resolved independently of the whiff rate: it is always "strike family read wrong / ball family read right".
> The whiff rate expresses **how easy that pitch is to hit (contact difficulty)** and has nothing to do with the ball/strike count:
> dead-center is the easiest → strike / ball → nasty → wide is the hardest; so "swinging at a ball is easier to touch than swinging at a nasty strike" is by design
> (`b1` ball is the neutral item; the real ball trap is the `b2` wide).

**Hit dice (one per pitch type, rolled after contact, 6 faces)**: the easier a pitch is to hit, the stronger it is after contact —

| Pitch type | Out | Foul | Single | Choose |
|---|---|---|---|---|
| Dead-center `s0` | 1 | 1 | 2 | 2 |
| Strike `s1` | 2 | 1 | 2 | 1 |
| Nasty strike `s2` | 2 | 2 | 2 | 0 |
| Ball `b1` | 2 | 2 | 1 | 1 |
| Wide `b2` | 3 | 2 | 1 | 0 |

> Doubles / triples / home runs **are no longer produced directly by the hit die**; they still only come from Bat upgrading a single.
> A "foul" on the hit die = one strike recorded for the plate appearance (no further increase at 2 strikes) and back to choosing swing / lay off.

#### 2.3.1 Pitcher-style gears (they decide the face distribution)

Each of the five "pitcher styles" is **an independent 6-face die** (not one die with adjusted weights) — the gears run from ball-heavy to strike-heavy (ball faces 5→1):

| Gear | UI name | Six-face distribution (counts: `s0` / `s1` / `s2` / `b1` / `b2`) | Ball:Strike | Role |
|---|---|---|---|---|
| `bbb` | Mostly balls | 1 / 0 / 0 / 1 / 4 | 5:1 | Extreme walk orientation (gives up nasty strikes by design · flagged red "Danger" on the panel) |
| `bb` | Ball-heavy | 1 / 0 / 1 / 1 / 3 | 4:2 | Walk orientation · punishes wild swings, favours patience |
| `bs` | Balanced (default) | 1 / 1 / 1 / 1 / 2 | 3:3 | The safe default |
| `ss` | Strike-heavy | 1 / 2 / 1 / 1 / 1 | 2:4 | Strikeout orientation · punishes waiting, favours swinging |
| `sss` | Mostly strikes | 1 / 3 / 1 / 1 / 0 | 1:5 | Extreme strikeout orientation |

- Every gear has **exactly one dead-center `s0`** (a floor on its strength) + **one ball `b1`** (the neutral item); the nasty strike `s2` is one face on every gear except `bbb`.
- Ball-heavy gears punish wild swings (more `b2` ⇒ 80% whiff); strike-heavy gears punish waiting (more `s1` ⇒ waiting means reading it wrong).
- **The whiff rate stops "swing" and "lay off" from being zero-sum**: swinging got stronger overall — with the Balanced gear, swinging everything reaches the hit die **89.8%** of the time,
  and even `bbb` (mostly balls) rose from the old model's 42.1% to **76.5%** (hit rate 36.9% when swinging everything — no longer a dead end).

#### 2.3.2 Where the gear comes from (Duel vs single-player)

- **Duel rooms (Duel / PvP / AI Duel)**: the defence picks a gear **before each half-inning it defends** (**every batter in that half-inning uses it, and it is re-picked after the sides change**); before the match starts the starting defence (the home-side host) picks the "starting pitcher" gear first. **Ball/strike is always on ⇒ the gear always applies** (the old condition "only applies when the opponent enables ball/strike" is gone).
- **Single-player (Bottom-9 Challenge)**: no panel; each inning rolls a weighted random gear of **Strike-heavy 30% · Balanced 50% · Ball-heavy 20%** (only the middle three gears; Mostly strikes / Mostly balls never appear).

**Panel interaction**: the five gears are five cards, **one tap selects it** (150 ms freeze feedback; taps are ignored for the first 250 ms after it appears, to prevent mis-taps); tapping the blank area outside the cards takes the default, Balanced. **If the countdown expires with no input, it starts on Balanced automatically.**

**Time limit**: **5 seconds**; it is **10 seconds** only for the match's first gear pick when the opponent is an AI (every other case — half-inning changes, human opponents, tournament games — is 5 seconds).

**Waiting hints and result echoes**:
- The offence does not see this panel; while waiting it shows "The opponent is choosing a pitching strategy…" (against an AI it shows "The AI is thinking about its pitching strategy…", and the AI pauses about 2 seconds before committing).
- Under every ball/strike plate-appearance result (contact / whiff / read right / read wrong, etc.) a separate line shows **"opponent chose «swing / lay off» · die face"** (dead-center / strike / nasty strike / ball / wide), so both the defence and spectators can see the opponent's choice and die face for every plate appearance.

### 2.4 Clear and fail

- **Clear (passed)**: the score is overturned (our score > their score) and the half-inning ends immediately
- **Fail (failed)**: 3 outs reached without overturning the score

---

## 3. The item system

### 3.1 Item overview

| Item | Name | Type | Description | Face distribution (1~6) |
|---|---|---|---|---|
| bat | Bat | Passive | Any hit is upgraded one level automatically (1B→2B→3B→HR) | no die roll |
| steal | Steal | Active | The runner on first steals second | success ×4 / failure ×2 |
| sac | Sac | Active | Sacrifice hit: every runner advances one base, the batter is out | success ×4 / failure ×2 |
| mist | Mist | Active | A defensive error, resolved at random | passed ball / wild throw / wild pitch / nothing ×2 / Nice Play |
| lun | Hack | Active | Blind-power hitter, high risk and big reward | OUT ×4 / triple ×1 / home run ×1 |
| ling | Cmd | Active | Call the play: on success, resets **this half-inning's** item uses | success ×3 / failure ×3 |

### 3.2 Rules of use

- **At most 3 items per half-inning** (**reset automatically on a side change**), and the same item cannot be used twice in a half-inning
- **How Cmd refreshes**: on success it resets **this half-inning's** uses to 3 and clears the used-item set, so every item becomes available again
- **Once the allowance is full, no item can be sent at all** (Cmd included) — to use Cmd you must do it while **one charge is left**
- **Bag limits**: at most 20 of each item, 120 in total

### 3.3 Conditions of use

| Item | Condition |
|---|---|
| Bat | none (once picked it applies automatically to any single on the hit die) |
| Steal | runner on first, second base empty |
| Sac | before two outs and a runner on base |
| Mist | none (but **only worth using with 0 outs**, see 3.5) |
| Hack | none |
| Cmd | no precondition (success resets the half-inning allowance); ⚠️ **cannot be sent while the allowance is full** |

### 3.4 Item restrictions in ball/strike mode

- **During a BS plate appearance**: only Steal is available; every other active item is disabled
- **Bat** is passive and always active (a 1B rolled on the hit die after ball/strike contact is upgraded to a 2B too)
- Mist / Sac / Hack can only be used **before a plate appearance starts**; once used the plate appearance is resolved directly, bypassing the ball/strike flow

### 3.5 Item effects in detail

**Bat (`bat`)**:
- Any single rolled on the hit die is upgraded automatically: 1B→2B, 2B→3B, 3B→HR
- OUT / DP / BB etc. are unaffected
- Consumed regardless of how the plate appearance ends

**Steal (`steal`)**:
- Success (4/6 = 66.67%): the runner on first takes second
- Failure (2/6 = 33.33%): the runner on first is out

**Sac (`sac`)**:
- Success (4/6 = 66.67%): every runner advances one base (including scoring from third), the batter is out
- Failure (2/6 = 33.33%): the batter is out, the bases are unchanged

**Mist (`mist`)**:

| Face | Effect |
|---|---|
| 1 passed ball | Runners advance one base; with nobody on, nothing happens (escaped it) |
| 2 wild throw | Runners advance **two bases**; with nobody on, nothing happens |
| 3 wild pitch | Runners advance one base; with nobody on, nothing happens |
| 4-5 nothing happens | The state is unchanged, but **the plate appearance is eaten** (a wasted batter) |
| 6 Nice Play | Runner on base and before 2 outs ⇒ **double play** (batter + **the runner closest to home**); already 2 outs or nobody on ⇒ only the batter is out |

- ⚠️ **Only worth using with "0 outs and a runner on base"**: with 1 out that 1/6 double play makes it 3 outs and ends the half-inning on the spot.
- ⚠️ The two "nothing happens" faces (4/5) **end the plate appearance** (they do not re-roll) ⇒ there is a 1/3 chance of wasting a batter, so it must not be regarded as a "50% advance item".

**Hack (`lun`)**:

| Face | Effect |
|---|---|
| 1-4 OUT | the batter is out (66.67%) |
| 5 triple | every runner advances three bases, the batter reaches third (16.67%) |
| 6 home run | the batter and every runner score (16.67%) |

**Cmd (`ling`)**:
- Success (3/6 = 50%): resets **this half-inning's** item uses to 3 and clears the "used this half-inning" set
- Failure (3/6 = 50%): no effect, but it still consumes one charge
- ⚠️ **There is only one correct window**: send Cmd when the half-inning allowance is **down to its last charge** — success means three charges for free, failure exhausts the allowance.
  Sending Cmd while the allowance is full **cannot go through at all**; sending it with charges to spare lowers the expectation instead of raising it (with three left, Cmd's expectation is 2.5 < 3).

> For measured conclusions on the relative strength of the items and on whether the allowance is worth hoarding, see Strategy Guide §10 (self-play measurements).

### 3.6 Where items come from

| Source | Reward |
|---|---|
| New-user grant | 3 of each |
| Normal clear (comeback win) | 4 of the 6, 1 of each |
| Walk-off home run (HR and clear) | Bat 3 / Hack 3 / Steal 2 / Sac 2 / Mist 2 / Cmd 2 |
| Standalone home run (no clear) | Bat 2 / Hack 2 |
| End of a 3-OUT inning (fail) | 1 weighted random item: Steal/Sac 20% each, Bat/Hack/Mist/Cmd 15% each |

---

## 4. Modes

### 4.1 Bottom-9 Challenge (Challenge)

**Entry point**: the home page (the home page *is* the Bottom-9 Challenge — it opens straight into it, with no separate button)

"Bottom-9 Challenge" = a challenge series of consecutive games, with progress and rewards settled independently. Naming history: `Tournament → (09-20) Challenge → (09-21) Bottom-9 Challenge`.

**Gameplay**:
1. The home page is the Bottom-9 Challenge by default; on entry the system serves the current challenge (published from the admin side)
2. One half-inning (usually the bottom of the 9th): come from behind by choosing swing / lay off and using items
3. Starting state: we trail, N outs, a specific base configuration
4. Overtaking the score clears it (passed); reaching 3 outs without overtaking fails it (failed)

**Characteristics**:
- Consecutive games; clearing every game = **completing the run**
- Progress is settled independently; after a refresh / re-entry you resume after the highest game already cleared (continue play)
- The admin side updates the challenges daily / per period; each game can configure its own team names, score, outs, bases, innings, etc.
- Clearing / completing pays item rewards; each game can also carry an admin-configured reward card
- Ball/strike is the **only mode** (no toggle, always on)

**API flow**:
1. `GET /api/series` → read the current Bottom-9 Challenge + progress
2. `POST /api/roll` → roll the die + advance the state
3. `POST /api/series action=progress` → report progress / completion

---

## 5. Other scenes

### 5.1 Report room (match report / Report)

**Entry point**: a report event in the home page's "NEWS" feed; you can also pick one in the report lobby (spectator page)

**Overview**:
- A live match broadcast scene, created and controlled by back-office programs
- **Watch only** — there is no host die-rolling gameplay

**Key features**:
- R/H/E scoreboard (hits / errors accumulate automatically)
- Base state rendered in real time
- Event log (match-ups, hits, outs, etc.)
- Supports both live and replay modes
- State machine: `created` → `live` → `ended` → `closed`; `live` ↔ `paused`; any → `cancelled`

**How to watch**:
1. Enter from "NEWS" on the home page (the report-viewer; there is no separate "Report" entry any more)
2. The spectator side pulls incremental event frames with `GET /api/live`
3. Voice commentary (TTS) is supported: Chinese goes through Tencent Cloud's large-model speech synthesis (needs a key configured on the admin side), Japanese uses the browser's local voice
4. On join it returns a snapshot of the current state (`situation`), so the situation renders without replaying every historical frame

### 5.2 Live room (interactive live / Live)

**Pages**:
- Lobby: the Duel lobby (it hosts the live-spectating entry)
- Spectator side: the live-spectating page

**Overview**:
- A live room is created by a host who publishes frame by frame; spectators are a read-only mirror
- Since 2.0.0 live has no separate "Live" entry: live spectating merged into the home page's "Duel" entry and is reached through the Duel lobby

**Host flow** (custom-challenge creation is retired; live now comes from enabling streaming in a Duel room):
1. Create a Duel in the lobby and turn on streaming
2. Once the room's `matchStatus=live`, spectators can watch
3. Publish frame by frame to the spectators
4. Danmaku (chat-overlay) interaction is supported

**Spectator flow**:
1. Enter the Duel lobby from the home page's "Duel" entry, pick a room with streaming on → tap "Watch"
2. The display refreshes incrementally (nothing manual needed)
3. Danmaku can be posted (needs the danmaku feature enabled on the site)
4. The manual "Refresh" button pulls the latest frame in full

### 5.3 Spectating (Live Viewer)

**Entry point**: a room in the Duel lobby with streaming on → tap "Watch" (live-spectating page)

**Overview**:
- Shares the same spectating logic as a live room
- Spectators enter the Duel lobby from the home page's "Duel" entry and tap "Watch" on a room with streaming on

### 5.4 Duel rooms (Duel / PvP)

**Pages**:
- Lobby: the Duel lobby
- Room: the Duel room

**Overview**:
- Home vs away PvP matches
- 1–9 innings, alternating offence and defence
- The away side bats first

**Lobby row buttons** (shown by the signed-in user's role for that room):
- I am that room's home or away side → "Return" (straight back into the Duel room)
- A third party and the away seat is still open (joinable) → "Join" (join as the away side)
- Both seats taken and the room has streaming on → "Watch"

**The full flow**:

1. **Create** (home side)
   - Tap "Create Duel" in the Duel lobby
   - Set the preset innings (1~9) and whether to stream
   - Room state: `matchStatus=waiting`

2. **Away side joins**
   - Tap "Join Duel" in the lobby
   - `matchStatus=live`, the match starts
   - **The away side bats first**

3. **During the match**
   - Whoever is batting rolls / uses items → reports a frame
   - The defence and spectators are a read-only mirror
   - 3 outs in a half-inning change the sides
   - End of the top half → the bottom half (home bats)
   - End of the bottom half → the next inning's top half (away bats)

4. **Extras**
   - Still level after the preset innings → extra innings
   - 0 outs with runners on first and second

5. **End of the match**
   - The home side taking the lead in the bottom half = walk-off, it ends immediately
   - The away side does not stop in the top half (plays the half out)
   - **30 seconds** after the end the room closes automatically

**Disconnects**:
- Being offline for more than **30 seconds** counts as offline; if both sides drop, the room is reclaimed

### 5.5 AI Duel (AI Duel / agent integration)

**Entry points**:
- Public endpoint: `POST /api/ai`
- Sign-up flow, credentials and the full contract: the **“AI Access” site** (`open.yakidev.top`) and the public contract repo `rollinace_duel_api`

**Overview**:
- External AI agents / server-side strategy programs join Duel rooms through the public endpoint
- Two shapes: **AI vs human** (the AI joins a Duel room created by a human, batting first as the away side by default) and **AI vs AI self-play** (platform-owned)
- It shares the same state machine, rule engine and spectating frame channel as the human side: every AI action broadcasts a frame, so a human can watch in real time
- Seats, credentials, sessions, the concurrent-match limit and quotas — all **integration details** — follow the “AI Access” site and the public contract repo listed above

**action list** (in-match actions; see the public contract for per-field semantics):

| action | Description |
|---|---|
| `state` | Reads the situation + the actions the server allows + whether it is your turn |
| `act` | Executes an operation (`roll` / `swing` / `read` / `take1b` / `roll2` / `item` / `init` / `duel_half_start` / `set_pitch`) |
| `heartbeat` | Keep-alive (reading the situation / acting refreshes the online timestamp as a side effect) |
| `leave` | Leaves the room |

**AI decision loop**:
1. `state`: act only when it is your turn and the list of allowed actions is non-empty; while the server is changing sides automatically, retry a moment later
2. `act`: decide within the allowed actions (the decision rules match player strategy, see the Strategy Guide)
3. A rejected operation returns the allowed set; simply correct yourself against it
4. **Side changes and match end are advanced by the server**; the AI needs no extra calls

**Notes**:
- Rules are resolved by the server-authoritative engine; the AI only decides within the allowed actions and must not derive results locally
- Judge success by the server's response
- For real integration read `rollinace_duel_api`'s `doc/AI_DUEL_API.md` / `doc/QUICKSTART.md` / `doc/AI_DUEL_FAQ.md` (multi-language samples included)

**Defensive gear selection (ball/strike)**:
- Ball/strike is **always on**, so an AI room necessarily uses it — no switch involved
- A defending AI decides by the role's configured "BS approach" (swing everything / swing-leaning / balanced / lay-off-leaning / lay off everything) and consults the opponent's swing / lay-off counters for that match to pick a countering gear: the opponent **swings a lot → ball-heavy (walk oriented)**, **lays off a lot → strike-heavy (strikeout oriented)**; it pauses about 2 seconds before committing (against an AI you can see "The AI is thinking about its pitching strategy…").

---

## 6. Match history

### 6.1 Cross-mode records

**API**: `GET /api/history`

**Storage**: cloud records kept separate from the user's main profile and bag

**What is recorded**:

| Mode | Field | Description |
|---|---|---|
| Bottom-9 Challenge | `challenge_mode_data.succ_ids` | list of cleared event ids (deduplicated) |
| Series | `series_mode_data.win_ids` | list of series ids won (deduplicated) |
| Duel | `duel_mode_data.wins / losses` | cumulative wins / losses |

- On the way out, event ids are resolved to event names; a miss falls back to the id

---

## 7. Music and sound

### 7.1 Sound effects

- Web Audio procedural synthesis, zero external assets
- Controlled by the `master` bus

### 7.2 BGM library

- mp3, uploaded from the admin side into the cloud music library
- Two themes: `classic` and `endless`
- At most 10 tracks per theme, each ≤ 10MB

### 7.3 Scene slots

Three slots per theme, each naming **one** track:

| Slot | Trigger |
|---|---|
| `always` (throughout) | plays the moment the page opens |
| `idle` (idle) | before play starts (entering a plate appearance) |
| `playing` (in play) | after play starts (entering a plate appearance) |

- **Exclusion rule**: "throughout" cannot coexist with idle/in-play; idle and in-play can coexist
- **Auto volume drop during play**: one coefficient per theme (0.2~1.0, default 0.5) with a 0.3 s fade, lowering the BGM only — sound effects are unaffected
- **iOS constraint**: sound needs a first user gesture (browser autoplay policy)

### 7.4 Voice commentary (TTS)

- Chinese: by default the browser's free local `speechSynthesis`; with a Tencent Cloud key configured on the admin side it uses the cloud's higher-quality voice
- Japanese: always the browser's local voice
- The Chinese TTS voice is configured on the admin side

---

## 8. Feature switches and guards

### 8.1 Site config

Some entries and capabilities are controlled by the site configuration (**whether one is open is shown in the app itself**):

| Switch | Default | Effect |
|---|---|---|
| Live | on | live lobby + live spectating |
| Report | on | report lobby + report spectating |
| Duel | on | Duel lobby + Duel rooms + challenge rooms |
| Danmaku | off | danmaku input area |
| Voice-commentary button | off | voice-commentary button on the report page |
| Music | on | master music switch |
| Chinese TTS voice | empty | empty = the browser's free local voice |
| WeChat article link | empty | related entry |

> Since 2.0.0 live has merged into the "Duel" entry: spectating is carried by the "Duel" entry (the Duel lobby); whether each entry is open is shown in the app itself.

### 8.2 How a switch takes effect

- **Page side**: with an entry off, its pages redirect to a single "unavailable" page
- **Server side**: with an entry off, its requests are rejected and no data is fetched
- Turning any entry off leaves every other feature (die rolls, Bottom-9 Challenge, records, etc.) unaffected

---

## 9. Baseball rule essentials

### 9.1 Outs and ending a half-inning

- 3 outs = the half-inning ends
- Strikeouts, double plays, failed sacrifices etc. all add outs

### 9.2 Runner advancement

- Hits advance runners by base count (1B one base, 2B two, 3B three)
- HR (home run): all runners + the batter score
- **Stop on overtaking**: once the score is overturned, later runners crossing home no longer score (HR excepted)

### 9.3 Double play (DP)

- Before 2 outs: the batter is out + the runner closest to home is out (two outs)
- After 2 outs: downgraded to a plain OUT (only the batter)

### 9.4 Walk (BB)

- The batter goes to first
- Runners advance one base each

---

## 10. UI elements

### 10.1 Main page

- **Scoreboard**: both scores, the inning, the outs
- **Base diagram**: occupancy of first / second / third
- **Dice area**: the pitch die (pitcher gear) + the hit die (after contact) + the second baseball die (shown on a two-option)
- **Item panel**: 6 skill slots showing stock and use state
- **Ball/strike lights**: 3 ball lamps (green) + 2 strike lamps (yellow)
- **Result area**: the text for this die result
- **Action buttons**: Swing / Lay off / Take the 1B / Roll the second die

### 10.2 Modes and entries

- The home page is the **Bottom-9 Challenge** by default (consecutive games) and opens straight into it, with no separate button
- Duel / report are reached through the Duel lobby and NEWS respectively (subject to the feature switches)
- Home-page entry buttons: left column **NEWS / Duel**, right column **Tournament / Items** — four in total; since 2.0.0 the old separate "Live" and "Report" buttons are gone, live spectating merging into "Duel" and report into "NEWS"
- International build (`*.rollin-ace.live`): only the "Items" button shows by default; the other entries (NEWS / Duel / Tournament) are hidden unless the admin explicitly turns the matching switch on

---

## 11. API endpoints quick reference

| Endpoint | Method | Description |
|---|---|---|
| `/api/roll` | POST | die roll + state-advance engine |
| `/api/series` | GET | read the series + progress |
| `/api/series` | POST | progress reporting |
| `/api/user` | GET | read the item bag |
| `/api/user` | POST | grant / consume / reset |
| `/api/live` | GET | lobby list / incremental stream |
| `/api/history` | GET | the player's match history (📜: normal clears / series wins / Duel record) |
| `/api/config` | GET | public site config (live / report / Duel / danmaku / TTS / music switches etc.) |
| `/api/migrate` | POST | recover an old identity (switch back with an old uid; needs the CSRF header `X-Requested-With: rollin`) |
| `/api/music` | GET | BGM delivery (`?theme=classic|endless` picks by scene; `&id=` picks a specific track) |
| `/api/tts` | GET | TTS synthesis (probe the config state / synthesise speech) |
| `/api/teams` | GET | team data (random team names in the Duel lobby etc.) |
| `/api/ai` | POST | AI Duel endpoint (public contract: session / create / join / list / state / act / heartbeat / leave / close etc.) |

> Admin endpoints are not listed here; the report / live back-office task API lives in the public repo `rollinace_live_api`.

---

## 12. Key constants (player-facing)

| Constant | Value | Description |
|---|---|---|
| Hit die (per pitch type, 6 faces each) | `s0`: OUT×1/FOUL×1/1B×2/Choose×2 · `s1`: OUT×2/FOUL×1/1B×2/Choose×1 · `s2`: OUT×2/FOUL×2/1B×2 · `b1`: OUT×2/FOUL×2/1B×1/Choose×1 · `b2`: OUT×3/FOUL×2/1B×1 | rolled after contact |
| Two-option die weights | DP:1 / BB:1 / 2B:2 / 3B:1 / HR:1 | the high-risk branch |
| Whiff rate (per pitch type) | `s0`:10% / `s1`:20% / `s2`:50% / `b1`:40% / `b2`:80% | when swinging |
| Solo pitcher-gear weights | Strike-heavy 30% / Balanced 50% / Ball-heavy 20% | rolled per inning in single-player |
| Items per half-inning | 3 | a successful Cmd resets it |
| Bag cap per item / total | 20 / 120 | 20 each of the 6 |
| Gear-panel time limit | 5 s (10 s for the match's first pick against an AI) | on timeout it starts on Balanced |
| Offline detection / auto room close | 30 s / 30 s | 30 s away counts as offline; the room closes 30 s after the match |
| New-user grant | 3 of each | 6 items |
| Fail-end reward weights | Steal:20 / Sac:20 / Bat:15 / Hack:15 / Mist:15 / Cmd:15 | 1 weighted random item |

> Integration details (credentials, sessions, the concurrent-match limit, quotas, etc.) are on the "AI Access" site and in the public contract docs, and are not expanded here.