City work orders

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-28 13:59:14 +00:00
parent 4b0724e6e5
commit e1d37ede87
4 changed files with 243 additions and 47 deletions

View file

@ -2737,6 +2737,79 @@ class WorkOrderTest(unittest.TestCase):
self.assertEqual(order["status"], "done")
self.assertEqual(self.dave["bank"], {"clay_core": 3})
def test_city_orders_fill_the_stockpile_and_share_the_favour(self):
self.assertIsNone(game.post_order(self.world, self.fred, "craft", "iron_warhammer", 1, [], 0, T0, city=True))
order = self.world["orders"][0]
self.dave["bank"] = {"iron_bar": 2}
self.mike["bank"] = {"clay_core": 3}
game.provide_reagent(self.world, self.dave, order["id"], "iron_bar")
game.provide_reagent(self.world, self.mike, order["id"], "clay_core")
self.fred["bank"] = {"iron_bar": 1, "oak_plank": 1}
self.assertIsNone(game.work_order(self.world, self.fred, order["id"], T0)) # the poster can make it
game.process_player(self.world, self.fred, T0 + 600, random.Random(1))
self.assertEqual(order["status"], "done")
self.assertEqual(self.world["city"]["stockpile"].get("iron_warhammer"), 1)
self.assertEqual(self.fred["bank"], {})
# Hammer 101: Dave's bars 20 and Mike's cores 45 as if donated, Fred the other 36.
self.assertEqual(order["favour"], {"dave": 20, "mike": 45, "fred": 36})
self.assertEqual((self.dave["favour"], self.mike["favour"], self.fred["favour"]), (20, 45, 36))
line = self.mike["ledger"][-1]
self.assertEqual((line["verb"], line["item"], line["qty"], line["label"]), ("Donated", "clay_core", 3, "City order"))
def test_city_materials_orders_are_delivered_to_the_stockpile(self):
self.assertEqual(game.post_order(self.world, self.mike, "gather", "copper_ore", 10, None, 0, T0, city=True),
"The city has no use for that")
self.assertIsNone(game.post_order(self.world, self.mike, "gather", "oak_logs", 100, None, 0, T0, city=True))
order = self.world["orders"][0]
self.mike["bank"] = {"oak_logs": 30}
self.dave["bank"] = {"oak_logs": 80}
self.assertIsNone(game.deliver_order(self.world, self.mike, order["id"], T0))
self.assertIsNone(game.deliver_order(self.world, self.dave, order["id"], T0))
self.assertEqual(self.world["city"]["stockpile"].get("oak_logs"), 100)
self.assertEqual(order["favour"], {"mike": 120, "dave": 280})
self.assertEqual((order["status"], order["held"], self.dave["bank"]), ("done", 0, {"oak_logs": 10}))
def test_several_crafters_work_a_city_order_at_once(self):
game.post_order(self.world, self.mike, "craft", "iron_warhammer", 2, [], 0, T0, city=True)
order = self.world["orders"][0]
self.fred["bank"] = {"iron_bar": 3, "oak_plank": 1, "clay_core": 3}
self.dave["bank"] = {"iron_bar": 3, "oak_plank": 1, "clay_core": 3}
self.assertIsNone(game.work_order(self.world, self.fred, order["id"], T0))
self.assertIsNone(game.work_order(self.world, self.dave, order["id"], T0)) # nobody holds a claim
game.process_player(self.world, self.fred, T0 + 600, random.Random(1))
game.process_player(self.world, self.dave, T0 + 600, random.Random(1))
self.assertEqual((order["status"], order["from"]), ("done", {"fred": 1, "dave": 1}))
self.assertEqual(self.world["city"]["stockpile"].get("iron_warhammer"), 2)
def test_a_building_order_fills_its_fund_then_the_stockpile(self):
self.world["city"]["buildings"]["houses"]["fund"] = {}
need = game.fund_missing(self.world, "houses")
item = next(i for i in need if i in game.ORDER_RAW)
self.assertEqual(game.post_order(self.world, self.mike, "gather", "copper_ore", 5, None, 0, T0, city=True, fund="houses"),
"The city has no use for that")
self.assertIsNone(game.post_order(self.world, self.mike, "gather", item, need[item] + 5, None, 0, T0, city=True, fund="houses"))
order = self.world["orders"][0]
self.fred["bank"] = {item: need[item] + 5}
stock = self.world["city"]["stockpile"].get(item, 0)
self.assertIsNone(game.deliver_order(self.world, self.fred, order["id"], T0))
self.assertNotIn(item, game.fund_missing(self.world, "houses"))
self.assertEqual(self.world["city"]["stockpile"].get(item, 0), stock + 5) # the fund was full
self.assertEqual(self.fred["ledger"][-1]["label"], "Houses")
def test_a_building_order_fits_its_fitting(self):
spec = next(f for f in game.FITTING_BY_ID.values() if f["id"] in game.ORDER_RECIPES)
building = self.world["city"]["buildings"][spec["building"]]
building["level"] = spec["level"]
self.assertIsNone(game.post_order(self.world, self.mike, "craft", spec["id"], 2, [], 0, T0, city=True, fund=spec["building"]))
self.fred["bank"] = {spec["id"]: 2}
self.assertIsNone(game.deliver_order(self.world, self.fred, self.world["orders"][0]["id"], T0))
self.assertIn(spec["id"], building["fittings"])
self.assertEqual(self.world["city"]["stockpile"].get(spec["id"]), 1) # one fits, the spare is stored
def test_orders_have_no_size_cap(self):
self.assertIsNone(game.post_order(self.world, self.mike, "gather", "oak_logs", 50_000, None, 0, T0, city=True))
self.assertEqual(game.post_order(self.world, self.mike, "gather", "oak_logs", 0, None, 0, T0), "Bad amount")
class Always:
"""An rng where every roll comes up: a gem, a drop, whatever's on offer."""