AGENT ABILITIES -> ACTION IMPLEMENTATIONS (FILTERED)
=====================================================

This document maps each agent's abilities from agents.txt to how they can be
implemented as subclasses of the Action class in main-2.py.

SCOPE: Only agents affecting Steel, Electrum, Brass, or Capital production/consumption.

The Action class framework provides:
  - declare_vars(model, i, t, ctx):  Create decision variables for (city i, step t)
  - add_constraints(model, i, t, ctx): Add precondition/legality constraints
  - add_global_constraints(model, t, ctx): Add per-step global constraints
  - contributes_gains_costs(model, i, t, ctx): Modify resource gains/costs
  - transition_contrib(model, i, t, ctx): Handle state transitions
  - selector_var(i, t, ctx): The boolean variable indicating action is chosen
  - describe(solver, i, t, ctx): Return human-readable action description

GOVERNOR CONSTRAINTS:
- Each city can have at most 1 governor at a time: governor[i,t] ∈ {0,1}
- Each governor can only apply their benefit to at most 1 city per turn
  (multiple unique governors can each apply benefits to different cities in the same turn)

═══════════════════════════════════════════════════════════════════════════════
INDUSTRIAL FOLLOWERS
═══════════════════════════════════════════════════════════════════════════════

CAPITALIST
──────────
Ability: Infinite Growth (As Governor, increases Capital Collection by +2)
  Implementation: GovernorModifierAction("infinite_growth")
  - add_constraints: Checks if appointed as Governor of city
  - contributes_gains_costs:
    - When Governor, append +2 to Capital gains for Collect actions
    - Use OnlyEnforceIf(governor[i,t]) logic


METALLURGIST
─────────────
Ability: Metallurgy (As Governor of Foundry, grants Overflow Vats Upgrade effect)
  Implementation: GovernorSpecialAction("metallurgy")
  - add_constraints:
    - Must be Governor AND city must be Foundry
    - Precondition: isF[i,t] == 1 AND governor[i,t] == 1
  - transition_contrib:
    - When triggered, vat values increase as if Overflow Vats upgrade active
    - Grant vat[i,t+1] = vat[i,t] + 2 (instead of +1 from upgrade_d)


FOREMAN
───────
Ability: Restructure (As Governor, Renovating does not prevent other Industry Actions)
  Implementation: RenovationModifierAction("restructure")
  - add_constraints: Governor check + city is being renovated
  - transition_contrib:
    - Normally, renovating blocks other actions
    - With Restructure, allow simultaneous industry action
    - Create is_restructuring boolean, allow other actions when true


ARTIFICER
──────────
Ability: Wondrous Craft (As Governor, Collects extra Trade Good)
  Implementation: GovernorModifierAction("wondrous_craft")
  - add_constraints: Governor check
  - contributes_gains_costs:
    - When Governor does Collect, add +1 to trade goods count
    - Track trade_goods accumulator separately from base resources


PLANNER
───────
Ability: Orchestrate Overwork (As Governor, allows the Overwork action on the city they govern)
  Implementation: GovernorModifierAction("planner")
  - add_constraints:
    - Governor check: must be Governor of city
    - Enables Overwork action when present
  - Modifies OverworkAction:
    - Remove global "at most 1 city overworks per step" constraint
    - Add constraint: city can only Overwork if Planner is Governor
    - Enables multiple cities to overwork simultaneously if they each have Planner


═══════════════════════════════════════════════════════════════════════════════
DIPLOMATIC FOLLOWERS (SPECIAL) - BIDDING/HIRING EFFECTS
═══════════════════════════════════════════════════════════════════════════════

FENCE
─────
Ability: Customs Acquisitions (When hired, bonus of 2 Trade Goods)
  Implementation: InitializerAction("customs_acquisitions")
  - declare_vars: Create hired_this_turn boolean for city
  - add_constraints: Triggers exactly once at hiring step
  - contributes_gains_costs:
    - Add +2 Trade Goods to step of hiring


═══════════════════════════════════════════════════════════════════════════════
INDUSTRIAL FOLLOWERS (CONTINUED)
═══════════════════════════════════════════════════════════════════════════════

COURIER
───────
Ability: Supply Cache (When first appointed Governor, bonus of 3 Capital/Steel/Brass)
  Implementation: InitializerAction("supply_cache")
  - declare_vars:
    - Create governor_appointed[i,t] boolean (checks transition to governor)
    - Create supply_cache_triggered[i] boolean (one-time flag)
  - add_constraints:
    - Trigger only on first governorship
    - Mark supply_cache_triggered to prevent re-triggering
  - contributes_gains_costs:
    - Add +3 Capital, +3 Steel, +3 Brass to step of first appointment


PROVISIONER
────────────
Ability: Credit Line (When appointed Governor of City with Base, gain 1.5 Electrum)
  Implementation: GovernorSpecialAction("credit_line")
  - declare_vars: Create governor[i,t] boolean
  - add_constraints:
    - Must be Governor AND city must have military Base
    - Check has_base[i,t] from military tracking
  - contributes_gains_costs:
    - Add +1.5 Electrum (represented as fractional or +1 with +0.5 flag)


PRODIGY
───────
Ability: Steel Efficiency (As Governor, when Upgrading/Launching Airship, refund 2 Steel)
  Implementation: GovernorModifierAction("steel_efficiency")
  - add_constraints:
    - Governor check
    - Action must be upgrade or airship launch
  - contributes_gains_costs:
    - Find cost_S for upgrade actions
    - Append -2 (refund) when conditions met
    - Constraint: refund = max(0, cost_S - 2) or simply subtract 2


INDUSTRIALIST
──────────────
Ability: Network (When appointed Governor, City + adjacent Cities gain Infrastructure)
  Implementation: GovernorSpecialAction("network")
  - declare_vars: Create infrastructure[i,t] boolean
  - add_constraints:
    - Triggers when city appointed as governor
    - Applies to all adjacent cities (within adjacency graph)
  - transition_contrib:
    - Mark target city and neighbors with infrastructure upgrade
    - Infrastructure persists through subsequent steps


ECONOMIST
──────────
Ability: Velocity of Money (Gain 1 Renown per 10 Capital Collected and Spent on Collection)
  Implementation: TriggerAction("velocity_of_money")
  - declare_vars:
    - Create capital_spent[i,t] accumulator (tracks collection costs)
    - Create capital_collected[i,t] accumulator (tracks collection gains)
  - add_constraints:
    - Track capital flow through Collect actions on this city
  - contributes_gains_costs:
    - Calculate velocity_renown = (capital_spent + capital_collected) // 10
    - Append velocity_renown to Renown gains each step
  - transition_contrib: Reset accumulators each step


═══════════════════════════════════════════════════════════════════════════════
BROTHERHOOD STARTING FOLLOWERS
═══════════════════════════════════════════════════════════════════════════════

BARON
─────
Ability: Barter (As Governor, Collecting generates +1 Trade Good per Bastion)
  Implementation: GovernorModifierAction("barter")
  - add_constraints:
    - Governor check
    - Action must be Collect
  - contributes_gains_costs:
    - Count bastions on map via bastion[*,t]
    - Add +1 Trade Good per bastion to Collect action
    - Use: trade_good_bonus = count(bastion[i,t] for all i)


BUILDER
────────
Ability: Build Better (When appointed Governor of City, give City its type-specific Upgrade)
  Implementation: GovernorSpecialAction("build_better")
  - declare_vars: Create governor[i,t] and auto_upgrade[i,t]
  - add_constraints:
    - Trigger when appointed Governor
    - City type determines which upgrade (Hub → special, Foundry → vat, etc.)
  - transition_contrib:
    - Determine city type isH/isF/isM/isMon
    - Auto-apply corresponding type-specific upgrade (hasA/hasB/hasD based on type)
    - For Foundry: initialize vats or enhance them



═══════════════════════════════════════════════════════════════════════════════
SPECIALIZED ACTION CLASSES TO CREATE
═══════════════════════════════════════════════════════════════════════════════

To implement the above, create these base action classes:

1. ModifierAction(name)
   - Base for abilities that modify existing actions
   - Override contributes_gains_costs to append bonuses

2. GovernorModifierAction(name)
   - Base for abilities tied to Governor position
   - add_constraints checks governor status
   - Child classes override contributes_gains_costs
   - Used by: CAPITALIST, PRODIGY, BARON

3. GovernorSpecialAction(name)
   - Base for complex governor-tied effects
   - Combines modifier + transition logic
   - Used by: PROVISIONER, INDUSTRIALIST, BUILDER

4. InitializerAction(name)
   - One-time bonuses when agent hired/appointed
   - declare_vars creates hired_flag
   - contributes_gains_costs fires once
   - Used by: COURIER, PROVISIONER, FENCE

5. TriggerAction(name)
   - Abilities that fire when conditions met
   - add_constraints checks trigger condition
   - transition_contrib handles cooldown/flags
   - Used by: ECONOMIST

6. RenovationModifierAction(name)
   - Base for abilities modifying renovation mechanics
   - Used by: FOREMAN


═══════════════════════════════════════════════════════════════════════════════
PLANNER INTEGRATION WITH OVERWORKACTION
═══════════════════════════════════════════════════════════════════════════════

Current OverworkAction (main-2.py lines 327-493):
- add_global_constraints (line 389-394): Enforces "at most 1 city overworks per step" globally

With Planner Governor:
1. Remove the global "at most 1 city per step" constraint from add_global_constraints
2. Add to add_constraints:
   - Can only overwork if governor[i,t] is the Planner
   - Constraint: ow[i,t] <= governor[i,t] (where governor tracks Planner specifically)
   - This allows multiple cities to overwork simultaneously if each has Planner
3. If multiple Planners can exist across cities, each city's Planner can independently enable overwork

Implication: Without Planner governor, city cannot overwork at all. OverworkAction becomes
conditional on Planner presence rather than globally limited.


═══════════════════════════════════════════════════════════════════════════════
IMPLEMENTATION NOTES
═══════════════════════════════════════════════════════════════════════════════

Resource Tracking:
- Core tracked resources: Capital, Steel, Brass, Electrum (these are actual resource accumulators)
- Trade Goods are convertible: Each unit of Trade Good can be independently converted to 1 unit
  of any core resource (Capital, Steel, Brass, or Electrum) at decision time
- When agents produce trade goods, they are accumulated as trade_good[i,t], then converted
  per-unit to core resources during optimization

Boolean Context Variables:
- Governor position: governor[i,t] - tracks who governs each city
- Renown tracking: renown[i,t] - accumulate from various sources
- Bastion tracking: bastion[i,t] - military structures
- Alliance tracking: alliance[faction_a, faction_b, t] - faction pairings

Shared State:
- Some abilities affect global/faction state
- Use ctx for faction-level data sharing
- Example: ctx["faction_renown"][faction_id, t] for faction-wide renown

Cooldown Mechanics:
- Counter variables for cooldowns: cooldown[i,t] = cooldown[i,t-1] - 1
- Constraint: Can trigger if cooldown[i,t] <= 0
- On trigger: Set cooldown[i,t+1] = COOLDOWN_LENGTH

Global Constraints:
- Some abilities have "at most 1 per step" limits
- Use add_global_constraints to enforce across all cities
- Example: sum(action_var[i,t] for i in range(N)) <= 1
