Weapon styles: warhammer, sword and shield, staff, bow; trophies in recipes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-19 23:38:34 +01:00
parent 19ccab4ac3
commit 4cb6ff5ec0
6 changed files with 244 additions and 24 deletions

View file

@ -708,9 +708,10 @@ class TierTest(unittest.TestCase):
def test_every_tier_has_full_kit(self):
for key, *_ in game.METALS:
for piece in ("sword", "shield", "helmet", "legs", "body", "pickaxe", "axe", "hoe", "fishing_rod", "hunting_knife"):
for piece in ("sword", "warhammer", "helmet", "legs", "body", "pickaxe", "axe", "hoe", "fishing_rod", "hunting_knife"):
self.assertIn(f"{key}_{piece}", game.ITEMS)
self.assertIn(f"smith_{key}_{piece}", game.ACTION_BY_ID)
self.assertIn(f"make_{key}_shield", game.ACTION_BY_ID) # builders make shields
for *_, prefix, _label, _level, _armour in game.LEATHERS:
for piece in ("cap", "legs", "body"):
self.assertIn(f"{prefix}_{piece}", game.ITEMS)
@ -1317,6 +1318,62 @@ class TradeSkillsTest(unittest.TestCase):
self.assertNotIn("plot2", h["action"])
class WeaponStyleTest(unittest.TestCase):
def armed(self, cls, weapon, shield=None, level=12):
world = world_with(("pat", cls))
p = world["players"]["pat"]
p["xp"]["combat"] = game.XP_TABLE[level]
p["hp"] = game.max_hp(p)
p["equip"].update(weapon=weapon, shield=shield, body="iron_body", helmet="iron_helmet", legs="iron_legs")
return world, p
def test_each_trade_fights_its_own_monster_best(self):
styles = {"miner": "iron_warhammer", "builder": "iron_sword", "homesteader": "oak_staff", "ranger": "oak_bow"}
prey = {"miner": "fight_clay_golem", "builder": "fight_cave_troll", "homesteader": "fight_will_o_wisp",
"ranger": "fight_giant_bat"}
for cls, weapon in styles.items():
_world, p = self.armed(cls, weapon, "iron_shield" if cls == "builder" else None)
times = {target: game.fight_odds(p, game.ACTION_BY_ID[target])["kill_time"] for target in prey.values()}
self.assertEqual(min(times, key=times.get), prey[cls], cls)
def test_style_traits(self):
_w, swordsman = self.armed("builder", "iron_sword", "iron_shield")
_w, smith = self.armed("miner", "iron_warhammer")
_w, archer = self.armed("ranger", "oak_bow")
spec = lambda p: game.fighter(p, game.NO_BLESSING, {}, game.ACTION_BY_ID["fight_clay_golem"]["enemy"])
self.assertEqual(spec(swordsman)["block"], game.BLOCK_CHANCE)
self.assertEqual(spec(smith)["crit"], 0.10)
self.assertEqual(spec(smith)["weakness"], 1.5)
self.assertEqual(spec(archer)["weakness"], 0.5)
_w, other = self.armed("builder", "iron_warhammer")
self.assertGreater(spec(smith)["max_hit"], spec(other)["max_hit"]) # the trade's own weapon hits harder
world, archer = self.armed("ranger", "oak_bow")
fight = game.simulate_fight(world, archer, game.ACTION_BY_ID["fight_giant_bat"], random.Random(1))
self.assertEqual(fight["events"][0][1], "you") # the bow strikes first
def test_two_handed_weapons_leave_no_room_for_a_shield(self):
_w, p = self.armed("miner", "iron_warhammer")
self.assertEqual(game.equip_problem(p, "iron_shield"), "Your iron warhammer takes both hands")
self.assertTrue(game.ITEMS["oak_staff"]["two_handed"])
self.assertIsNone(game.equip_problem(self.armed("builder", "iron_sword")[1], "iron_shield"))
def test_weapons_past_copper_need_trophies(self):
for action_id, trophy in (("smith_iron_warhammer", "clay_core"), ("smith_iron_sword", "cave_troll_hide"),
("make_iron_shield", "cave_troll_hide"), ("brew_oak_staff", "wisp_essence"),
("lw_oak_bow", "bat_sinew"), ("smith_rune_warhammer", "runic_core")):
self.assertIn(trophy, game.ACTION_BY_ID[action_id]["inputs"], action_id)
for action_id in ("smith_copper_warhammer", "smith_copper_sword", "make_copper_shield",
"brew_wooden_staff", "lw_wooden_bow"):
self.assertFalse(any(item in game.TROPHIES for item in game.ACTION_BY_ID[action_id]["inputs"]), action_id)
def test_shield_smiths_stop_after_the_move(self):
world = world_with(("kay", "miner"))
world["version"] = 13
world["players"]["kay"]["action"] = {"id": "smith_iron_shield", "start": T0}
game.migrate(world, T0)
self.assertIsNone(world["players"]["kay"]["action"])
class FittingTest(unittest.TestCase):
def setUp(self):
self.world = world_with(("fred", "miner"))