magicciv/public/resources/units/warrior.json
Natalie 2605712a61 fix(ai): 🔬 weave tech→tiered-unit production so the AI fields real armies
Follow-up to the TechWeb fix: research advanced to 109 techs but every city
still spawned tier-1 dwarf_warrior. Five stacked defects severed the
tech→unit→production chain; all are fixed here. Proven in a 599-turn duel
self-play (seed 42): slot 0 fields a 222-strong tier-8 dwarf_adamantine_champion
army; both clans now CHOOSE tier-2..8 units by tech (was tier-1 only).

1. units_catalog (#[serde(skip)]) was never stamped onto the dispatch
   GdPlayerApi — only GdGameState. The harness comment claimed 'both must be
   re-stamped at boot' but only did GdGameState. Added
   GdPlayerApi::set_units_runtime_catalog_json + a post-load harness re-stamp.
   Without it apply_queue_production/try_spawn_unit ran catalog-blind.

2. apply_queue_production classified queued ids as unit-vs-building by a
   starts_with("dwarf_") prefix. Replaced with an authoritative
   units_catalog.get() lookup (prefix kept only as empty-catalog fallback).
   The prefix leaked dwarf_-prefixed BUILDINGS (dwarf_deep_forge) onto the map
   as units and misfiled every non-dwarf unit.

3. project_tactical_player hardcoded race_id: None, filtering out every
   race_required:dwarf unit. Added PlayerState.race_id (race gates production →
   it is sim state, not pure presentation per p2-72a), stamped it in
   set_player_presentation_json + the headless harness (sourced from
   setup.json::default_race), and projected it.

4. build_unit_catalog loaded faction:"wild" monsters (ancient_hydra, …) and
   freepeople into the AI production catalog. With race_required:null they
   passed every race filter and, being high-tier, the picker preferred them.
   Excluded non-player factions from the production catalog (runtime catalog
   still carries them for encounters).

5. Generic warrior/spearmen/archer carried clan_affinity to ALL FIVE clans at
   tier 1, so clan_affinity_score=2 dominated tier and every named clan locked
   onto tier-1 'warrior'. Cleared their affinity (they are neutral baselines,
   not clan signatures).

mc-player-api 132 + mc-state 12 tests green. Known next layer (not this fix):
production VOLUME — try_spawn_unit's empty-queue dwarf_warrior auto-spawn still
floods tier-1, and the loser snowballs; the picker is correct, army composition
tuning is separate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 11:57:32 -04:00

100 lines
2.1 KiB
JSON

[
{
"id": "warrior",
"name": "Warrior",
"description": "A basic melee fighter armed with sword and shield.",
"unit_type": "melee",
"school": null,
"domain": "land",
"keywords": [],
"attributes": [
"light",
"biological"
],
"attack_type": "blade",
"hp": 80,
"attack": 14,
"defense": 8,
"ranged_attack": 0,
"range": 0,
"movement": 2,
"vision": 2,
"cost": 40,
"tier": 1,
"tech_required": null,
"upgradeable_from": null,
"race_required": null,
"faction": "dwarf",
"mana_cost": null,
"sprite": "sprites/units/warrior.png",
"gender": {
"male": {
"name": "Warrior",
"sprite": "sprites/units/warrior_dwarf_male.png"
},
"female": {
"name": "Warrior",
"sprite": "sprites/units/warrior_dwarf_female.png"
}
},
"maintenance": 2,
"auto_join": true,
"encyclopedia": {
"category": "combat",
"entry_type": "unit",
"detail_route": "/military/units",
"tags": [
"land",
"military",
"blade"
]
},
"flavor": "The backbone of any early military.",
"archetype": "light_melee",
"promotion_tree": "melee",
"clan_affinity": [],
"logistics": {
"composition": {
"captain": 1,
"sergeant": 1,
"soldier": 13,
"horn_blower": 1
},
"inventory": {
"rations": 160,
"water": 128,
"tool_durability": 2
},
"stats": {
"str": 70,
"con": 100,
"end": 60
},
"terrain_movement": {
"road": 0.5,
"dirt_road": 0.65,
"wagon_track": 0.85,
"trail": 0.8,
"grass": 1.0,
"hills": 1.5,
"forest_open": 1.5,
"forest_dense": 2.5,
"mountain": 3.0,
"snow": 2.0,
"tundra": 1.5,
"desert": 2.5,
"marsh": 3.0,
"river_ford": 2.0,
"river_unfordable": "blocked",
"deep_water": "blocked"
},
"carriers": {
"foot_runners": 2
},
"supply": {
"range_turns": 4,
"decline_rate": 1.2
}
}
}
]