From 82c464e31e6d031d511f2b85451f8b1126c7ccd8 Mon Sep 17 00:00:00 2001 From: Natalie Date: Sun, 17 May 2026 03:45:07 -0700 Subject: [PATCH] =?UTF-8?q?docs(@projects/@magic-civilization):=20?= =?UTF-8?q?=E2=9C=A8=20update=20player=20api=20docs=20to=20reflect=20gener?= =?UTF-8?q?alised=20naming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- src/game/engine/docs/PLAYER_API.md | 29 ++++++++++++++----- .../crates/mc-player-api/src/action.rs | 2 +- .../crates/mc-player-api/src/dispatch.rs | 4 +-- src/simulator/crates/mc-player-api/src/lib.rs | 2 +- .../crates/mc-player-api/src/wire.rs | 2 +- .../crates/mc-player-api/tests/common/mod.rs | 2 +- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/game/engine/docs/PLAYER_API.md b/src/game/engine/docs/PLAYER_API.md index dd79ed6d..2b64f071 100644 --- a/src/game/engine/docs/PLAYER_API.md +++ b/src/game/engine/docs/PLAYER_API.md @@ -1,17 +1,32 @@ -# Claude Player API +# Player API -**Status:** Phase 0 design draft, p2-67. +**Status:** Production (originally landed as "Claude Player API" in p2-67; +generalised 2026-05-17 — naming dropped the Claude-specific framing once +the protocol turned out to be useful for OpenSpiel / RL adapters and +shell smoke tests). **Owner:** simulator-infra. **Wire:** JSON-Lines over stdin/stdout (one JSON value per line, `\n` terminator). **Encoding:** UTF-8 strict, no BOM, no trailing whitespace. ## Purpose -Let a Claude Agent SDK process play one slot of a Magic Civilization game while -the production AI plays the others. Every action Claude takes maps 1-to-1 to a -button or interaction the human UI exposes — no privileged shortcuts, no -direct `GameState` mutation. Game state is read via a **fog-aware -projection** so Claude only sees what the player it's bound to could see. +Let *any external client* play one slot of a Magic Civilization game while +the production AI plays the others. Every action the client takes maps +1-to-1 to a button or interaction the human UI exposes — no privileged +shortcuts, no direct `GameState` mutation. Game state is read via a +**fog-aware projection** so the client only sees what the player it's +bound to could see. + +Known consumers today: + +- `tooling/claude-player-mcp/` — Claude-Code MCP transport. +- `scripts/player-api-example.py` — plain Python reference client. +- `scripts/claude-smoke-5endturn.sh`, `scripts/claude-demo-25turn.sh` — + shell smoke / demo drivers (raw JSON-Lines). + +A future OpenSpiel / RL trainer adapter (cf. `p2-67-followup-rl-self-play`) +would `subprocess.Popen` the same harness and treat each `view` → +`legal_actions` → `act` cycle as one step in its training loop. ## Wire protocol diff --git a/src/simulator/crates/mc-player-api/src/action.rs b/src/simulator/crates/mc-player-api/src/action.rs index d92a57d6..db94cf64 100644 --- a/src/simulator/crates/mc-player-api/src/action.rs +++ b/src/simulator/crates/mc-player-api/src/action.rs @@ -136,7 +136,7 @@ pub enum BuildingActionPayload { } /// Every UI-equivalent action the player can take. Wire format is -/// `{"type":"", ...}` — see `CLAUDE_PLAYER_API.md` for the +/// `{"type":"", ...}` — see `PLAYER_API.md` for the /// complete schema. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "snake_case")] diff --git a/src/simulator/crates/mc-player-api/src/dispatch.rs b/src/simulator/crates/mc-player-api/src/dispatch.rs index d7867db3..c5056d5e 100644 --- a/src/simulator/crates/mc-player-api/src/dispatch.rs +++ b/src/simulator/crates/mc-player-api/src/dispatch.rs @@ -214,7 +214,7 @@ pub fn apply_action( // bench-cheat: every Offer immediately signs the agreement // (instant-sign), and Accept/Reject are no-op acknowledgements. // The honest contract is documented in - // `docs/CLAUDE_PLAYER_API.md` once Phase 8 doc updates land. + // `docs/PLAYER_API.md` once Phase 8 doc updates land. PlayerAction::OfferOpenBorders { to } => apply_offer_open_borders(state, player, *to), PlayerAction::AcceptOpenBorders { from: _ } | PlayerAction::RejectOpenBorders { from: _ } @@ -1242,7 +1242,7 @@ fn apply_offer_open_borders( }); } let pair = if from < to { (from, to) } else { (to, from) }; - // Bench-cheat (documented in CLAUDE_PLAYER_API.md): the + // Bench-cheat (documented in PLAYER_API.md): the // counterparty AI doesn't yet model offer acceptance, so Offer // signs immediately. Real protocol with pending-offer staging // is a Phase 11+ follow-up. diff --git a/src/simulator/crates/mc-player-api/src/lib.rs b/src/simulator/crates/mc-player-api/src/lib.rs index 95f10066..26c4f77d 100644 --- a/src/simulator/crates/mc-player-api/src/lib.rs +++ b/src/simulator/crates/mc-player-api/src/lib.rs @@ -11,7 +11,7 @@ //! follow-up tasks of p2-67 Phase 1; both are tracked there. Until those //! modules land this crate is a pure types crate — no behaviour, no I/O. //! -//! See `src/game/engine/docs/CLAUDE_PLAYER_API.md` for the full spec. +//! See `src/game/engine/docs/PLAYER_API.md` for the full spec. #![warn(missing_docs)] #![allow(clippy::module_name_repetitions)] diff --git a/src/simulator/crates/mc-player-api/src/wire.rs b/src/simulator/crates/mc-player-api/src/wire.rs index 9f75de91..3d36412e 100644 --- a/src/simulator/crates/mc-player-api/src/wire.rs +++ b/src/simulator/crates/mc-player-api/src/wire.rs @@ -1,5 +1,5 @@ //! Wire envelopes for the JSON-Lines protocol described in -//! `src/game/engine/docs/CLAUDE_PLAYER_API.md`. +//! `src/game/engine/docs/PLAYER_API.md`. //! //! - [`Request`] — adapter → harness (`view`, `act`, `shutdown`). //! - [`Response`] — harness → adapter (success: events + view; failure: error). diff --git a/src/simulator/crates/mc-player-api/tests/common/mod.rs b/src/simulator/crates/mc-player-api/tests/common/mod.rs index 41280f5b..fb12508a 100644 --- a/src/simulator/crates/mc-player-api/tests/common/mod.rs +++ b/src/simulator/crates/mc-player-api/tests/common/mod.rs @@ -199,7 +199,7 @@ pub fn build_building_catalog() -> Vec { } /// Runtime `UnitsCatalog` literal — id → `UnitStats`. Mirrors what -/// `claude_player_main.gd::_apply_runtime_units_catalog` harvests from +/// `player_api_main.gd::_apply_runtime_units_catalog` harvests from /// `public/resources/units/*.json` (the `movement` field maps to /// `UnitStats::base_moves`). pub fn build_runtime_units_catalog() -> UnitsCatalog {