Compare commits
No commits in common. "new-planner-meta" and "new-main" have entirely different histories.
new-planne
...
new-main
3 changed files with 39 additions and 144 deletions
15
README.md
15
README.md
|
|
@ -78,7 +78,6 @@ for step in solution.plan:
|
||||||
"upgrades": [], // already-installed upgrade keys
|
"upgrades": [], // already-installed upgrade keys
|
||||||
"available_turns": null, // null = all turns, or e.g. [0,2,4]
|
"available_turns": null, // null = all turns, or e.g. [0,2,4]
|
||||||
"can_renovate": true, // metropolis must be false
|
"can_renovate": true, // metropolis must be false
|
||||||
"overwork_pending": false, // starts holding an Overwork charge
|
|
||||||
"forced_action": {"1": "renovate"} // turn -> action (hard constraint)
|
"forced_action": {"1": "renovate"} // turn -> action (hard constraint)
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -112,15 +111,8 @@ Upgrade keys: `infrastructure`, `harvester`, `fine_dining`, `overflow_vats`,
|
||||||
Monument/Metropolis renown + trade goods), with the **1 Capital** cost.
|
Monument/Metropolis renown + trade goods), with the **1 Capital** cost.
|
||||||
- **Foundry vats**: collecting a vat yields its level, empties it, and adds +1
|
- **Foundry vats**: collecting a vat yields its level, empties it, and adds +1
|
||||||
to the other two (full stateful per-turn model; *Overflow Vats* adds +1 more).
|
to the other two (full stateful per-turn model; *Overflow Vats* adds +1 more).
|
||||||
- **Overwork** (Planner Governor): an Overworked collection is doubled, has its
|
- **Overwork** (Planner Governor): doubles a city's collection that turn, waives
|
||||||
Capital cost waived, and **locks** that city out of collecting the next turn.
|
the Capital cost, and **locks** that city out of collecting the next turn.
|
||||||
Appointing the Planner *arms* the city rather than necessarily firing that
|
|
||||||
turn: the charge may be spent by that same turn's collection (the classic
|
|
||||||
play) or held while the city collects normally, acts, or idles — in which case
|
|
||||||
the city's **next** collection is the Overworked one, whether or not the
|
|
||||||
Planner is still there. A held charge is not optional (the next collection
|
|
||||||
spends it) and charges do not stack. `City.overwork_pending` seeds a city that
|
|
||||||
entered the horizon already holding one.
|
|
||||||
- **Upgrades** with Steel costs (Infrastructure 0 / Harvester 2 / type-specific
|
- **Upgrades** with Steel costs (Infrastructure 0 / Harvester 2 / type-specific
|
||||||
2 / Fortification 4), Infrastructure's −1 future-cost discount, and the +1/+2
|
2 / Fortification 4), Infrastructure's −1 future-cost discount, and the +1/+2
|
||||||
Renown each grants. *Harvester*, *Fine Dining*, *Transit Authority* yield
|
Renown each grants. *Harvester*, *Fine Dining*, *Transit Authority* yield
|
||||||
|
|
@ -154,8 +146,7 @@ Upgrade keys: `infrastructure`, `harvester`, `fine_dining`, `overflow_vats`,
|
||||||
"final_renown_total": 35,
|
"final_renown_total": 35,
|
||||||
"plan": [
|
"plan": [
|
||||||
{"turn": 0, "city": "Aridias", "action": "collect",
|
{"turn": 0, "city": "Aridias", "action": "collect",
|
||||||
"detail": "hub: +2 luxuries", "governor": "", "overwork": false,
|
"detail": "hub: +2 luxuries", "governor": "", "overwork": false}
|
||||||
"overwork_armed": false} // armed = the Planner charged this city here
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
14
index.html
14
index.html
|
|
@ -645,10 +645,6 @@
|
||||||
const vs = num(c.vat_steel || 1, {min: 0}), vb = num(c.vat_brass || 1, {min: 0}),
|
const vs = num(c.vat_steel || 1, {min: 0}), vb = num(c.vat_brass || 1, {min: 0}),
|
||||||
ve = num(c.vat_electrum || 1, {min: 0});
|
ve = num(c.vat_electrum || 1, {min: 0});
|
||||||
const reno = el("input", {type: "checkbox"}); reno.checked = c.can_renovate !== false;
|
const reno = el("input", {type: "checkbox"}); reno.checked = c.can_renovate !== false;
|
||||||
// Mid-game restore: the Planner already governed this city and it has
|
|
||||||
// not collected since, so its first collection here is overworked.
|
|
||||||
const owPend = el("input", {type: "checkbox"});
|
|
||||||
owPend.checked = !!c.overwork_pending;
|
|
||||||
const adjacent = el("input", {
|
const adjacent = el("input", {
|
||||||
value: (c.adjacent || []).join(", "),
|
value: (c.adjacent || []).join(", "),
|
||||||
placeholder: "Bearhearth, Kingsland"
|
placeholder: "Bearhearth, Kingsland"
|
||||||
|
|
@ -716,7 +712,6 @@
|
||||||
const u = allowedUpgrades().filter(name => upBoxes[name] && upBoxes[name].checked);
|
const u = allowedUpgrades().filter(name => upBoxes[name] && upBoxes[name].checked);
|
||||||
if (u.length) o.upgrades = u;
|
if (u.length) o.upgrades = u;
|
||||||
if (!reno.checked) o.can_renovate = false;
|
if (!reno.checked) o.can_renovate = false;
|
||||||
if (owPend.checked) o.overwork_pending = true;
|
|
||||||
const adj = parseStrs(adjacent.value);
|
const adj = parseStrs(adjacent.value);
|
||||||
if (adj) o.adjacent = adj;
|
if (adj) o.adjacent = adj;
|
||||||
const fa = parsePairs(forced.value);
|
const fa = parsePairs(forced.value);
|
||||||
|
|
@ -738,7 +733,6 @@
|
||||||
el("div", {class: "stack"}, [
|
el("div", {class: "stack"}, [
|
||||||
field("Type", type),
|
field("Type", type),
|
||||||
checkField("Can renovate", reno),
|
checkField("Can renovate", reno),
|
||||||
checkField("Overwork pending", owPend),
|
|
||||||
]),
|
]),
|
||||||
field("Renown", renown),
|
field("Renown", renown),
|
||||||
field("Upgrades (already installed)", upWrap),
|
field("Upgrades (already installed)", upWrap),
|
||||||
|
|
@ -1428,16 +1422,10 @@
|
||||||
class: "mini", type: "button",
|
class: "mini", type: "button",
|
||||||
onclick: () => downloadPlanCsv(s, n),
|
onclick: () => downloadPlanCsv(s, n),
|
||||||
}, "Download CSV")));
|
}, "Download CSV")));
|
||||||
// Overwork column: the Planner *arms* a city, and the charge is
|
|
||||||
// spent by that city's next Collection - which may be a later
|
|
||||||
// turn, with the Planner long gone.
|
|
||||||
const owCell = p => p.overwork
|
|
||||||
? (p.overwork_armed ? "yes (armed here)" : "yes (armed earlier)")
|
|
||||||
: (p.overwork_armed ? "armed - fires on next collect" : "");
|
|
||||||
out.append(gridTable(
|
out.append(gridTable(
|
||||||
["Turn", "City", "Action", "Detail", "Governor", "Overwork"],
|
["Turn", "City", "Action", "Detail", "Governor", "Overwork"],
|
||||||
s.plan.map(p => [p.turn, p.city, p.action, p.detail, p.governor,
|
s.plan.map(p => [p.turn, p.city, p.action, p.detail, p.governor,
|
||||||
owCell(p)])));
|
p.overwork ? "yes" : ""])));
|
||||||
} else {
|
} else {
|
||||||
out.append(el("p", {}, "(no actions / no feasible plan)"));
|
out.append(el("p", {}, "(no actions / no feasible plan)"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
154
solve.py
154
solve.py
|
|
@ -37,30 +37,11 @@ Upgrades (Steel cost in brackets, each grants +1 City Renown unless noted):
|
||||||
|
|
||||||
Governors / Overwork:
|
Governors / Overwork:
|
||||||
|
|
||||||
The Planner Leader has *Overwork*: an Overworked Collection is doubled and
|
The Planner Leader has *Overwork*: when appointed Governor of a City it
|
||||||
its Capital cost waived, but the City cannot Collect the following Turn.
|
doubles that City's Collection that Turn and waives the Capital cost, but
|
||||||
The Planner can govern at most one City per Turn.
|
the City cannot Collect the following Turn. The Planner can govern at most
|
||||||
|
one City per Turn. Generic governor Agents may also grant a free Upgrade
|
||||||
Appointing the Planner Governor of a City *arms* that City rather than
|
or bonus Trade Goods on Collect.
|
||||||
necessarily firing that Turn, which lets the model cover every legal
|
|
||||||
timing:
|
|
||||||
|
|
||||||
* arm and spend the same Turn - the classic case: the Planner governs a
|
|
||||||
Collecting City and that Collection is the doubled one;
|
|
||||||
* arm and hold - the Planner governs a City that Collects normally (or
|
|
||||||
takes some other Action, or is idle) and the charge carries forward;
|
|
||||||
the City's *next* Collection is the Overworked one, whether or not the
|
|
||||||
Planner is still there.
|
|
||||||
|
|
||||||
A held charge is not optional: once armed, the very next Collection that
|
|
||||||
City makes is Overworked (and is followed by the no-Collect lock). Charges
|
|
||||||
never stack, so the model does not offer arming a City that is already
|
|
||||||
holding one (re-arming would buy nothing anyway).
|
|
||||||
``City.overwork_pending`` seeds a City that entered the horizon already
|
|
||||||
holding a charge.
|
|
||||||
|
|
||||||
Generic governor Agents may also grant a free Upgrade or bonus Trade Goods
|
|
||||||
on Collect.
|
|
||||||
|
|
||||||
Other modeled industrial Governor Agents (see Agent named constructors):
|
Other modeled industrial Governor Agents (see Agent named constructors):
|
||||||
Baron (+Trade Goods/Bastion), Builder (free type-specific Upgrade),
|
Baron (+Trade Goods/Bastion), Builder (free type-specific Upgrade),
|
||||||
|
|
@ -200,10 +181,6 @@ class City:
|
||||||
adjacent: list[str] = field(default_factory=list)
|
adjacent: list[str] = field(default_factory=list)
|
||||||
available_turns: Optional[list[int]] = None # None => all turns
|
available_turns: Optional[list[int]] = None # None => all turns
|
||||||
can_renovate: bool = True # Metropolis cannot renovate
|
can_renovate: bool = True # Metropolis cannot renovate
|
||||||
# Start state: the City is already holding an unspent Overwork charge (the
|
|
||||||
# Planner governed it before the horizon began and it has not Collected
|
|
||||||
# since). Its first Collection in the horizon is then Overworked.
|
|
||||||
overwork_pending: bool = False
|
|
||||||
# Hard constraint: force a specific action on a given turn (turn -> Action).
|
# Hard constraint: force a specific action on a given turn (turn -> Action).
|
||||||
forced_action: dict[int, str] = field(default_factory=dict)
|
forced_action: dict[int, str] = field(default_factory=dict)
|
||||||
# Soft hint (NOT a constraint): a suggested action on a given turn
|
# Soft hint (NOT a constraint): a suggested action on a given turn
|
||||||
|
|
@ -227,7 +204,7 @@ class Agent:
|
||||||
agents can be expressed with the generic effect flags.
|
agents can be expressed with the generic effect flags.
|
||||||
"""
|
"""
|
||||||
name: str
|
name: str
|
||||||
overwork: bool = False # Planner: arms Overwork on the governed City
|
overwork: bool = False # Planner: double + waive cost
|
||||||
free_upgrade: bool = False # e.g. Brotherhood Builder
|
free_upgrade: bool = False # e.g. Brotherhood Builder
|
||||||
bonus_trade_goods: int = 0 # e.g. Baron: +N Trade Goods on collect
|
bonus_trade_goods: int = 0 # e.g. Baron: +N Trade Goods on collect
|
||||||
# --- additional industrial Governor effects (see named constructors) ---
|
# --- additional industrial Governor effects (see named constructors) ---
|
||||||
|
|
@ -257,9 +234,8 @@ class Agent:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def planner(cls, name: str = "Planner", **kw) -> "Agent":
|
def planner(cls, name: str = "Planner", **kw) -> "Agent":
|
||||||
"""Faction Planner Leader: arms Overwork on the governed City. The
|
"""Faction Planner Leader: Overwork (double collection, waive Capital
|
||||||
armed Collection (this Turn's, or the City's next one) is doubled with
|
cost, lock next-Turn collect on the governed City)."""
|
||||||
its Capital cost waived, and locks the following Turn's Collect."""
|
|
||||||
return cls(name=name, overwork=True, **kw)
|
return cls(name=name, overwork=True, **kw)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -454,13 +430,7 @@ class CityTurnPlan:
|
||||||
action: str
|
action: str
|
||||||
detail: str = "" # e.g. collect choice, upgrade name, renovate target
|
detail: str = "" # e.g. collect choice, upgrade name, renovate target
|
||||||
governor: str = "" # agent appointed governor (if any)
|
governor: str = "" # agent appointed governor (if any)
|
||||||
# This Turn's Collection is the Overworked one (doubled, Capital waived).
|
|
||||||
overwork: bool = False
|
overwork: bool = False
|
||||||
# The Planner armed an Overwork charge here this Turn. Together with
|
|
||||||
# ``overwork``: armed+overwork = armed and spent now; armed alone = the
|
|
||||||
# charge is held for this City's next Collection; overwork alone = it is
|
|
||||||
# spending a charge armed on an earlier Turn.
|
|
||||||
overwork_armed: bool = False
|
|
||||||
# Net resource change produced by this Action (resource -> amount). Only the
|
# Net resource change produced by this Action (resource -> amount). Only the
|
||||||
# stockpiled resources this City's Action affects appear here.
|
# stockpiled resources this City's Action affects appear here.
|
||||||
deltas: dict[str, float] = field(default_factory=dict)
|
deltas: dict[str, float] = field(default_factory=dict)
|
||||||
|
|
@ -530,16 +500,8 @@ class _Builder:
|
||||||
self.act: dict[tuple[int, int, Action], cp_model.IntVar] = {}
|
self.act: dict[tuple[int, int, Action], cp_model.IntVar] = {}
|
||||||
# governor assignment: gov[(agent_idx, city_idx, turn)] bool
|
# governor assignment: gov[(agent_idx, city_idx, turn)] bool
|
||||||
self.gov: dict[tuple[int, int, int], cp_model.IntVar] = {}
|
self.gov: dict[tuple[int, int, int], cp_model.IntVar] = {}
|
||||||
# overwork[(city_idx, turn)] bool: this City's Collection on this Turn
|
# overwork[(city_idx, turn)] bool (planner governs & overworks this city)
|
||||||
# is the Overworked one (doubled yield, Capital cost waived).
|
|
||||||
self.overwork: dict[tuple[int, int], cp_model.IntVar] = {}
|
self.overwork: dict[tuple[int, int], cp_model.IntVar] = {}
|
||||||
# ow_arm[(city_idx, turn)] bool: the Planner governs this City this Turn
|
|
||||||
# and so arms an Overwork charge on it.
|
|
||||||
self.ow_arm: dict[tuple[int, int], cp_model.IntVar] = {}
|
|
||||||
# ow_pending[(city_idx, turn)] bool: an armed-but-unspent charge is
|
|
||||||
# carried *into* this Turn. Defined for turns 0..T (T = after the last
|
|
||||||
# Turn); ow_pending[(ci, 0)] comes from City.overwork_pending.
|
|
||||||
self.ow_pending: dict[tuple[int, int], cp_model.IntVar] = {}
|
|
||||||
# final renown per city
|
# final renown per city
|
||||||
self.city_final_renown: list[cp_model.IntVar] = []
|
self.city_final_renown: list[cp_model.IntVar] = []
|
||||||
# airship launch booleans (each adds AIRSHIP_RENOWN to asset renown)
|
# airship launch booleans (each adds AIRSHIP_RENOWN to asset renown)
|
||||||
|
|
@ -657,73 +619,24 @@ class _Builder:
|
||||||
if govs:
|
if govs:
|
||||||
m.Add(sum(govs) <= 1)
|
m.Add(sum(govs) <= 1)
|
||||||
|
|
||||||
self._build_overwork(cities, agents)
|
# Overwork bool: planner (overwork agent) governs this city.
|
||||||
|
|
||||||
def _build_overwork(self, cities: list[City], agents: list[Agent]):
|
|
||||||
"""Overwork as an armed-charge state machine, one per City.
|
|
||||||
|
|
||||||
Appointing the Planner (an ``overwork`` Agent) Governor *arms* the City
|
|
||||||
(``ow_arm``). A charge sits on the City (``ow_pending``) until a
|
|
||||||
Collection spends it, and the Collection that spends it is the
|
|
||||||
Overworked one (``overwork``): doubled, Capital cost waived, and the
|
|
||||||
following Turn's Collect is locked out.
|
|
||||||
|
|
||||||
The charge may be spent by the Collection on the very Turn it is armed
|
|
||||||
(the classic Planner play) or held for a later one - the Planner does
|
|
||||||
not have to still be there, and the City is free to Collect normally,
|
|
||||||
act, or idle on the arming Turn. What it cannot do is *skip* a charge:
|
|
||||||
a carried charge is spent by the next Collection, whichever Turn that
|
|
||||||
falls on.
|
|
||||||
|
|
||||||
The flow equation ``pending' = pending + arm - overwork`` over 0/1
|
|
||||||
variables is what ties this together. Charges never stack: the Planner
|
|
||||||
is not placed on a City that is already holding one (``arm + pending
|
|
||||||
<= 1``), even on a Turn whose Collection would spend that charge - the
|
|
||||||
Collection is doubled once either way, so the placement would buy
|
|
||||||
nothing while quietly banking a second charge.
|
|
||||||
"""
|
|
||||||
m = self.m
|
|
||||||
overwork_agents = [ai for ai, a in enumerate(agents) if a.overwork]
|
overwork_agents = [ai for ai, a in enumerate(agents) if a.overwork]
|
||||||
for ci, city in enumerate(cities):
|
for ci in range(len(cities)):
|
||||||
for t in range(self.T):
|
for t in range(self.T):
|
||||||
contrib = [
|
contrib = [
|
||||||
self.gov[(ai, ci, t)]
|
self.gov[(ai, ci, t)]
|
||||||
for ai in overwork_agents
|
for ai in overwork_agents
|
||||||
if (ai, ci, t) in self.gov
|
if (ai, ci, t) in self.gov
|
||||||
]
|
]
|
||||||
arm = m.NewBoolVar(f"owarm_c{ci}_t{t}")
|
ow = m.NewBoolVar(f"overwork_c{ci}_t{t}")
|
||||||
# At most one Planner can be here: each governs <=1 City and
|
if contrib:
|
||||||
# each City has <=1 Governor, so the sum is already 0/1.
|
m.Add(ow == sum(contrib)) # at most one planner total
|
||||||
m.Add(arm == sum(contrib) if contrib else arm == 0)
|
else:
|
||||||
self.ow_arm[(ci, t)] = arm
|
m.Add(ow == 0)
|
||||||
self.overwork[(ci, t)] = m.NewBoolVar(f"overwork_c{ci}_t{t}")
|
self.overwork[(ci, t)] = ow
|
||||||
for t in range(self.T + 1):
|
|
||||||
self.ow_pending[(ci, t)] = m.NewBoolVar(f"owpend_c{ci}_t{t}")
|
|
||||||
# Charge carried in from before the horizon (session restore).
|
|
||||||
m.Add(self.ow_pending[(ci, 0)] == int(city.overwork_pending))
|
|
||||||
|
|
||||||
for t in range(self.T):
|
# Only one overworking placement at a time is already implied by
|
||||||
arm = self.ow_arm[(ci, t)]
|
# the agent's "<=1 city" constraint.
|
||||||
ow = self.overwork[(ci, t)]
|
|
||||||
pend = self.ow_pending[(ci, t)]
|
|
||||||
collect = self.act[(ci, t, Action.COLLECT)]
|
|
||||||
# Only a Collection can be Overworked, and only with a charge
|
|
||||||
# (armed this Turn or carried in).
|
|
||||||
m.Add(ow <= collect)
|
|
||||||
m.Add(ow <= pend + arm)
|
|
||||||
# A carried charge is not optional: Collecting spends it.
|
|
||||||
m.Add(ow >= pend + collect - 1)
|
|
||||||
# No stacking: don't arm a City that already holds a charge.
|
|
||||||
# Without this the Planner could arm a City on the very Turn
|
|
||||||
# its held charge fires, spending one and banking another.
|
|
||||||
m.Add(arm + pend <= 1)
|
|
||||||
# Charge flow.
|
|
||||||
m.Add(self.ow_pending[(ci, t + 1)] == pend + arm - ow)
|
|
||||||
# An Overworked Collection locks the next Turn's Collect.
|
|
||||||
if t + 1 < self.T:
|
|
||||||
m.Add(
|
|
||||||
self.act[(ci, t + 1, Action.COLLECT)] == 0
|
|
||||||
).OnlyEnforceIf(ow)
|
|
||||||
|
|
||||||
def _build_hints(self):
|
def _build_hints(self):
|
||||||
"""Apply soft solution hints via ``model.AddHint``. Unlike the forced_*
|
"""Apply soft solution hints via ``model.AddHint``. Unlike the forced_*
|
||||||
|
|
@ -1014,8 +927,17 @@ class _Builder:
|
||||||
refund = self._mul_bool(capped, prodigy, cap)
|
refund = self._mul_bool(capped, prodigy, cap)
|
||||||
self._add_delta("steel", t, refund)
|
self._add_delta("steel", t, refund)
|
||||||
|
|
||||||
# --- Overwork: arming, spending and the "no collect next turn" lock
|
# --- Overwork "no collect next turn" lock --------------------------
|
||||||
# all live in _build_overwork, which runs before this.
|
for t in range(T - 1):
|
||||||
|
# if overworked at t, cannot collect at t+1
|
||||||
|
m.Add(self.act[(ci, t + 1, Action.COLLECT)] == 0).OnlyEnforceIf(
|
||||||
|
self.overwork[(ci, t)]
|
||||||
|
)
|
||||||
|
# Overwork requires a collection this turn (otherwise pointless, and a
|
||||||
|
# governor that overworks implies the city collects).
|
||||||
|
for t in range(T):
|
||||||
|
m.Add(self.act[(ci, t, Action.COLLECT)] >= self.overwork[(ci, t)])
|
||||||
|
|
||||||
# --- Launches need available steel handled by balance; renown -------
|
# --- Launches need available steel handled by balance; renown -------
|
||||||
# --- Final renown of the city --------------------------------------
|
# --- Final renown of the city --------------------------------------
|
||||||
self._build_city_renown(ci, city, installed, type_active)
|
self._build_city_renown(ci, city, installed, type_active)
|
||||||
|
|
@ -1139,11 +1061,8 @@ class _Builder:
|
||||||
|
|
||||||
# ---- per-Collection bonuses from governor agents ---------------
|
# ---- per-Collection bonuses from governor agents ---------------
|
||||||
# Each is applied whenever the City Collects (any type) while
|
# Each is applied whenever the City Collects (any type) while
|
||||||
# governed. These are *not* doubled by Overwork: the Governor's
|
# governed. A bonus Governor occupies the City's only Governor slot,
|
||||||
# bonus is the Agent's own grant, not part of the City's Collection
|
# so these never co-occur with the Planner's Overwork doubling.
|
||||||
# yield. (Overwork can now co-occur with one of these, since a
|
|
||||||
# charge armed on an earlier Turn is spent by a Collection that a
|
|
||||||
# different Agent may be governing.)
|
|
||||||
# Baron -> +N Trade Goods (N = bonus per Bastion)
|
# Baron -> +N Trade Goods (N = bonus per Bastion)
|
||||||
# Artificer -> +1 Trade Good
|
# Artificer -> +1 Trade Good
|
||||||
# Capitalist -> +2 Capital (only on a Hub collecting Capital)
|
# Capitalist -> +2 Capital (only on a Hub collecting Capital)
|
||||||
|
|
@ -1691,15 +1610,12 @@ def _extract(problem: Problem, b: _Builder, solver, status_name: str) -> Solutio
|
||||||
(ci, t) in b._foreman_renov
|
(ci, t) in b._foreman_renov
|
||||||
and bool(solver.Value(b._foreman_renov[(ci, t)]))
|
and bool(solver.Value(b._foreman_renov[(ci, t)]))
|
||||||
)
|
)
|
||||||
overwork = bool(solver.Value(b.overwork[(ci, t)]))
|
|
||||||
# The Planner can arm a City that is idling this Turn, so an
|
|
||||||
# otherwise-empty row still has to be reported.
|
|
||||||
armed = bool(solver.Value(b.ow_arm[(ci, t)]))
|
|
||||||
if (chosen is None or chosen == Action.IDLE) and not foreman_renov \
|
if (chosen is None or chosen == Action.IDLE) and not foreman_renov \
|
||||||
and not armed and (ci, t) not in extra:
|
and (ci, t) not in extra:
|
||||||
continue
|
continue
|
||||||
detail = ""
|
detail = ""
|
||||||
governor = ""
|
governor = ""
|
||||||
|
overwork = bool(solver.Value(b.overwork[(ci, t)]))
|
||||||
# governor name
|
# governor name
|
||||||
for ai, agent in enumerate(problem.agents):
|
for ai, agent in enumerate(problem.agents):
|
||||||
if (ai, ci, t) in b.gov and solver.Value(b.gov[(ai, ci, t)]) == 1:
|
if (ai, ci, t) in b.gov and solver.Value(b.gov[(ai, ci, t)]) == 1:
|
||||||
|
|
@ -1760,7 +1676,7 @@ def _extract(problem: Problem, b: _Builder, solver, status_name: str) -> Solutio
|
||||||
plan.append(CityTurnPlan(
|
plan.append(CityTurnPlan(
|
||||||
turn=t, city=city.name, action=action_label,
|
turn=t, city=city.name, action=action_label,
|
||||||
detail=detail, governor=governor, overwork=overwork,
|
detail=detail, governor=governor, overwork=overwork,
|
||||||
overwork_armed=armed, deltas=deltas,
|
deltas=deltas,
|
||||||
))
|
))
|
||||||
|
|
||||||
def _unscale(r, raw):
|
def _unscale(r, raw):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue