248 lines
8.2 KiB
Markdown
248 lines
8.2 KiB
Markdown
# GAME DESIGN DOCUMENT — *“DUEL OF SIGNS: A ROCK–PAPER–SCISSORS TOURNAMENT”*
|
||
|
||
---
|
||
|
||
## 1. Concept Paragraph
|
||
|
||
**Concept:**
|
||
*Duel of Signs* is a deterministic, text-based tournament between two contenders — called **Signmasters** — who compete through successive matches of an expanded **Rock–Paper–Scissors** variant. The universe is a ceremonial arena where hand-sign duels determine dominance. Each player secretly chooses one of three signs (`[Rock]`, `[Paper]`, `[Scissors]`) per round. The goal is to win a majority of rounds in a predefined number of matches. Players can also invoke the `[Predict:<Sign>]` token to gamble on the opponent’s next move for bonus points. This design is **entirely unrelated to any negotiation or trading scenario**; it contains no resource bargaining, currency, or offers — only symbolic duels and prediction tactics.
|
||
|
||
---
|
||
|
||
## 2. Roles and Win Condition
|
||
|
||
**Roles:**
|
||
- **Player A:** Signmaster 1
|
||
- **Player B:** Signmaster 2
|
||
|
||
Each behaves symmetrically.
|
||
|
||
**Primary Objective:**
|
||
Earn more **tournament points** than the opponent after all rounds have concluded.
|
||
|
||
**Scoring:**
|
||
- Win a duel → +2 points
|
||
- Draw a duel → +1 point
|
||
- Loss → 0 points
|
||
- Correct use of `[Predict:<Sign>]` (if correct) → +1 bonus point
|
||
- Incorrect prediction → −1 penalty point
|
||
|
||
**Decision Rule:**
|
||
At the end of the final round:
|
||
- Higher score → **Winner**
|
||
- Equal scores → **Draw**
|
||
|
||
---
|
||
|
||
## 3. Turn Structure and Determinism
|
||
|
||
Each **round** has two **turns** (one per player in sequential mode).
|
||
The game proceeds through a fixed **number of rounds**, e.g., `5`.
|
||
Turn order alternates each round (A starts odd rounds, B starts even).
|
||
|
||
After both have chosen, the system resolves the duel deterministically:
|
||
- Rock beats Scissors
|
||
- Scissors beats Paper
|
||
- Paper beats Rock
|
||
All scoring and predictions apply deterministically without randomness.
|
||
|
||
A **random seed** is used only for reproducibility during environment reset (e.g., for deciding initial starting player or generating tournament metadata). Given the same seed, the entire match sequence will replay exactly.
|
||
|
||
---
|
||
|
||
## 4. Action Grammar (Machine‑Parsable)
|
||
|
||
### 4.1 Allowed Action Tokens
|
||
|
||
| Action Type | Token Format | Semantic Meaning |
|
||
|--------------|---------------|------------------|
|
||
| Play Sign | `[Play:Rock]`, `[Play:Paper]`, `[Play:Scissors]` | Commit to a sign |
|
||
| Predict | `[Predict:Rock]`, `[Predict:Paper]`, `[Predict:Scissors]` | Attempt to forecast opponent’s next Play sign |
|
||
| Concede | `[Concede]` | Forfeit the match immediately |
|
||
|
||
### 4.2 Formal Grammar
|
||
|
||
Regular expressions (expressed textually):
|
||
|
||
```
|
||
PLAY_TOKEN = r'^\[Play:(Rock|Paper|Scissors)\]$'
|
||
PREDICT_TOKEN = r'^\[Predict:(Rock|Paper|Scissors)\]$'
|
||
CONCEDE_TOKEN = r'^\[Concede\]$'
|
||
```
|
||
|
||
**Valid examples:**
|
||
|
||
- ✔ `[Play:Rock]` → valid play
|
||
- ✔ `[Predict:Paper]` → valid prediction
|
||
|
||
**Invalid examples:**
|
||
|
||
- ❌ `[Play: Stones]` → invalid sign (unrecognized subtype)
|
||
- ❌ `[PredictPaper]` → missing colon and brackets, invalid format
|
||
- ❌ `[yield]` → token not in allowed action set
|
||
|
||
---
|
||
|
||
## 5. Game State Schema
|
||
|
||
```json
|
||
{
|
||
"tournament_name": "Grand Duels 2077",
|
||
"seed": 123,
|
||
"round_index": 3,
|
||
"max_rounds": 5,
|
||
"turn_order": ["PlayerA", "PlayerB"],
|
||
"players": {
|
||
"PlayerA": {
|
||
"score": 5,
|
||
"last_action": "[Play:Rock]",
|
||
"predicted_action": "[Predict:Paper]",
|
||
"round_wins": 2
|
||
},
|
||
"PlayerB": {
|
||
"score": 4,
|
||
"last_action": "[Play:Scissors]",
|
||
"predicted_action": null,
|
||
"round_wins": 1
|
||
}
|
||
},
|
||
"round_history": [
|
||
{
|
||
"round": 1,
|
||
"PlayerA_action": "[Play:Rock]",
|
||
"PlayerB_action": "[Play:Paper]",
|
||
"winner": "PlayerB"
|
||
},
|
||
{
|
||
"round": 2,
|
||
"PlayerA_action": "[Predict:Scissors]",
|
||
"PlayerB_action": "[Play:Scissors]",
|
||
"winner": "Draw"
|
||
}
|
||
],
|
||
"current_turn": "PlayerB",
|
||
"status": "active",
|
||
"winner": null,
|
||
"observation_log": [
|
||
"Round 1: PlayerA played Rock; PlayerB played Paper → PlayerB wins.",
|
||
"Round 2: PlayerA predicted Scissors correctly."
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Initialization Rules
|
||
|
||
- **Seed**: A reproducible integer input for deterministic setup.
|
||
- **Starting Player**: Chooses first mover by fixed or seeded rule (e.g., even seed → PlayerA starts).
|
||
- **Scores & History**: Zeroed at start.
|
||
- **Observations:** Each player receives an opening message:
|
||
- Tournament title
|
||
- Number of rounds
|
||
- Their player role (A or B)
|
||
- Reminder of available actions and scoring system.
|
||
|
||
---
|
||
|
||
## 7. Validation and Error Handling
|
||
|
||
When an action is received (content extracted from inside `\boxed{}`):
|
||
|
||
**Validation Steps:**
|
||
1. Confirm the format matches one of the regex tokens.
|
||
2. Confirm it’s the player’s turn.
|
||
3. Ensure they haven’t already played a `[Play:*]` or `[Predict:*]` in this round (disallow duplicates).
|
||
4. If `[Concede]`, mark immediate terminal outcome.
|
||
|
||
**Invalid Move Reasons:**
|
||
- “Unrecognized token format.”
|
||
- “It is not your turn.”
|
||
- “Duplicate action this round.”
|
||
- “Concession not allowed after round resolution.”
|
||
|
||
If invalid, `set_invalid_move(player, reason)` will be triggered and the opponent **automatically wins** the match.
|
||
|
||
---
|
||
|
||
## 8. Terminal Conditions and Scoring
|
||
|
||
**Terminal checks per turn:**
|
||
1. If both players have legal `[Play:*]` actions, resolve round outcome:
|
||
- Update scores
|
||
- Record to `round_history`
|
||
- Increment `round_index`
|
||
2. If `[Concede]` action is made → opponent receives **instant win**
|
||
3. If `round_index > max_rounds` → tournament ends
|
||
|
||
**Endgame Scoring:**
|
||
- `winner = player with higher score`
|
||
- if equal → `"Draw"`
|
||
|
||
**Tie‑breakers (if desired extension):**
|
||
If tied, compare number of individual round wins; if still tied, declare draw.
|
||
|
||
---
|
||
|
||
## 9. Player Prompt Specification
|
||
|
||
**Prompt Identity Blurb:**
|
||
> You are a Signmaster in the grand arena of *Duel of Signs.* Each round, you must choose a hand sign to defeat your opponent or attempt a daring prediction for extra points.
|
||
|
||
**Prompt Contents:**
|
||
- Current round, scores, and last known actions.
|
||
- Reminder of valid action format and consequences.
|
||
- Scoring recap.
|
||
- End instruction:
|
||
“Put your final answer within `\boxed{}` at the end of your response.”
|
||
|
||
**Allowed Actions:**
|
||
```
|
||
[Play:Rock]
|
||
[Play:Paper]
|
||
[Play:Scissors]
|
||
[Predict:Rock]
|
||
[Predict:Paper]
|
||
[Predict:Scissors]
|
||
[Concede]
|
||
```
|
||
|
||
**Example Valid Response:**
|
||
```
|
||
I think Paper will protect me from Rock.
|
||
\boxed{[Play:Paper]}
|
||
```
|
||
|
||
**Example Invalid Response:**
|
||
```
|
||
I choose to play paper.
|
||
\boxed{PlayPaper}
|
||
```
|
||
→ invalid because brackets and colon missing.
|
||
|
||
**Helper extraction rule:**
|
||
`\_extract_answer_content(self, action: str) -> str`
|
||
Parses text inside `\boxed{}` and returns only the internal token string for validation and step logic.
|
||
|
||
---
|
||
|
||
## 10. API Mapping Plan
|
||
|
||
| API Method | Purpose | Reads / Writes | Outcome |
|
||
|-------------|----------|----------------|----------|
|
||
| **reset(seed=None)** | Initialize tournament state using provided or default seed. Create base observations and metadata. | Writes: `seed`, `tournament_name`, `round_index=1`, `players` fields. | Returns initial observation to both players. |
|
||
| **step(player_action)** | Process one player’s turn. Validate syntax and legality. Update game state accordingly. If round complete, compute duel result. | Reads: `current_turn`, `players[...]`, `round_history`. Writes: `scores`, `round_index`, `winner`, `status`. | Returns new observations, and signals win/draw when terminal. |
|
||
| **_generate_player_prompt(player_id)** | Builds contextual textual prompt per player at their turn. Displays current scores, allowed tokens, round state, and format examples. | Reads: full `game_state`. | Returns formatted text prompt for model or user. |
|
||
|
||
---
|
||
|
||
## 11. Copy‑Check Against the Example
|
||
|
||
- **Theme & Objective:** Completely distinct — ceremonial hand‑sign duels rather than negotiation or trading.
|
||
- **Entities & Resources:** Signs, rounds, scores; no goods, offers, or currencies.
|
||
- **Prompt Text:** Focused on symbolic combat, prediction bonuses, and deterministic scoring.
|
||
- **Game State Keys:** (`tournament_name`, `round_index`, `round_history`, `predicted_action`, `round_wins`, etc.) — all unique to this design.
|
||
|
||
---
|
||
|
||
**End of “Duel of Signs” Game Design Document** |