8.3 KiB
Turn-Based TextArena Environment Design Document
1. Concept Paragraph
Game Title: Crown of Fools
In Crown of Fools, two rival jesters compete in a royal card challenge, vying to assemble the most powerful hand before the court’s patience expires. The deck includes number cards (1–10), special Trick cards (that can reverse or multiply values), and the single Crown Joker, a wildcard that can turn a weak hand into a masterpiece. Players take turns drawing, playing, or discarding cards to manipulate their hand values strategically. The game is unrelated to any negotiation or trading simulation example; instead, it is a whimsical, competitive card duel focused on tactical card management and risk. The core action tokens revolve around [Draw], [Play:<card_id>], [Discard:<card_id>], and [Pass].
2. Roles and Win Condition
-
Players:
Two jesters: Player A (Jester Red) and Player B (Jester Blue). -
Objective:
Each jester seeks to achieve the highest total hand value when the deck runs out, or when a jester declares “Crown” (their confidence in having the superior hand). -
Win Condition:
- If a player declares
[Crown], both hands are revealed:- The player with the greater total hand value wins.
- If the totals are equal, the one holding the Crown Joker wins.
- If neither holds the Joker, the game is a draw.
- If the deck depletes naturally (both run out of possible draws), scores are calculated automatically using the same rule.
- If a player declares
3. Turn Structure and Determinism
- Turns alternate strictly: Player A → Player B → Player A → …
- Each turn consists of one valid action.
- The game ends immediately once a terminal condition (deck empty or
[Crown]declaration) is met. - Maximum of 30 turns (combined), after which an automatic scoring occurs.
- A pseudo-random seed initializes deck order; same seed ensures deterministic reproducibility for all runs.
4. Action Grammar (Machine-Parseable)
Allowed player actions (contents within \boxed{{}}):
| Action Token | Format | Description |
|---|---|---|
| Draw card | [Draw] |
Take top card from the deck into hand |
| Play card | [Play:<card_id>] |
Use a card’s effect (must exist in hand) |
| Discard card | [Discard:<card_id>] |
Remove a card from hand to discard pile |
| Pass | [Pass] |
Skip a turn (no effect) |
| Declare crown | [Crown] |
End the round and reveal hands |
Validation Examples:
-
Valid:
[Draw]– Correct token.
Invalid:[DrawCard]– Not a recognized keyword. -
Valid:
[Play:Trick_7]– Matches held card label pattern.
Invalid:[Play7]– Missing colon and invalid syntax. -
Valid:
[Discard:Num_3]– Legal ifNum_3in hand.
Invalid:[Discard:Joker]– Joker cannot be voluntarily discarded. -
Valid:
[Pass]– Legal at any time.
Invalid:[Pause]– Keyword not permitted. -
Valid:
[Crown]– Legal action any time after turn 5.
Invalid:[CrownNow]– Not a recognized pattern.
Formal Regular Expressions:
^\[Draw\]$^\[Play:[A-Za-z0-9_]+\]$^\[Discard:[A-Za-z0-9_]+\]$^\[Pass\]$^\[Crown\]$
5. Game State Schema
Example runtime schema:
{
"phase": "active",
"turn_index": 7,
"current_player": "A",
"deck_order": ["Num_9", "Num_2", "Trick_1", "Crown_Joker", "Num_8", "Trick_3"],
"discard_pile": ["Num_5"],
"players": {
"A": {
"hand": ["Num_1", "Num_4", "Trick_2"],
"score": 7,
"has_joker": false,
"last_action": "[Play:Trick_2]"
},
"B": {
"hand": ["Num_6", "Crown_Joker"],
"score": 16,
"has_joker": true,
"last_action": "[Draw]"
}
},
"history": [
{"player": "A", "action": "[Draw]"},
{"player": "B", "action": "[Play:Num_3]"}
],
"seed": 20240506,
"terminal": false,
"winner": null
}
6. Initialization Rules
- Deck Composition:
- Number cards:
Num_1–Num_10, each duplicated twice. - Trick cards:
Trick_1–Trick_5. - One
Crown_Joker.
Total = 26 cards.
- Number cards:
- Initial Hands: Each player draws 3 cards from the shuffled deck.
- Seed Control:
A provided or default integer seed initializes the deterministic shuffle. - Onboarding Observation:
Introduces theme, player roles, and first 3 cards each player holds.
7. Validation and Error Handling
When validating extracted action content:
- Unrecognized pattern:
→set_invalid_move("Unrecognized action format") - Invalid card reference:
→set_invalid_move("Card not in hand") - Prohibited discard of Joker:
→set_invalid_move("Cannot discard the Crown Joker") - Premature ‘Crown’ declaration (before turn 5):
→set_invalid_move("Crown can only be declared after turn 5") - Deck empty when trying to draw:
→set_invalid_move("Deck empty; cannot draw")
Each invalid move triggers an immediate loss for the acting player (to discourage random token submissions).
8. Terminal Conditions and Scoring
Terminal checks each turn:
[Crown]declared → reveal both hands.- Deck exhausted → automatic reveal.
- Turn counter ≥ 30 → automatic reveal.
Scoring rule:
- Each
Num_Xvalue contributes its digit. - Each
Trick_Xdoubles another card of the same digit value. - The
Crown_Jokeradds +5 to total and breaks ties.
Decision:
- Highest total wins; ties broken by possession of Joker; otherwise draw.
9. Player Prompt Specification
Prompt Outline
Identity Blurb:
You are a jester in the royal court, dueling your rival by drawing and playing cards to earn the court’s applause. Gather the highest hand value before your opponent declares “Crown”!
Action Instructions:
You must select exactly one action each turn using the bracketed tokens below:
[Draw]– take the top card from the deck[Play:<card_id>]– apply a card’s effect[Discard:<card_id>]– remove a unwanted card (not Joker)[Pass]– skip[Crown]– declare your confidence and end the round
Put your final answer within
\boxed{{}}at the end of your response.
Example valid response:
I need to strengthen my hand first.
\boxed{{[Draw]}}
Example invalid response:
I choose DrawCard.
\boxed{{[DrawCard]}}
Implementation Helper:
_extract_answer_content(self, action: str) -> strmust extract only the contents within\boxed{{}}.
Players are encouraged to include reasoning before their boxed token, but only the token itself is parsed as the action command.
10. API Mapping Plan
| API Method | Purpose | Reads/Writes | Terminal Logic |
|---|---|---|---|
| reset(seed) | Initializes deck using deterministic shuffle; deals hands; resets counters and history. | Writes entire game_state. |
Sets terminal=false, winner=null. |
| step(player_action) | Extracts boxed contents, validates grammar and legality, executes turn effects. | Reads: current_player, hands, deck. Writes: history, hands, discard_pile, turn_index. |
After action, checks terminal conditions; sets winner or marks draw. |
| _generate_player_prompt() | Builds a textual observation containing: current turn, visible discard pile top, hand summary, and rules. | Reads: game_state; may embed last few transcript lines. |
None; just generates prompt text. |
11. Copy-check Against the Example
This design is completely original and not derived from any negotiation or trading scenario.
- Theme: whimsical court card duel.
- Resources: cards (numbers, tricks, joker), not goods or proposals.
- Objectives: achieve high hand value, not mutual agreement.
- State Keys: e.g.,
"deck_order","discard_pile","has_joker"— all unique to this design. - Prompt and grammar: completely new and unrelated to negotiation format.
This document therefore satisfies the independence, determinism, and structural clarity required for future TextArena implementation.