docs(objectives-specific): 📝 Update P2 milestone documentation for data resources, unit audio cues, and chronicle hall unlocks with detailed descriptions and implementation notes
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
876a7de3a2
commit
9990986720
3 changed files with 193 additions and 0 deletions
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
id: p2-36
|
||||
title: Reconcile the 14 building IDs defined in both `resources/buildings/` and `data/buildings/`
|
||||
priority: p2
|
||||
status: partial
|
||||
scope: game1
|
||||
updated_at: 2026-04-27
|
||||
evidence:
|
||||
- public/resources/buildings/ (6 wonder per-file dupes deleted: clan_moot_stone, covenant_stone, grand_observatory, hall_of_ancestors, voice_of_ages, world_pillar)
|
||||
- public/games/age-of-dwarves/data/buildings/mundane_wonders.json (canonical wonder ladder, unchanged)
|
||||
- public/games/age-of-dwarves/data/buildings/manifest.json (regenerated: 102 IDs, was 108)
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
After the `p1-31` per-file split, 14 building IDs are defined in **both** `public/resources/buildings/<id>.json` (engine defaults) and `public/games/age-of-dwarves/data/buildings/<...>.json` (Age-of-Dwarves overrides). The data loader iterates `resources/` first then `data/` and overwrites by id — the data/ definition silently wins. Every duplicate currently differs in `cost`, `tech_required`, or `tier`, so the resources/ side is dead code wherever the override exists.
|
||||
|
||||
| ID | resources/ definition | data/ definition (wins) | Drift |
|
||||
|---|---|---|---|
|
||||
| `barracks` | cost=80, tech=military_doctrine, tier=1 | cost=50, tech=null, tier=1 | tech gate dropped |
|
||||
| `forge` | cost=100, tech=smelting, tier=2 | cost=60, tech=null, tier=1 | tech gate dropped, tier dropped |
|
||||
| `granary` | cost=60, tech=husbandry, tier=1 | cost=30, tech=null, tier=1 (in stub.json) | tech gate dropped |
|
||||
| `library` | cost=75, tech=scholarship, tier=1 | cost=60, tech=null, tier=1 | tech gate dropped |
|
||||
| `monument` | cost=40, tech=null, tier=1 | cost=30, tech=null, tier=1 | cost only |
|
||||
| `siege_workshop` | cost=120, tech=mathematics, tier=2 | cost=80, tech=siege_craft, tier=2 | different tech |
|
||||
| `temple` | cost=90, tech=ancestor_rites, tier=2 | cost=80, tech=null, tier=2 | tech gate dropped |
|
||||
| `walls` | cost=75, tech=masonry, tier=1 | cost=70, tech=null, tier=1 | tech gate dropped |
|
||||
| `clan_moot_stone` (wonder) | cost=80, tier=1 | cost=180, tier=2 (in mundane_wonders.json) | wonder cost/tier diverged |
|
||||
| `covenant_stone` (wonder) | cost=355, tier=4 | cost=600, tier=6 | wonder cost/tier diverged |
|
||||
| `grand_observatory` (wonder) | cost=220, tech=astronomy, tier=5 | cost=600, tech=astronomy, tier=6 | wonder cost/tier diverged |
|
||||
| `hall_of_ancestors` (wonder) | cost=360, tier=4 | cost=260, tier=3 | wonder cost/tier diverged |
|
||||
| `voice_of_ages` (wonder) | cost=780, tier=10 | cost=1200, tier=10 | wonder cost diverged |
|
||||
| `world_pillar` (wonder) | cost=540, tier=7 | cost=1040, tech=world_theory, tier=9 | wonder cost/tech/tier diverged |
|
||||
|
||||
The pattern is clear:
|
||||
- **Ordinary buildings (8)**: `data/` versions are cheaper and drop the tech gate. Likely a deliberate Age-of-Dwarves "always-buildable starter" simplification.
|
||||
- **Wonders (6)**: `data/buildings/mundane_wonders.json` versions are heavier-cost / higher-tier, suggesting `mundane_wonders.json` is the actual Game 1 wonder ladder and the per-file `resources/` versions are stale legacy entries.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ✓ Wonder duplicates resolved (6 of 14): `mundane_wonders.json` chosen as canonical per p0-04 evidence (`PlayerState.wonders_built` and `WonderId` keys come from this file). The per-file `resources/buildings/{clan_moot_stone,covenant_stone,grand_observatory,hall_of_ancestors,voice_of_ages,world_pillar}.json` deleted as dead overrides — confirmed zero source-code references to the per-file paths (only string-id lookups exist, and the IDs still resolve via `mundane_wonders.json`).
|
||||
- ✗ Ordinary-building duplicates remain (8 of 14): `barracks`, `forge`, `granary`, `library`, `monument`, `siege_workshop`, `temple`, `walls`. For each, the data/ version drops the tech gate and lowers cost vs the resources/ version. Needs design call: are the data/ overrides intentional Game-1 simplification (delete resources/), or stale drift (delete data/ overrides and accept the deeper tech-gated economy)?
|
||||
- ✗ All 14 duplicates removed: post-fix audit shows zero IDs defined in both layers. (8 remaining.)
|
||||
- ✓ For wonders specifically: bundled `data/buildings/mundane_wonders.json` pattern won — it's the canonical wonder ladder per p0-04. Per-file resources/ wonders deleted. (Note: this leaves the wonder system on a different convention from p1-31's per-file building pattern, by design — wonders are a coherent ladder edited as a unit.)
|
||||
- ✗ Game 1 balance untouched unless explicitly intended: post-wonder-cleanup balance is unchanged because the data/ side already won at runtime. The 8 remaining ordinary-building dupes will need balance review when reconciled.
|
||||
- ✓ `python3 tools/validate-game-data.py` passes 0 failures post-wonder-delete: PASSED 317 / FAILED 0.
|
||||
- ✗ A 10-seed `tools/autoplay-batch.sh 10 300` regression batch shows no mass behaviour shift after the remaining 8 ordinary-building dupes are reconciled.
|
||||
- ✗ `data/buildings/stub.json` audit: defines `granary` as a "compatibility stub" with cost=30 (vs `resources/buildings/granary.json` cost=60 with `tech=husbandry`). Decide if stub.json belongs at all post-reconciliation — it likely becomes redundant once `granary` is reconciled.
|
||||
|
||||
## Progress note (2026-04-27)
|
||||
|
||||
Wonder phase completed autonomously: all 6 wonder duplicates collapsed onto `mundane_wonders.json`. The remaining 8 ordinary-building duplicates each represent a design call (sparse Game-1-friendly override vs richer engine-default with tech gate) and are deferred until that call is made.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Authoring new buildings (covered by `p1-32` and other authoring objectives).
|
||||
- Mechanic changes to wonders (e.g. wonder slot limits) — value-only reconciliation here.
|
||||
- The `data/units/stub.json` parallel issue (founder compatibility id) — file as a separate audit if it shows similar drift.
|
||||
77
.project/objectives/p2-38-unit-audio-cues-stubs.md
Normal file
77
.project/objectives/p2-38-unit-audio-cues-stubs.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
id: p2-38
|
||||
title: "Unit audio_cues stub strings — selection/move/attack lines for the dwarven roster"
|
||||
priority: p2
|
||||
status: done
|
||||
scope: game1
|
||||
owner: asset-audio
|
||||
updated_at: 2026-04-27
|
||||
assigned_by: shipwright
|
||||
blockedBy: [p1-34]
|
||||
evidence:
|
||||
- "56 unit JSONs in public/games/age-of-dwarves/data/units/ have audio_cues field with select (3 lines), move (2), attack (2), death (1) string arrays. Verified: `grep -c '\"audio_cues\":' *.json | grep -c ':1$'` = 56."
|
||||
- "Voice differentiation per archetype confirmed via QA samples: Berserker shouts single-word rage ('BLOOD!', 'AXE-WORK!'); Shield Bearer terse declaratives ('Hold.', 'We become the place.'); Marksman runic references ('The runes agree with me.', 'THEY AGREE!'); War Ram contract metaphor ('Horns are the contract.', 'CONTRACT HONORED!'); Mountain King ancestral weight ('Ten thousand names on this plate.', 'FOR THE TEN THOUSAND!')"
|
||||
- "All 56 files: valid JSON, no intra-unit duplicate lines, lines 2-8 words each"
|
||||
- "No magic / Game 2/3 lore leaks. Dwarven idiom maintained across all units."
|
||||
- "p1-35 (lore) + p2-36 (audio_cues) ran in parallel against the same 56 files using targeted Edits with unique anchors — no conflicts surfaced."
|
||||
- "React build verification: pnpm --prefix .project/designs/app run build exits 0 (164 modules, 464KB bundle)"
|
||||
remaining_work:
|
||||
- "Actual .ogg audio file generation remains in asset-audio team's p2-16 audio pack pipeline. This objective shipped string content only; voice acting / TTS-generation downstream."
|
||||
---
|
||||
## Summary
|
||||
|
||||
The 50-unit dwarven roster needs in-character audio cue strings — the
|
||||
one-liner that plays when a unit is selected, told to move, or ordered
|
||||
to attack. AoE/Civ/StarCraft conventions: 2–4 lines per cue type, played
|
||||
randomly so repetition doesn't drone.
|
||||
|
||||
This objective lands the **string content** only. Voice acting and audio
|
||||
file generation are downstream (asset-audio team's existing p2-16 audio
|
||||
pack work). The `audio_cues` field unblocks the audio team to know what
|
||||
lines to record / TTS-generate.
|
||||
|
||||
Each unit gets:
|
||||
```json
|
||||
"audio_cues": {
|
||||
"select": ["...", "...", "..."],
|
||||
"move": ["...", "..."],
|
||||
"attack": ["...", "..."],
|
||||
"death": ["..."]
|
||||
}
|
||||
```
|
||||
|
||||
Lines should reflect the unit's identity:
|
||||
- Berserker: "BLOOD!" / "I do not need a shield."
|
||||
- Mountain King: "The crown stands." / "Speak the names." (referring to
|
||||
ten thousand clan-name engravings)
|
||||
- EMP Trooper: "What runs on lightning..." / "Quietly."
|
||||
- Shield Bearer: "Hold." / "We become the place." / "One step. One step."
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] All 50 newly-authored dwarven military units have `audio_cues`
|
||||
field with select/move/attack/death arrays
|
||||
- [ ] Each `select` array has 3 lines, `move` has 2, `attack` has 2,
|
||||
`death` has 1
|
||||
- [ ] Lines are 2–8 words each (snappy enough for combat UI)
|
||||
- [ ] Voice matches established dwarven flavor (terse, declarative,
|
||||
mountain/iron imagery)
|
||||
- [ ] Unit-specific identity surfaces (a Berserker doesn't sound like a
|
||||
Shield Bearer)
|
||||
- [ ] No lines reference Game 2/3 lore (no magic, no spells)
|
||||
- [ ] Apex units (mountain_king, doomsoul, ancestral_walker, etc.) get
|
||||
weightier lines than T1 units
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Actual `.ogg` audio file generation (asset-audio's p2-16 / p2-33 work)
|
||||
- Voice actor casting / TTS personality picks
|
||||
- Wild creature audio cues (separate objective)
|
||||
- Existing 25-unit roster (warrior etc.) — their audio cues already
|
||||
shipped via p0-21 / p2-33
|
||||
|
||||
## Notes for implementing agent
|
||||
|
||||
The `audio_cues` field is additive and JSON-safe (string arrays).
|
||||
Reference how the tech-file flavor lines are written
|
||||
(`data/techs/dwarven_warfare.json`) for voice consistency.
|
||||
58
.project/objectives/p2-39-chronicle-hall-phantom-unlock.md
Normal file
58
.project/objectives/p2-39-chronicle-hall-phantom-unlock.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
id: p2-39
|
||||
title: Resolve `chronicle_hall` phantom unlock in `chronicle_keeping` culture tech
|
||||
priority: p2
|
||||
status: done
|
||||
scope: game1
|
||||
updated_at: 2026-04-27
|
||||
evidence:
|
||||
- public/resources/culture/oral_tradition.json (line 96 — `chronicle_keeping.unlocks.buildings = ["chronicle_hall"]`)
|
||||
- public/games/age-of-dwarves/data/buildings/mundane_wonders.json (line 102–115 — `bardic_circle`, the actual `chronicle_keeping`-gated wonder)
|
||||
- .project/objectives/p3-01-courier-diplomacy.md (cycle 3 audit that surfaced the phantom)
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The `chronicle_keeping` culture tech (era_4 oral_tradition pillar) declares
|
||||
`unlocks.buildings = ["chronicle_hall"]`, but no `chronicle_hall` building file
|
||||
exists anywhere in `public/resources/buildings/` or
|
||||
`public/games/age-of-dwarves/data/buildings/`. Surfaced by the p3-01 cycle 3
|
||||
audit when the era_4 Rune Scribe culture path tried to extend
|
||||
`chronicle_hall.enables_units` and discovered it was a phantom.
|
||||
|
||||
The actual building gated on `culture_required: "chronicle_keeping"` is
|
||||
`bardic_circle` (mundane_wonders.json:102 — tier 4, era 2 wonder). The phantom
|
||||
is a stale unlock string left over from an earlier design.
|
||||
|
||||
This is a pre-existing data integrity bug, separate from p3-01's courier scope.
|
||||
|
||||
## Resolution options
|
||||
|
||||
**Option A — point the unlock at the real building:** rewrite
|
||||
`oral_tradition.json:96` from `"chronicle_hall"` to `"bardic_circle"`. Smallest
|
||||
diff. Truthful given current data.
|
||||
|
||||
**Option B — author a real `chronicle_hall` building:** an era_4 normal (non-wonder)
|
||||
culture-tech-unlocked institution. Distinct from `bardic_circle` (wonder, tier 4).
|
||||
Bigger diff. Adds a new strategic institution and unblocks the era_4 Rune Scribe
|
||||
culture path that p3-01 abandoned.
|
||||
|
||||
**Default to Option A** unless explicitly requested otherwise. Option B becomes
|
||||
viable only if the design wants culture-side courier production at era_4, which
|
||||
is currently out of scope.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [✓] Decide A vs B (default A). Option A chosen.
|
||||
- [✓] If A: edit `public/resources/culture/oral_tradition.json:96` `"chronicle_hall"` → `"bardic_circle"`. Verify no other reference to `chronicle_hall` remains in the data tree (`grep -r chronicle_hall public/`). — Only hit in dist/guide bundle (compiled artifact, not source data).
|
||||
- [✓] `python3 tools/validate-game-data.py` → 0 failed. (317 passed, 0 failed)
|
||||
- [✓] Run dashboard regen.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Authoring or rebalancing the era_4 Rune Scribe culture path (separate scope inside p3-01 if pursued later).
|
||||
- Audit of other phantom unlocks across the culture trees (out of scope; address one at a time as discovered).
|
||||
|
||||
## Dependencies
|
||||
|
||||
- None. Pure data integrity fix.
|
||||
Loading…
Add table
Reference in a new issue