Track donations per item

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-28 08:23:14 +00:00
parent 45a51476a9
commit fa960e1d6c
2 changed files with 48 additions and 19 deletions

47
game.py
View file

@ -1542,7 +1542,7 @@ RAID_TRAITS = ["lightly armoured, heavy on archers", "mounted and fast, few bows
# --- world ---------------------------------------------------------------
WORLD_VERSION = 33
WORLD_VERSION = 34
def new_world(now: float, speed: float = 1.0) -> dict:
@ -1798,6 +1798,11 @@ def migrate(world: dict, now: float | None = None) -> dict:
for player in world["players"].values():
player.setdefault("bury", True)
world["version"] = 33
if world["version"] < 34:
# Donation history per item, from here on.
for player in world["players"].values():
player.setdefault("gave", {})
world["version"] = 34
return world
@ -2058,6 +2063,7 @@ def new_player(uid: str, name: str, cls: str, now: float) -> dict:
"rented": 0, "boosts": [], "bought": None, "deeds": {}, "owned": [], "look": dict(DEFAULT_LOOK),
"garrison": False,
"donated": 0,
"gave": {}, # item (or "gold"): {qty, worth, favour} given to the city, see credit()
"pinned": [], # skills pinned to the top of the sidebar
"tracked": None, # recipe shown under the top bar
}
@ -2131,13 +2137,26 @@ def bank_add(world: dict, player: dict, item: str, qty: int, now: float, summary
overflow = summary["overflow"]
stockpile = world["city"]["stockpile"]
stockpile[item] = stockpile.get(item, 0) + spill
gain = spill * ITEMS[item]["value"]
player["favour"] += gain * OVERFLOW_FAVOUR
player["donated"] += gain
credit(player, item, spill, OVERFLOW_FAVOUR)
overflow[item] = overflow.get(item, 0) + spill
return keep
def credit(player: dict, item: str, qty: int, rate: float) -> None:
"""Favour for giving `qty` of an item (or gold) to the city, at `rate` per point of worth.
Every gift is tallied per item in `gave`: how many, their worth at the time, and the
favour paid for them, so a later revalue can recompute favour exactly.
"""
worth = qty * (1 if item == "gold" else ITEMS[item]["value"])
player["favour"] += worth * rate
player["donated"] += worth
tally = player["gave"].setdefault(item, {"qty": 0, "worth": 0, "favour": 0})
tally["qty"] += qty
tally["worth"] += worth
tally["favour"] += worth * rate
def bank_take(player: dict, item: str, qty: int) -> None:
left = player["bank"][item] - qty
if left > 0:
@ -4036,7 +4055,6 @@ def donate(world: dict, player: dict, item: str, qty: int, now: float) -> str |
return "Not enough gold"
player["gold"] -= qty
city["treasury"] += qty
gain = qty
label = f"{qty:,} gold"
else:
if not city_uses(item):
@ -4045,10 +4063,8 @@ def donate(world: dict, player: dict, item: str, qty: int, now: float) -> str |
return "You don't have that many"
bank_take(player, item, qty)
city["stockpile"][item] = city["stockpile"].get(item, 0) + qty
gain = qty * ITEMS[item]["value"]
label = amount(item, qty)
player["favour"] += gain * city_rate(world, "favour")
player["donated"] += gain
credit(player, item, qty, city_rate(world, "favour"))
log(world, now, "donation", f"{player['name']} donated {label}", player["id"])
return None
@ -4115,9 +4131,7 @@ def fund(world: dict, player: dict, key: str, item: str, qty: int | str, source:
player["gold"] -= qty
else:
bank_take(player, item, qty)
gain = qty * (1 if item == "gold" else ITEMS[item]["value"])
player["favour"] += gain * city_rate(world, "favour")
player["donated"] += gain
credit(player, item, qty, city_rate(world, "favour"))
elif item == "gold":
city["treasury"] -= qty
else:
@ -4148,9 +4162,7 @@ def install(world: dict, player: dict, fitting: str, source: str, now: float) ->
if not player["bank"].get(fitting):
return "You don't have one"
bank_take(player, fitting, 1)
gain = ITEMS[fitting]["value"]
player["favour"] += gain * city_rate(world, "favour")
player["donated"] += gain
credit(player, fitting, 1, city_rate(world, "favour"))
elif source == "city":
if not city["stockpile"].get(fitting):
return "There isn't one in the stockpile"
@ -4379,8 +4391,7 @@ def pay_wages(world: dict, player: dict, qty, source: str, now: float) -> str |
qty = min(qty, room)
if source == "bank":
player["gold"] -= qty
player["favour"] += qty * city_rate(world, "favour")
player["donated"] += qty
credit(player, "gold", qty, city_rate(world, "favour"))
log(world, now, "donation", f"{player['name']} paid {qty:,} gold of guard wages", player["id"])
else:
city["treasury"] -= qty
@ -5417,9 +5428,7 @@ def aid_problem(world: dict, player: dict, kind: str, item: str, source: str, no
return "Nothing to give"
if source == "bank":
bank_take(player, item, qty)
gain = qty * ITEMS[item]["value"] * city_rate(world, "favour")
player["favour"] += gain
player["donated"] += qty * ITEMS[item]["value"]
credit(player, item, qty, city_rate(world, "favour"))
else:
take_stock_qty(stock, item, qty)
problem["progress"][item] = problem["progress"].get(item, 0) + qty