Building funds safe from raids; settlement tiers; population and food on the town square

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-18 19:20:52 +01:00
parent e3b70c1e3a
commit 3716df7493
6 changed files with 358 additions and 91 deletions

34
app.py
View file

@ -56,7 +56,7 @@ class Store:
db.execute("CREATE TABLE IF NOT EXISTS world (id INTEGER PRIMARY KEY CHECK (id = 1), data TEXT NOT NULL)")
row = db.execute("SELECT data FROM world WHERE id = 1").fetchone()
if row:
self.world = json.loads(row[0])
self.world = game.migrate(json.loads(row[0]))
self.world["config"]["speed"] = speed
else:
self.world = game.new_world(time.time(), speed)
@ -109,20 +109,25 @@ def city_view(world: dict, now: float) -> dict:
city = world["city"]
buildings = {}
for key, building in city["buildings"].items():
spec = game.BUILDINGS[key]
if building["damaged"]:
cost = game.repair_cost(key, building["level"])
elif building["level"] < spec["max"]:
cost = game.build_cost(key, building["level"] + 1)
working = city["construction"] and city["construction"]["building"] == key
target = game.fund_target(world, key)
missing = game.fund_missing(world, key)
if working:
status = "building"
elif key in city["queue"]:
status = "queued"
elif target is None:
status = "max" if building["level"] >= game.BUILDINGS[key]["max"] else "capped"
else:
cost = None
buildings[key] = {**building, "cost": cost, "missing": game.missing_for(city, cost) if cost else []}
status = "funding"
buildings[key] = {**building, "target": target, "missing": missing, "status": status,
"cap": game.level_cap(world, key)}
return {
"population": int(city["population"]),
"housing": game.housing(world),
**game.population_view(world),
"buildings": buildings,
"queue": city["queue"],
"treasury": int(city["treasury"]),
"stockpile": city["stockpile"],
"buildings": buildings,
"construction": city["construction"],
"starving": city["starving"],
"merchant_until": city.get("merchant_until", 0),
@ -290,8 +295,11 @@ class Handler(BaseHTTPRequestHandler):
return "Gold can't be sold" if item == "gold" else game.sell(world, player, item, qty, now)
if path == "/api/equip":
return self.equip(player, item, body.get("slot"))
if path == "/api/build":
return game.commission(world, player, str(body.get("building")), now)
if path == "/api/fund":
qty = body.get("qty")
return game.fund(world, player, str(body.get("building")), str(body.get("item")),
qty if qty == "all" else (qty if isinstance(qty, int) else -1),
str(body.get("source")), now)
if path == "/api/garrison":
raid = game.upcoming_raid(world)
if body.get("join") and not raid: