Files
AnotherReplayReader/docs/adr/0002-structured-game-knowledge.md
T
2026-08-22 00:41:17 +02:00

7.2 KiB

ADR 0002: Structured Game Knowledge for Prompt and Validation

⚠️ 已归档(2026-08-21):本文是历史决策记录,其设想与当前实现存在差异;当前实现以代码和 PLAN_ai_analysis_v2.md 为准,正文不再更新。

Date: 2026-07-07

Status

Accepted

Context

Game knowledge — unit capabilities, faction rules, map geometry, build restrictions, and known exceptions — currently lives in two unconnected places:

  1. Prompt text inside AIAnalyze.BuildDefaultSystemPrompt() as large hardcoded strings with [MOD:] conditional tags.
  2. Validation rules inside AIAnalysisValidation.cs as hardcoded string matching (e.g., claimLooksLikeBuilder checks for "MCV", "基地车", "Nanocore", etc.).

This causes several problems:

  • Prompt knowledge and validation knowledge are not synchronized. Adding a new unit type requires editing both the prompt text and the validation code.
  • Users can only override the entire system prompt or append text. There is no way to add or correct a single unit fact without replacing the whole prompt.
  • Validation rules use fragile substring matching against natural-language Chinese text, which will drift as the prompt text changes.
  • There is no reusable data structure that both prompt rendering and validation logic can query.

We need a unified knowledge architecture that:

  • Serves as the single source of truth for both prompt rendering and deterministic validation.
  • Lets users add map-, faction-, or mod-specific knowledge without editing code.
  • Replaces hardcoded substring matching in validation with tag-based queries.
  • Preserves the built-in game knowledge as the default for each supported mod.

Decision

Knowledge Set structure

Game knowledge is organized into KnowledgeSets, each keyed by mod name (e.g., "default" for base game, "corona" for the Corona mod). Each set is self-contained and complete — there is no cross-set inheritance or conditional inclusion. The mod name from the replay directly selects which set to load, replacing the current [MOD:] inline tag system entirely.

Each KnowledgeSet is a hierarchy where scope is inherited from the path, not stored in entries:

KnowledgeSet (e.g. "default")
├── global/                    ← applies to all factions and maps
│   ├── entries...
├── factions/
│   ├── 盟军/
│   │   ├── entries...         ← scope = faction:盟军
│   ├── 神州/
│   │   ├── entries...
├── maps/
│   ├── map_mp_2_rao1/
│       ├── entries...         ← scope = map:map_mp_2_rao1

Mod knowledge vs base game: Since a mod is a self-contained game version, its KnowledgeSet is a complete copy of the relevant knowledge, not a diff. This avoids the complexity of conditional tags ([MOD:] / [MOD:NO:]) — users editing a mod's knowledge JSON see only that mod's entries without conditional logic. The current [MOD:] inline text approach is retired; knowledge sets are now purely data-driven.

KnowledgeEntry format

Every knowledge entry has the same structure whether it is built-in or user-supplied:

id: string                  # unique identifier within the knowledge set
tags: string[]              # from the predefined tag taxonomy (see below)
text: string                # markdown description, used for prompt rendering

Tag taxonomy (finite, predefined)

Tags serve as the bridge between prompt knowledge and validation logic. Validation rules query entries by tag instead of matching strings.

Capability tags (what a unit can do): builder, pack, unpack, amphibious, transport, returnToProducer, cloak, toggleWeapon

Type tags (what a unit is): infantry, vehicle, aircraft, naval, structure, hero, production, defense, superweapon

Combat role tags (what a unit fights): antiInfantry, antiVehicle, antiStructure, antiAir, antiNaval

Special power references (links to observable replay data): specialPower:PackReplaceSelf, specialPower:UnpackReplaceSelf, etc.

Prompt rendering

The built-in BuildDefaultSystemPrompt() is refactored to render from the knowledge set in this order:

  1. Global entries
  2. Faction-specific entries for each player's faction (in player order)
  3. Map-specific entries for the current map

User customizations still apply as layers on top:

  • AdditionalRules is appended at the end of the rendered prompt.
  • UseCustomSystemPrompt completely replaces the default (as before).

User extensibility

Users can add or overlay knowledge entries via a JSON file (e.g., AnotherReplayReader.user_knowledge.json) stored alongside the settings file. The file follows the same KnowledgeSet structure; entries with matching id values override built-in entries.

Validation consumption

Validation rules (AIAnalysisValidation.cs) are refactored to:

  • Load the active knowledge set and query entries by tag (e.g., entries.WithTag("builder")) instead of matching hardcoded substrings.
  • Use specialPower:* tags to verify power-to-unit-type inferences.
  • Keep deterministic rules (e.g., ValidateUnpackAmbiguity) as code, but drive what entries they check from tags rather than hardcoded asset names.

Storage format

JSON container with text fields as markdown. Example:

{
  "global": {
    "entries": [
      {
        "id": "general-rules",
        "tags": ["rule"],
        "text": "## 核心原则\n- ..."
      }
    ]
  },
  "factions": {
    "盟军": {
      "entries": [
        {
          "id": "AlliedMCV",
          "tags": ["builder", "vehicle", "amphibious", "pack", "unpack"],
          "text": "### 基地车(AlliedMCV)\n盟军基地车,两栖,...\n可以在陆地或水上展开为主基地。"
        }
      ]
    }
  }
}

Consequences

  • Positive: Prompt knowledge and validation knowledge share a single source of truth.
  • Positive: Users can add or correct game knowledge facts without modifying code.
  • Positive: Validation no longer depends on fragile Chinese substring matching — tag queries are deterministic and language-independent.
  • Positive: New mods (e.g., "corona") get their own KnowledgeSet without polluting the default.
  • Negative: Requires migration of ~700 lines of hardcoded prompt text into KnowledgeEntry records — a significant one-time refactoring effort.
  • Negative: The tag taxonomy must be maintained as the game or mod evolves. Additions must be reviewed to prevent tag proliferation.
  • Negative: JSON file editing is less user-friendly than a dedicated settings UI (acceptable as an initial step; the AiPromptSettings text fields remain available as a simpler escape hatch).

Implementation Status

Not yet implemented. The following migration path is planned:

  1. Define C# records (KnowledgeSet, KnowledgeEntry, KnowledgeTag constants) in a new Utils/AiKnowledge.cs file.
  2. Create the built-in KnowledgeSet by extracting data from the current BuildDefaultSystemPrompt() strings into structured entries with tags.
  3. Wire the knowledge set through GetSystemPrompt() so it renders entries in the correct order.
  4. Refactor AIAnalysisValidation.ValidateTimelineConsistency() to query the knowledge set by tag instead of hardcoded matching.
  5. Add user knowledge file loading in AiSettings.Load().