diff --git a/game.py b/game.py index eb187c9..a74541c 100644 --- a/game.py +++ b/game.py @@ -3185,15 +3185,15 @@ def stop(player: dict, reason: str | None = None) -> None: def queueable(action: dict) -> bool: - """Crafting: turns materials into something. Only these can be queued.""" - return bool(action["inputs"] and action["outputs"]) and not ( + """Crafting and gathering: makes or gathers something. Only these can be queued.""" + return bool(action["outputs"]) and not ( action.get("enemy") or action.get("special") or action.get("together")) def queue_reason(world: dict, player: dict, action: dict) -> str | None: """Why it can't go in the queue. Materials are checked when its turn comes.""" if not queueable(action): - return "Only crafting can be queued" + return "Only crafting and gathering can be queued" if skill_level(player, action["skill"]) < action["level"]: return f"Needs level {action['level']}" if action.get("pattern") and action["pattern"] not in player.get("patterns", []): @@ -6286,6 +6286,7 @@ ORDER_RECIPES, ORDER_RAW = _order_sources() # line here (new / balance / fix), and a new release a new entry on top. PATCH_NOTES = [ {"date": "2026-10-27", "title": "Prayer", "notes": [ + ("new", "Gathering can be queued."), ("new", "Make X and queue counts go up to 9,999. Queue has no length cap."), ("balance", "Rebalanced favour values of items"), ("balance", "Prospecting: 3 ore per try (was 5), 50% gem chance (was 15%)."), diff --git a/static/app.js b/static/app.js index 7044b5e..d08ff5f 100644 --- a/static/app.js +++ b/static/app.js @@ -20,7 +20,7 @@ let seenOrders = null; // order ids already known, so only new ones toast let deliveredSeen = {}; // how much of each order had arrived let earnedSeen = {}; // gold each order had paid you for reagents let pickedClass = null; // registration -let queueOpen = false; // the crafting queue panel under the top bar +let queueOpen = false; // the queue panel under the top bar const tabs = {}; // skill -> selected recipe tab let refreshing = false; let refreshedFor = null; // action (start and length) a completion refresh was sent for @@ -777,7 +777,7 @@ function topbar() { chips += `Idle${S.me.stopped ? ` · ${esc(S.me.stopped)}` : ""}`; } if (S.me?.action?.left || S.me?.queue.length) { - chips += ``; + chips += ``; } const fires = S.me ? Object.keys(C.fires).map((id) => [id, fireNow(id)]) : []; if (fires.some(([, n]) => n.heat >= 0)) { @@ -791,7 +791,7 @@ function topbar() { return `

${esc(title)}

${chips}${S.me ? trackedBar() : ""}${S.me && queueOpen ? queuePanel() : ""}`; } -// The crafting queue, opened from the ⏳ chip: what's being made, what's next, and in what order. +// The queue, opened from the ⏳ chip: what's being made, what's next, and in what order. function queuePanel() { const me = S.me, q = me.queue, recipe = (id) => C.actions.find((x) => x.id === id); const now = me.action?.left && recipe(me.action.id), back = me.action?.resume && recipe(me.action.resume); @@ -805,10 +805,10 @@ function queuePanel() { `; }).join(""); return `
-
⏳ Crafting queue${q.length}
+
⏳ Queue${q.length}
${now ? `
${now.icon}${esc(now.name)}${fmt(me.action.left)} left
` : ""} - ${rows ? `
    ${rows}
` : `

Empty. +Q on a recipe adds to it.

`} + ${rows ? `
    ${rows}
` : `

Empty. +Q on a recipe or gathering adds to it.

`}
After queue: ${back ? `${esc(back.name)}${now ? `` : ""}` : "idle"} ${q.length ? `` : ""}
`; diff --git a/tests/test_game.py b/tests/test_game.py index b7025be..ee36140 100644 --- a/tests/test_game.py +++ b/tests/test_game.py @@ -103,6 +103,15 @@ class ActionTest(unittest.TestCase): self.assertEqual(summary["resumed"], "mine_stone") self.assertEqual(p["queue"], []) + def test_queue_gathering(self): + world, p = self._smith(4) + self.assertIsNone(game.queue_add(world, p, "cut_logs", 3, T0)) # starts it, mining is what comes after + self.assertIsNone(game.queue_add(world, p, "smith_copper_legs", 1, T0)) + self.assertIsNone(game.queue_add(world, p, "cut_logs", 2, T0)) + game.process_player(world, p, T0 + 3600, random.Random(1)) + self.assertEqual((p["bank"].get("logs"), p["bank"].get("copper_legs")), (5, 1)) + self.assertEqual((p["action"]["id"], p["queue"]), ("mine_stone", [])) + def test_queue_skips_what_you_cant_make(self): world, p = self._smith(4) game.start_action(world, p, "smith_copper_helmet", T0, once=1) @@ -133,7 +142,7 @@ class ActionTest(unittest.TestCase): def test_queue_rules(self): world, p = self._smith(4) - self.assertEqual(game.queue_add(world, p, "cut_logs", 1, T0), "Only crafting can be queued") + self.assertEqual(game.queue_add(world, p, "bury_bones", 1, T0), "Only crafting and gathering can be queued") self.assertIsNone(game.queue_add(world, p, "smith_copper_helmet", 1, T0)) self.assertEqual(p["action"]["id"], "smith_copper_helmet") # nothing being made: it just starts self.assertEqual(p["action"]["resume"], "mine_stone")