Crafting cards: one-row buttons, list all missing reagents
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a205d429bd
commit
377f534f6b
3 changed files with 20 additions and 9 deletions
10
game.py
10
game.py
|
|
@ -3053,10 +3053,10 @@ def can_start(world: dict, player: dict, action: dict) -> str | None:
|
||||||
if order is not None or "order" in (player["action"] or {}) and player["action"]["id"] == action["id"]:
|
if order is not None or "order" in (player["action"] or {}) and player["action"]["id"] == action["id"]:
|
||||||
if not order or order["status"] != "open" or order["claimed"] != player["id"] and not order.get("city"):
|
if not order or order["status"] != "open" or order["claimed"] != player["id"] and not order.get("city"):
|
||||||
return "Work order done" if order and order["status"] == "done" else "Work order closed"
|
return "Work order done" if order and order["status"] == "done" else "Work order closed"
|
||||||
for item, qty in fire_inputs(world, action).items():
|
short = [ITEMS[item]["name"].lower() for item, qty in fire_inputs(world, action).items()
|
||||||
pooled = order["provided"].get(item, 0) if order else 0
|
if (order["provided"].get(item, 0) if order else 0) + player["bank"].get(item, 0) < qty]
|
||||||
if pooled + player["bank"].get(item, 0) < qty:
|
if short:
|
||||||
return f"Out of {ITEMS[item]['name'].lower()}"
|
return f"Out of: {', '.join(short)}"
|
||||||
if action.get("special") == "tend" and not tend_target(world, player, action):
|
if action.get("special") == "tend" and not tend_target(world, player, action):
|
||||||
return f"Your pile in the {FIRES[action['tend']]['name'].lower()} is full" if action["tend"] else "Your piles are all full"
|
return f"Your pile in the {FIRES[action['tend']]['name'].lower()} is full" if action["tend"] else "Your piles are all full"
|
||||||
if action.get("special") == "sabotage":
|
if action.get("special") == "sabotage":
|
||||||
|
|
@ -6753,6 +6753,8 @@ ORDER_RECIPES, ORDER_RAW = _order_sources()
|
||||||
# line here (new / balance / fix), and a new release a new entry on top.
|
# line here (new / balance / fix), and a new release a new entry on top.
|
||||||
PATCH_NOTES = [
|
PATCH_NOTES = [
|
||||||
{"date": "2026-10-28", "title": "Queue", "notes": [
|
{"date": "2026-10-28", "title": "Queue", "notes": [
|
||||||
|
("fix", "Crafting cards: buttons stay on one row on phones and narrow cards."),
|
||||||
|
("new", "\"Out of:\" lists every missing reagent."),
|
||||||
("new", "Updated guild roster layout"),
|
("new", "Updated guild roster layout"),
|
||||||
("new", "Firekeeping: +Q next to 🔥 Tend all queues tending until your piles are full, then the queue moves on."),
|
("new", "Firekeeping: +Q next to 🔥 Tend all queues tending until your piles are full, then the queue moves on."),
|
||||||
("new", "City work orders: 🏘️ City when posting, or 🔨 on anything a building needs (goes straight into its fund). Anyone can craft them, several at once. Reagents earn their worth in favour, the maker the rest."),
|
("new", "City work orders: 🏘️ City when posting, or 🔨 on anything a building needs (goes straight into its fund). Anyone can craft them, several at once. Reagents earn their worth in favour, the maker the rest."),
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,16 @@ span[data-goto]:not(.item-chip):hover, b[data-goto]:hover { text-decoration: und
|
||||||
.bar.hp > span { background: var(--bad); }
|
.bar.hp > span { background: var(--bad); }
|
||||||
.warn { color: var(--warn); }
|
.warn { color: var(--warn); }
|
||||||
select { background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px; margin-left: 6px; }
|
select { background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px; margin-left: 6px; }
|
||||||
.action .foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: auto; }
|
.action .foot { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; margin-top: auto; }
|
||||||
|
/* The reason gets its own line when it and the buttons don't fit side by side; the buttons stay one row. */
|
||||||
|
.action .foot .why:empty { display: none; }
|
||||||
|
.action .foot > .btns { flex-wrap: nowrap; }
|
||||||
|
.action .foot > :last-child { margin-left: auto; }
|
||||||
|
.action { container-type: inline-size; }
|
||||||
|
@container (max-width: 270px) {
|
||||||
|
.action .foot .btn { padding-inline: 9px; }
|
||||||
|
.action .foot .make input { width: 48px; padding-inline: 6px; }
|
||||||
|
}
|
||||||
|
|
||||||
/* --- bank ------------------------------------------------------------- */
|
/* --- bank ------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ class ActionTest(unittest.TestCase):
|
||||||
self.assertEqual(p["bank"]["copper_bar"], 3)
|
self.assertEqual(p["bank"]["copper_bar"], 3)
|
||||||
self.assertNotIn("copper_ore", p["bank"])
|
self.assertNotIn("copper_ore", p["bank"])
|
||||||
self.assertIsNone(p["action"])
|
self.assertIsNone(p["action"])
|
||||||
self.assertEqual(summary["stopped"], "Out of copper ore")
|
self.assertEqual(summary["stopped"], "Out of: copper ore")
|
||||||
|
|
||||||
def test_crafting_stops_as_the_last_one_finishes(self):
|
def test_crafting_stops_as_the_last_one_finishes(self):
|
||||||
world = world_with(("ann", "commoner"))
|
world = world_with(("ann", "commoner"))
|
||||||
|
|
@ -254,7 +254,7 @@ class ActionTest(unittest.TestCase):
|
||||||
duration = game.action_time(world, p, game.ACTION_BY_ID["smith_copper_bar"])
|
duration = game.action_time(world, p, game.ACTION_BY_ID["smith_copper_bar"])
|
||||||
summary = game.process_player(world, p, T0 + duration + 0.1, random.Random(1))
|
summary = game.process_player(world, p, T0 + duration + 0.1, random.Random(1))
|
||||||
self.assertIsNone(p["action"])
|
self.assertIsNone(p["action"])
|
||||||
self.assertEqual(summary["stopped"], "Out of copper ore")
|
self.assertEqual(summary["stopped"], "Out of: copper ore")
|
||||||
|
|
||||||
def test_level_and_city_requirements(self):
|
def test_level_and_city_requirements(self):
|
||||||
world = world_with(("ann", "commoner"))
|
world = world_with(("ann", "commoner"))
|
||||||
|
|
@ -2709,7 +2709,7 @@ class WorkOrderTest(unittest.TestCase):
|
||||||
self.dave["bank"] = {"iron_bar": 1}
|
self.dave["bank"] = {"iron_bar": 1}
|
||||||
game.provide_reagent(self.world, self.dave, order["id"], "iron_bar")
|
game.provide_reagent(self.world, self.dave, order["id"], "iron_bar")
|
||||||
self.fred["bank"] = {"iron_bar": 1, "oak_plank": 1, "clay_core": 3}
|
self.fred["bank"] = {"iron_bar": 1, "oak_plank": 1, "clay_core": 3}
|
||||||
self.assertEqual(game.work_order(self.world, self.fred, order["id"], T0), "Out of iron bar")
|
self.assertEqual(game.work_order(self.world, self.fred, order["id"], T0), "Out of: iron bar")
|
||||||
self.fred["bank"]["iron_bar"] = 2
|
self.fred["bank"]["iron_bar"] = 2
|
||||||
self.assertIsNone(game.work_order(self.world, self.fred, order["id"], T0))
|
self.assertIsNone(game.work_order(self.world, self.fred, order["id"], T0))
|
||||||
game.process_player(self.world, self.fred, T0 + 600, random.Random(1))
|
game.process_player(self.world, self.fred, T0 + 600, random.Random(1))
|
||||||
|
|
@ -2850,7 +2850,7 @@ class JewelcraftingTest(unittest.TestCase):
|
||||||
game.start_action(self.world, self.ann, "prospect_garnet", T0)
|
game.start_action(self.world, self.ann, "prospect_garnet", T0)
|
||||||
summary = game.process_player(self.world, self.ann, T0 + 1000, Always())
|
summary = game.process_player(self.world, self.ann, T0 + 1000, Always())
|
||||||
self.assertEqual(self.ann["bank"], {"iron_ore": 2, "garnet": 1})
|
self.assertEqual(self.ann["bank"], {"iron_ore": 2, "garnet": 1})
|
||||||
self.assertEqual(summary["stopped"], "Out of iron ore")
|
self.assertEqual(summary["stopped"], "Out of: iron ore")
|
||||||
self.assertGreater(self.ann["xp"]["jewelcrafting"], game.XP_TABLE[15])
|
self.assertGreater(self.ann["xp"]["jewelcrafting"], game.XP_TABLE[15])
|
||||||
|
|
||||||
def test_jewellery_bonuses(self):
|
def test_jewellery_bonuses(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue