Jewelcrafting: gems, rings, amulets, trinkets

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-20 19:59:45 +01:00
parent 0d33e09799
commit fb237cb686
5 changed files with 266 additions and 26 deletions

View file

@ -1603,3 +1603,80 @@ class WorkOrderTest(unittest.TestCase):
game.process_player(self.world, self.fred, T0 + 600, random.Random(1))
self.assertEqual(self.mike["bank"].get("iron_warhammer"), 1)
self.assertEqual(self.fred["bank"], {}) # used his own plank and cores, never needed bars
class Always:
"""An rng where every roll comes up: a gem, a drop, whatever's on offer."""
def random(self):
return 0.0
def choices(self, population, weights=None, k=1):
return [population[0]] * k
def randint(self, a, b):
return a
class JewelcraftingTest(unittest.TestCase):
def setUp(self):
self.world = world_with(("ann", "commoner"))
self.ann = self.world["players"]["ann"]
def test_recipes_take_a_band_a_gem_and_past_quartz_a_shard(self):
self.assertEqual(game.ACTION_BY_ID["jc_quartz_precision"]["inputs"], {"copper_bar": 1, "quartz": 1})
self.assertEqual(game.ACTION_BY_ID["jc_garnet_vigour"]["inputs"],
{"silver_bar": 2, "garnet": 1, "watchtower_shard": 2})
self.assertEqual(game.ACTION_BY_ID["jc_diamond_charm"]["inputs"],
{"gold_bar": 1, "diamond": 2, "dragonspine_shard": 1})
self.assertIn(["watchtower_shard", 1, game.REAGENT_ODDS], game.ACTION_BY_ID["fight_harpies"]["drops"])
def test_mining_turns_up_gems(self):
self.ann["xp"]["mining"] = game.XP_TABLE[15]
game.start_action(self.world, self.ann, "mine_iron", T0)
rock = game.ACTION_BY_ID["mine_iron"]
game.process_player(self.world, self.ann, T0 + game.action_time(self.world, self.ann, rock) + 0.1, Always())
self.assertEqual(self.ann["bank"]["garnet"], 1)
self.assertEqual(self.ann["bank"]["iron_ore"], 1)
def test_prospecting_cracks_ore_for_gems(self):
self.ann["xp"]["jewelcrafting"] = game.XP_TABLE[15]
self.ann["bank"] = {"iron_ore": 7}
game.start_action(self.world, self.ann, "prospect_garnet", T0)
summary = game.process_player(self.world, self.ann, T0 + 1000, Always())
self.assertEqual(self.ann["bank"], {"iron_ore": 2, "garnet": 1})
self.assertEqual(summary["stopped"], "Out of iron ore")
self.assertGreater(self.ann["xp"]["jewelcrafting"], game.XP_TABLE[15])
def test_jewellery_bonuses(self):
p = self.ann
p["xp"]["combat"] = game.XP_TABLE[20]
before = game.fighter(p, game.NO_BLESSING, {})
hp = game.max_hp(p)
p["equip"].update(ring="garnet_precision", amulet="garnet_vigour", trinket="garnet_hourglass")
after = game.fighter(p, game.NO_BLESSING, {})
self.assertAlmostEqual(after["accuracy"], before["accuracy"] * 1.08)
self.assertEqual(game.max_hp(p), hp + 10)
game.gain_xp(self.world, p, "mining", 100, T0)
self.assertAlmostEqual(p["xp"]["mining"], 103)
p["equip"]["ring"] = "garnet_fury"
self.assertAlmostEqual(game.fighter(p, game.NO_BLESSING, {})["crit"], before["crit"] + 0.03)
p["equip"]["ring"] = "garnet_might"
self.assertEqual(game.combat_power(p), game.combat_power({**p, "equip": {**p["equip"], "ring": None}}) + 4)
def test_miners_cut_jewels(self):
self.assertIn("jewelcrafting", game.CLASSES["miner"]["fast"])
self.assertIn("jewelcrafting", game.CLASSES["miner"]["craft"])
def test_gems_can_be_asked_for(self):
self.assertEqual(game.ORDER_RAW["sapphire"], "mine_mithril")
self.assertEqual(game.ORDER_RECIPES["emerald_warding"], "jc_emerald_warding")
def test_migration_adds_the_skill_and_slots(self):
self.world["version"] = 17
del self.ann["xp"]["jewelcrafting"]
for slot in ("ring", "amulet", "trinket"):
del self.ann["equip"][slot]
game.migrate(self.world, T0)
self.assertEqual(self.ann["xp"]["jewelcrafting"], 0)
self.assertEqual({slot: self.ann["equip"][slot] for slot in ("ring", "amulet", "trinket")},
{"ring": None, "amulet": None, "trinket": None})