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

@ -23,6 +23,14 @@ Alpha. One season, bandit raids plus two friendly events, six buildings.
one area per tier (Old Watchtower, Sunken Barrows, Iron Hills, Frostpeak, one area per tier (Old Watchtower, Sunken Barrows, Iron Hills, Frostpeak,
Dragon's Spine), each with a golem, a troll, a spirit and a flyer that drop Dragon's Spine), each with a golem, a troll, a spirit and a flyer that drop
trophies for stronger weapons, and a boss (the dragons at the top). trophies for stronger weapons, and a boss (the dragons at the top).
- **Weapons:** four styles, one per trade, and anyone can use any of them.
Sword and shield (2.4s swings, the shield blocks 15% of hits; swords from
Smithing, shields from Construction), warhammer (Smithing; slow, heavy,
twice the crits), staff (Herblore; accurate, ignores armour) and bow
(Leatherworking; fast, strikes first). The last three take both hands and
carry a shield's power. Your trade's weapon does 15% more damage. Golems
break under hammers, trolls fall to swords, spirits only fear staves, and
flyers fall to bows. Past copper, each weapon needs its tier's trophies.
- **Tiers:** six RuneScape-style tiers (copper, iron, steel, mithril, - **Tiers:** six RuneScape-style tiers (copper, iron, steel, mithril,
adamant, rune at levels 1–75) of ore, trees (up to enchanted) and hides (deer, adamant, rune at levels 1–75) of ore, trees (up to enchanted) and hides (deer,
boar and bear from hunting; green, blue and red dragonhide from fighting boar and bear from hunting; green, blue and red dragonhide from fighting

7
app.py
View file

@ -409,6 +409,13 @@ class Handler(BaseHTTPRequestHandler):
problem = game.equip_problem(player, item) problem = game.equip_problem(player, item)
if problem: if problem:
return problem return problem
shield = player["equip"].get("shield")
if spec.get("two_handed") and shield:
# Both hands on the weapon: the shield goes back to the bank.
if game.bank_room(self.store.world, player, shield) < 1:
return "No room in the bank for your shield"
player["bank"][shield] = player["bank"].get(shield, 0) + 1
player["equip"]["shield"] = None
game.bank_take(player, item, 1) game.bank_take(player, item, 1)
current = player["equip"][spec["slot"]] current = player["equip"][spec["slot"]]
if current: if current:

155
game.py
View file

@ -186,6 +186,22 @@ PLANKS = [("plank", "Plank"), ("oak_plank", "Oak plank"), ("willow_plank", "Will
for (_log, _name, _icon, _value, _action_id, _verb), (_plank, _plank_name) in zip(TREES, PLANKS): for (_log, _name, _icon, _value, _action_id, _verb), (_plank, _plank_name) in zip(TREES, PLANKS):
ITEMS[_log] = {"name": _name, "icon": _icon, "value": _value} ITEMS[_log] = {"name": _name, "icon": _icon, "value": _value}
ITEMS[_plank] = {"name": _plank_name, "icon": "🪚", "value": _value * 2 + 1} ITEMS[_plank] = {"name": _plank_name, "icon": "🪚", "value": _value * 2 + 1}
# Weapons: four styles, one per trade. The sword pairs with a shield; the
# warhammer, staff and bow take both hands, so they carry the shield's power too.
SWORD_POWER = next(piece[5] for piece in PIECES if piece[0] == "sword")
SHIELD_POWER = next(piece[5] for piece in PIECES if piece[0] == "shield")
TWO_HANDED_POWER = [sword + shield for sword, shield in zip(SWORD_POWER, SHIELD_POWER)]
WOODS = ["wooden", "oak", "willow", "maple", "yew", "magic"]
STAVES = ["Wooden staff", "Oak staff", "Willow staff", "Maple staff", "Yew staff", "Enchanted staff"]
BOWS = ["Shortbow", "Oak bow", "Willow bow", "Maple bow", "Yew bow", "Enchanted bow"]
for _tier, _metal in enumerate(METALS):
ITEMS[f"{_metal[0]}_sword"]["style"] = "sword"
_weapon = {"slot": "weapon", "power": TWO_HANDED_POWER[_tier], "tier": _tier, "two_handed": True,
"req": ["combat", EQUIP_LEVELS[_tier]], "value": round(5 * _metal[5] * 1.2)}
ITEMS[f"{_metal[0]}_warhammer"] = {"name": f"{_metal[1]} warhammer", "icon": "🔨", "style": "hammer", **_weapon}
ITEMS[f"{WOODS[_tier]}_staff"] = {"name": STAVES[_tier], "plural": STAVES[_tier].replace("staff", "staves"),
"icon": "🪄", "style": "staff", **_weapon}
ITEMS[f"{WOODS[_tier]}_bow"] = {"name": BOWS[_tier], "icon": "🏹", "style": "bow", **_weapon}
for _tier, (_raw, _leather, _prefix, _label, _level, _armour) in enumerate(LEATHERS): for _tier, (_raw, _leather, _prefix, _label, _level, _armour) in enumerate(LEATHERS):
ITEMS[_raw[0]] = {"name": _raw[1], "icon": _raw[2], "value": _raw[3]} ITEMS[_raw[0]] = {"name": _raw[1], "icon": _raw[2], "value": _raw[3]}
ITEMS[_leather[0]] = {"name": _leather[1], "icon": "🪢", "value": _leather[2]} ITEMS[_leather[0]] = {"name": _leather[1], "icon": "🪢", "value": _leather[2]}
@ -314,18 +330,21 @@ CLASSES = {
"bonus": "Mining and smithing 20% faster", "bonus": "Mining and smithing 20% faster",
"masterwork": "Masterwork: 1 in 10 smithing crafts make double", "masterwork": "Masterwork: 1 in 10 smithing crafts make double",
"signature": "Prospector: 1 in 10 mining trips bring back double", "signature": "Prospector: 1 in 10 mining trips bring back double",
"combat": "Warhammer: +15% damage with one. Slow, heavy, crushes golems",
}, },
"builder": { "builder": {
"name": "Builder", "icon": "🏗️", "fast": ["woodcutting", "construction"], "craft": ["construction"], "name": "Builder", "icon": "🏗️", "fast": ["woodcutting", "construction"], "craft": ["construction"],
"bonus": "Woodcutting and construction (masonry included) 20% faster", "bonus": "Woodcutting and construction (masonry included) 20% faster",
"masterwork": "Masterwork: 1 in 10 construction crafts make double", "masterwork": "Masterwork: 1 in 10 construction crafts make double",
"signature": "Foreman: +1 labour every time you work a building site", "signature": "Foreman: +1 labour every time you work a building site",
"combat": "Sword and shield: +15% damage with a sword. The shield blocks, and trolls fall to blades",
}, },
"homesteader": { "homesteader": {
"name": "Homesteader", "icon": "🌾", "fast": ["cooking", "herblore"], "craft": ["cooking", "herblore"], "name": "Homesteader", "icon": "🌾", "fast": ["cooking", "herblore"], "craft": ["cooking", "herblore"],
"bonus": "Cooking and herblore 20% faster. Two plots: farm one crop 30% faster, or two crops at once", "bonus": "Cooking and herblore 20% faster. Two plots: farm one crop 30% faster, or two crops at once",
"masterwork": "Masterwork: 1 in 10 cooking and herblore crafts make double", "masterwork": "Masterwork: 1 in 10 cooking and herblore crafts make double",
"signature": "Steady hand: potions you drink last 25% longer", "signature": "Steady hand: potions you drink last 25% longer",
"combat": "Staff: +15% damage with one. Rarely misses, ignores armour, and spirits fear it",
}, },
"ranger": { "ranger": {
"name": "Ranger", "icon": "🏹", "fast": ["hunting", "fishing", "leatherworking", "cooking"], "name": "Ranger", "icon": "🏹", "fast": ["hunting", "fishing", "leatherworking", "cooking"],
@ -333,6 +352,7 @@ CLASSES = {
"bonus": "Hunting, fishing, leatherworking and cooking 20% faster", "bonus": "Hunting, fishing, leatherworking and cooking 20% faster",
"masterwork": "Masterwork: 1 in 10 leatherworking and cooking crafts make double", "masterwork": "Masterwork: 1 in 10 leatherworking and cooking crafts make double",
"signature": "Pathfinder: your scouting gathers 50% more reconnaissance", "signature": "Pathfinder: your scouting gathers 50% more reconnaissance",
"combat": "Bow: +15% damage with one. Fast, strikes first, and brings down flyers",
}, },
} }
# Classes from before the trades, as a starting point until their player re-picks. # Classes from before the trades, as a starting point until their player re-picks.
@ -369,9 +389,16 @@ def _tiered_actions() -> list[dict]:
bars * piece_xp[tier], {f"{key}_bar": bars}, {hardware: made}, group="Hardware", bars * piece_xp[tier], {f"{key}_bar": bars}, {hardware: made}, group="Hardware",
city=city)) city=city))
for piece, _slot, noun, bars, offset, _power, _armour in PIECES: for piece, _slot, noun, bars, offset, _power, _armour in PIECES:
if piece == "shield":
continue # builders make shields now, in Construction
inputs = {f"{key}_bar": bars, **({trophy("troll", tier): tier} if piece == "sword" and tier else {})}
actions.append(_action(f"smith_{key}_{piece}", "smithing", f"{name} {noun}", TIER_LEVELS[tier] + offset, actions.append(_action(f"smith_{key}_{piece}", "smithing", f"{name} {noun}", TIER_LEVELS[tier] + offset,
25 + 5 * bars + 2 * tier, bars * piece_xp[tier], {f"{key}_bar": bars}, 25 + 5 * bars + 2 * tier, bars * piece_xp[tier], inputs,
{f"{key}_{piece}": 1}, group=name, city=city)) {f"{key}_{piece}": 1}, group=name, city=city))
actions.append(_action(f"smith_{key}_warhammer", "smithing", f"{name} warhammer", TIER_LEVELS[tier] + 6,
45 + 2 * tier, 4 * piece_xp[tier],
{f"{key}_bar": 3, PLANKS[tier][0]: 1, **({trophy("golem", tier): 2 + tier} if tier else {})},
{f"{key}_warhammer": 1}, group=name, city=city))
for tool, _icon in TOOLS.values(): for tool, _icon in TOOLS.values():
tool_id = f"{key}_{tool.replace(' ', '_')}" tool_id = f"{key}_{tool.replace(' ', '_')}"
actions.append(_action(f"smith_{tool_id}", "smithing", f"{name} {tool}", TIER_LEVELS[tier] + 3, actions.append(_action(f"smith_{tool_id}", "smithing", f"{name} {tool}", TIER_LEVELS[tier] + 3,
@ -406,10 +433,54 @@ def _tiered_actions() -> list[dict]:
CRIT_CHANCE = 0.05 CRIT_CHANCE = 0.05
CRIT_MULT = 1.5 CRIT_MULT = 1.5
RESPAWN = 3 # seconds before the next enemy turns up RESPAWN = 3 # seconds before the next enemy turns up
PLAYER_INTERVAL = 2.4 # seconds between your swings
MAX_FIGHT = 600 # a fight that drags on longer is broken off MAX_FIGHT = 600 # a fight that drags on longer is broken off
FLEE_BELOW = 0.2 # out of food and under this share of HP: get out FLEE_BELOW = 0.2 # out of food and under this share of HP: get out
# How each kind of weapon fights. Two-handed weapons carry the shield's power themselves.
STYLES = {
"sword": {"name": "sword", "interval": 2.4, "hit": 1.0, "accuracy": 1.0, "crit": 0.05},
"hammer": {"name": "warhammer", "interval": 3.6, "hit": 1.6, "accuracy": 0.95, "crit": 0.10},
"staff": {"name": "staff", "interval": 3.0, "hit": 1.15, "accuracy": 1.25, "crit": 0.05, "pierce": True},
"bow": {"name": "bow", "interval": 1.8, "hit": 0.75, "accuracy": 1.05, "crit": 0.05, "first": True},
}
CLASS_STYLE = {"miner": "hammer", "builder": "sword", "homesteader": "staff", "ranger": "bow"}
CLASS_STYLE_BONUS = 1.15 # damage with your own trade's weapon
BLOCK_CHANCE = 0.15 # a shield turns aside this share of hits
# Damage each style does to each kind of monster (1 when not listed).
WEAKNESS = {
"golem": {"hammer": 1.5, "bow": 0.5},
"troll": {"sword": 1.5},
"spirit": {"hammer": 0.5, "sword": 0.5, "bow": 0.5, "staff": 1.5},
"flyer": {"hammer": 0.5, "sword": 0.5, "bow": 1.5},
}
def trophy(kind: str, tier: int) -> str:
"""The trophy a tier's monster of this kind drops (tier 1 is the Old Watchtower)."""
return _slug(AREA_MONSTERS[kind][2][tier - 1])
def _weapon_actions() -> list[dict]:
"""Shields (Construction), staves (Herblore) and bows (Leatherworking); trophies past the first tier."""
actions = []
for tier, (key, name, *_rest) in enumerate(METALS):
plank, leather, herb = PLANKS[tier][0], LEATHERS[tier][1][0], HERBS[tier][0]
extra = lambda kind, count: {trophy(kind, tier): count} if tier else {}
actions.append(_action(f"make_{key}_shield", "construction", f"{name} shield", TIER_LEVELS[tier] + 5,
40 + 2 * tier, [10, 22, 36, 52, 70, 92][tier],
{plank: 3, leather: 2, f"{key}_bar": 1, **extra("troll", 1 + tier)},
{f"{key}_shield": 1}, group="Shields"))
actions.append(_action(f"brew_{WOODS[tier]}_staff", "herblore", STAVES[tier], TIER_LEVELS[tier] + 5,
45 + 2 * tier, [12, 26, 42, 60, 80, 105][tier],
{plank: 2, herb: 3, **extra("spirit", 2 + tier)}, {f"{WOODS[tier]}_staff": 1},
group="Staves"))
actions.append(_action(f"lw_{WOODS[tier]}_bow", "leatherworking", BOWS[tier], LEATHERS[tier][4] + 4,
40 + 2 * tier, [12, 26, 42, 60, 80, 105][tier],
{plank: 2, leather: 2, **extra("flyer", 2 + tier)}, {f"{WOODS[tier]}_bow": 1},
group="Bows"))
return actions
# kind: HP, seconds between swings, accuracy, evasion, max hit (multipliers), damage it shrugs off # kind: HP, seconds between swings, accuracy, evasion, max hit (multipliers), damage it shrugs off
MONSTER_KINDS = { MONSTER_KINDS = {
"human": (1.0, 2.6, 1.0, 1.0, 1.0, 0.0), "human": (1.0, 2.6, 1.0, 1.0, 1.0, 0.0),
@ -581,9 +652,9 @@ BUILDINGS = {
"barracks": { "barracks": {
"name": "Barracks", "icon": "⛺", "max": 5, "gold": 300, "name": "Barracks", "icon": "⛺", "max": 5, "gold": 300,
"base": {"logs": 300, "bricks": 200, "thatch": 200, "leather": 80, "copper_sword": 25, "provisions": 80, "copper_rivets": 60}, "base": {"logs": 300, "bricks": 200, "thatch": 200, "leather": 80, "copper_sword": 25, "provisions": 80, "copper_rivets": 60},
"advanced": {"iron_sword": 20, "hard_leather": 40}, "advanced": {"iron_bar": 60, "hard_leather": 40},
"late": {"steel_sword": 12, "oak_plank": 30, "hide_glue": 40}, "late": {"steel_bar": 40, "oak_plank": 30, "hide_glue": 40},
"final": {"mithril_sword": 8, "willow_plank": 25, "bear_leather": 40}, "final": {"mithril_bar": 25, "willow_plank": 25, "bear_leather": 40},
"effect": "Trains townsfolk as militia: more defence per citizen", "effect": "Trains townsfolk as militia: more defence per citizen",
}, },
"smithy": { "smithy": {
@ -671,7 +742,7 @@ RAID_TRAITS = ["lightly armoured, heavy on archers", "mounted and fast, few bows
# --- world --------------------------------------------------------------- # --- world ---------------------------------------------------------------
WORLD_VERSION = 13 WORLD_VERSION = 14
def new_world(now: float, speed: float = 1.0) -> dict: def new_world(now: float, speed: float = 1.0) -> dict:
@ -792,6 +863,14 @@ def migrate(world: dict, now: float | None = None) -> dict:
_fold_masonry(world) _fold_masonry(world)
_return_overfunding(world) _return_overfunding(world)
world["version"] = 13 world["version"] = 13
if world["version"] < 14:
# Shields moved from Smithing to Construction: anyone smithing them stops.
for player in world["players"].values():
action = player["action"]
if action and (action["id"] not in ACTION_BY_ID or action.get("resume", "") and action["resume"] not in ACTION_BY_ID):
stop(player, "Shields are made in Construction now")
_return_overfunding(world)
world["version"] = 14
return world return world
@ -1073,10 +1152,23 @@ def regen(world: dict, player: dict, now: float, boost: float = 1) -> None:
player["hp_at"] = now player["hp_at"] = now
def fighter(player: dict, blessed: dict, brew: dict) -> dict: def weapon_style(player: dict) -> str:
"""Your side of a fight: power from level and gear (plus prayers and potions) aims and hits; armour dodges and soaks.""" weapon = player["equip"].get("weapon")
return ITEMS[weapon].get("style", "sword") if weapon else "sword"
def fighter(player: dict, blessed: dict, brew: dict, enemy: dict | None = None) -> dict:
"""Your side of a fight: power from level and gear (plus prayers and potions) aims and hits, shaped by
the weapon's style, your trade and the enemy's weakness; armour dodges and soaks, a shield blocks."""
style_id = weapon_style(player)
style = STYLES[style_id]
power = combat_power(player) + blessed["power"] + brew.get("power", 0) power = combat_power(player) + blessed["power"] + brew.get("power", 0)
return {"interval": PLAYER_INTERVAL, "accuracy": 10 + 2 * power, "max_hit": max(2, round(2 + power / 3)), damage = style["hit"] * (CLASS_STYLE_BONUS if CLASS_STYLE.get(player["cls"]) == style_id else 1)
weakness = WEAKNESS.get(enemy["kind"], {}).get(style_id, 1) if enemy else 1
return {"style": style_id, "interval": style["interval"], "accuracy": (10 + 2 * power) * style["accuracy"],
"max_hit": max(2, round((2 + power / 3) * damage * weakness)), "crit": style["crit"],
"pierce": style.get("pierce", False), "first": style.get("first", False), "weakness": weakness,
"block": BLOCK_CHANCE if player["equip"].get("shield") else 0,
"evasion": 10 + 2 * (skill_level(player, "combat") + armour(player) // 2), "evasion": 10 + 2 * (skill_level(player, "combat") + armour(player) // 2),
"taken": (1 - damage_reduction(player)) * blessed["taken"] * (1 - brew.get("reduce", 0))} "taken": (1 - damage_reduction(player)) * blessed["taken"] * (1 - brew.get("reduce", 0))}
@ -1085,50 +1177,59 @@ def hit_chance(accuracy: float, evasion: float) -> float:
return min(0.95, max(0.05, accuracy / (accuracy + evasion) + 0.15)) return min(0.95, max(0.05, accuracy / (accuracy + evasion) + 0.15))
def _average_hit(max_hit: float) -> float: def _average_hit(max_hit: float, crit: float = CRIT_CHANCE) -> float:
return (1 - CRIT_CHANCE) * (max_hit + 1) / 2 + CRIT_CHANCE * max_hit * CRIT_MULT return (1 - crit) * (max_hit + 1) / 2 + crit * max_hit * CRIT_MULT
def fight_odds(player: dict, action: dict) -> dict: def fight_odds(player: dict, action: dict) -> dict:
"""What a fight against this enemy looks like on average, for the cards.""" """What a fight against this enemy looks like on average, for the cards."""
me, foe = fighter(player, blessing(player), potion_effect(player, "combat")), action["enemy"] foe = action["enemy"]
me = fighter(player, blessing(player), potion_effect(player, "combat"), foe)
hit, their_hit = hit_chance(me["accuracy"], foe["evasion"]), hit_chance(foe["accuracy"], me["evasion"]) hit, their_hit = hit_chance(me["accuracy"], foe["evasion"]), hit_chance(foe["accuracy"], me["evasion"])
dps = hit * _average_hit(me["max_hit"]) * (1 - foe["reduction"]) / me["interval"] shrug = 0 if me["pierce"] else foe["reduction"]
dps = hit * _average_hit(me["max_hit"], me["crit"]) * (1 - shrug) / me["interval"]
kill = foe["hp"] / dps kill = foe["hp"] / dps
hurt = their_hit * _average_hit(foe["max_hit"]) * me["taken"] / foe["interval"] * kill hurt = their_hit * (1 - me["block"]) * _average_hit(foe["max_hit"]) * me["taken"] / foe["interval"] * kill
return {"hit": round(hit, 2), "their_hit": round(their_hit, 2), "max_hit": me["max_hit"], return {"hit": round(hit, 2), "their_hit": round(their_hit, 2), "max_hit": me["max_hit"], "style": me["style"],
"their_max": max(1, round(foe["max_hit"] * me["taken"])), "kill_time": round(kill, 1), "damage": round(hurt, 1)} "weakness": me["weakness"], "their_max": max(1, round(foe["max_hit"] * me["taken"])),
"kill_time": round(kill, 1), "damage": round(hurt, 1)}
def simulate_fight(world: dict, player: dict, action: dict, rng: random.Random) -> dict: def simulate_fight(world: dict, player: dict, action: dict, rng: random.Random) -> dict:
"""Play out one fight swing by swing. Nothing changes until it's over: the result is applied then.""" """Play out one fight swing by swing. Nothing changes until it's over: the result is applied then."""
foe, blessed, brew = action["enemy"], blessing(player), potion_effect(player, "combat") foe, blessed, brew = action["enemy"], blessing(player), potion_effect(player, "combat")
me = fighter(player, blessed, brew) me = fighter(player, blessed, brew, foe)
shrug = 0 if me["pierce"] else foe["reduction"]
hit, their_hit = hit_chance(me["accuracy"], foe["evasion"]), hit_chance(foe["accuracy"], me["evasion"]) hit, their_hit = hit_chance(me["accuracy"], foe["evasion"]), hit_chance(foe["accuracy"], me["evasion"])
top, hp, foe_hp = max_hp(player), player["hp"], foe["hp"] top, hp, foe_hp = max_hp(player), player["hp"], foe["hp"]
pantry = {item: player["bank"][item] for item in edible(player)} pantry = {item: player["bank"][item] for item in edible(player)}
eaten, events, hurt = {}, [], 0 eaten, events, hurt = {}, [], 0
wind = blessed["wind"] and not (player["action"] or {}).get("wind_used") wind = blessed["wind"] and not (player["action"] or {}).get("wind_used")
pace = speed(world) pace = speed(world)
mine, theirs, result, t = me["interval"], foe["interval"], None, 0.0 # A bow looses its first arrow before the enemy closes in.
mine, theirs, result, t = (0.5 if me["first"] else me["interval"]), foe["interval"], None, 0.0
while result is None: while result is None:
t = min(mine, theirs) t = min(mine, theirs)
if t > MAX_FIGHT: if t > MAX_FIGHT:
result = "fled" result = "fled"
break break
crit = rng.random() < CRIT_CHANCE
if mine <= theirs: if mine <= theirs:
mine += me["interval"] mine += me["interval"]
crit = rng.random() < me["crit"]
landed = rng.random() < hit landed = rng.random() < hit
dealt = max(1, round((me["max_hit"] * CRIT_MULT if crit else rng.randint(1, me["max_hit"])) dealt = max(1, round((me["max_hit"] * CRIT_MULT if crit else rng.randint(1, me["max_hit"]))
* (1 - foe["reduction"]))) if landed else 0 * (1 - shrug))) if landed else 0
foe_hp = max(0, foe_hp - dealt) foe_hp = max(0, foe_hp - dealt)
events.append([round(t / pace, 2), "you", ("crit" if crit else "hit") if landed else "miss", dealt, round(hp), foe_hp]) events.append([round(t / pace, 2), "you", ("crit" if crit else "hit") if landed else "miss", dealt, round(hp), foe_hp])
if not foe_hp: if not foe_hp:
result = "won" result = "won"
continue continue
theirs += foe["interval"] theirs += foe["interval"]
crit = rng.random() < CRIT_CHANCE
landed = rng.random() < their_hit landed = rng.random() < their_hit
if landed and rng.random() < me["block"]:
events.append([round(t / pace, 2), "foe", "block", 0, max(0, round(hp)), foe_hp])
continue
dealt = max(1, round((foe["max_hit"] * CRIT_MULT if crit else rng.randint(1, foe["max_hit"])) * me["taken"])) if landed else 0 dealt = max(1, round((foe["max_hit"] * CRIT_MULT if crit else rng.randint(1, foe["max_hit"])) * me["taken"])) if landed else 0
hp -= dealt hp -= dealt
hurt += dealt hurt += dealt
@ -1151,7 +1252,7 @@ def simulate_fight(world: dict, player: dict, action: dict, rng: random.Random)
result = "fled" result = "fled"
return {"enemy": foe["name"], "enemy_hp": foe["hp"], "top": top, "start_hp": round(player["hp"]), return {"enemy": foe["name"], "enemy_hp": foe["hp"], "top": top, "start_hp": round(player["hp"]),
"hp": hp, "result": result, "end": round(t / pace, 2), "duration": (t + RESPAWN) / pace, "hp": hp, "result": result, "end": round(t / pace, 2), "duration": (t + RESPAWN) / pace,
"interval": me["interval"] / pace, "enemy_interval": foe["interval"] / pace, "events": events, "interval": me["interval"] / pace, "enemy_interval": foe["interval"] / pace, "events": events, "style": me["style"],
"eaten": eaten, "damage": hurt, "pp": blessed["cost"], "eaten": eaten, "damage": hurt, "pp": blessed["cost"],
"wind_used": blessed["wind"] and not wind and not (player["action"] or {}).get("wind_used")} "wind_used": blessed["wind"] and not wind and not (player["action"] or {}).get("wind_used")}
@ -1887,6 +1988,9 @@ def _wear_lines(broken: dict, arrows: int) -> list[str]:
def equip_problem(player: dict, item: str) -> str | None: def equip_problem(player: dict, item: str) -> str | None:
"""Why the player can't wear or use this yet, or None.""" """Why the player can't wear or use this yet, or None."""
weapon = player["equip"].get("weapon")
if ITEMS[item].get("slot") == "shield" and weapon and ITEMS[weapon].get("two_handed"):
return f"Your {ITEMS[weapon]['name'].lower()} takes both hands"
req = ITEMS[item].get("req") req = ITEMS[item].get("req")
if req and skill_level(player, req[0]) < req[1]: if req and skill_level(player, req[0]) < req[1]:
name = next(s["name"] for s in SKILLS if s["id"] == req[0]) name = next(s["name"] for s in SKILLS if s["id"] == req[0])
@ -2463,6 +2567,10 @@ FITTINGS = [
("enchanted_hearths", "Enchanted hearths", "houses", 4, 80, {"magic_plank": 50, "red_dragon_leather": 5, "adamant_chain": 6}, ("enchanted_hearths", "Enchanted hearths", "houses", 4, 80, {"magic_plank": 50, "red_dragon_leather": 5, "adamant_chain": 6},
"Everyone recovers HP twice as fast", "fireplace", "#a77be8"), "Everyone recovers HP twice as fast", "fireplace", "#a77be8"),
] ]
# Builders' shields, homesteaders' staves and rangers' bows, after each skill's other tabs.
for _weapon in _weapon_actions():
ACTIONS.append(_weapon)
ACTION_BY_ID[_weapon["id"]] = _weapon
FITTING_BY_ID = {} FITTING_BY_ID = {}
for _id, _name, _building, _blevel, _level, _inputs, _effect, _glyph, _tint in FITTINGS: for _id, _name, _building, _blevel, _level, _inputs, _effect, _glyph, _tint in FITTINGS:
FITTING_BY_ID[_id] = {"id": _id, "name": _name, "building": _building, "level": _blevel, "effect": _effect} FITTING_BY_ID[_id] = {"id": _id, "name": _name, "building": _building, "level": _blevel, "effect": _effect}
@ -3038,6 +3146,7 @@ PIECE_GLYPHS = {"sword": "pointy-sword", "shield": "round-shield", "helmet": "vi
TOOL_GLYPHS = {"pickaxe": "war-pick", "axe": "wood-axe", "hoe": "sickle", "fishing rod": "fishing-pole", TOOL_GLYPHS = {"pickaxe": "war-pick", "axe": "wood-axe", "hoe": "sickle", "fishing rod": "fishing-pole",
"hunting knife": "bowie-knife", "hammer": "claw-hammer"} "hunting knife": "bowie-knife", "hammer": "claw-hammer"}
LEATHER_GLYPHS = {"cap": "hood", "legs": "trousers", "body": "leather-vest"} LEATHER_GLYPHS = {"cap": "hood", "legs": "trousers", "body": "leather-vest"}
WEAPON_GLYPHS = {"hammer": "warhammer", "staff": "wizard-staff", "bow": "pocket-bow"}
HARDWARE_GLYPHS = ["screw", "nails", "door-handle", "metal-plate", "crossed-chains", "padlock"] HARDWARE_GLYPHS = ["screw", "nails", "door-handle", "metal-plate", "crossed-chains", "padlock"]
GLYPHS = { GLYPHS = {
"stone": ("stone-block", "#a8a29e"), "wheat": ("wheat", "#e3c060"), "vegetables": ("carrot", "#f08a3c"), "stone": ("stone-block", "#a8a29e"), "wheat": ("wheat", "#e3c060"), "vegetables": ("carrot", "#f08a3c"),
@ -3109,6 +3218,9 @@ def _assign_glyphs() -> None:
ITEMS[ore[0]].update(glyph="ore", tint=tint) ITEMS[ore[0]].update(glyph="ore", tint=tint)
ITEMS[f"{key}_bar"].update(glyph="metal-bar", tint=tint) ITEMS[f"{key}_bar"].update(glyph="metal-bar", tint=tint)
ITEMS[HARDWARE[tier][0]].update(glyph=HARDWARE_GLYPHS[tier], tint=tint) ITEMS[HARDWARE[tier][0]].update(glyph=HARDWARE_GLYPHS[tier], tint=tint)
ITEMS[f"{key}_warhammer"].update(glyph=WEAPON_GLYPHS["hammer"], tint=tint)
ITEMS[f"{WOODS[tier]}_staff"].update(glyph=WEAPON_GLYPHS["staff"], tint=WOOD_TINTS[tier])
ITEMS[f"{WOODS[tier]}_bow"].update(glyph=WEAPON_GLYPHS["bow"], tint=WOOD_TINTS[tier])
for piece, glyph in PIECE_GLYPHS.items(): for piece, glyph in PIECE_GLYPHS.items():
ITEMS[f"{key}_{piece}"].update(glyph=glyph, tint=tint) ITEMS[f"{key}_{piece}"].update(glyph=glyph, tint=tint)
for tool, glyph in TOOL_GLYPHS.items(): for tool, glyph in TOOL_GLYPHS.items():
@ -3176,5 +3288,6 @@ def content() -> dict:
"prayers": [{**prayer, "text": describe_prayer(prayer)} for prayer in PRAYERS], "max_prayers": MAX_PRAYERS, "prayers": [{**prayer, "text": describe_prayer(prayer)} for prayer in PRAYERS], "max_prayers": MAX_PRAYERS,
"potion_charges": POTION_CHARGES, "problems": PROBLEMS, "fittings": list(FITTING_BY_ID.values()), "potion_charges": POTION_CHARGES, "problems": PROBLEMS, "fittings": list(FITTING_BY_ID.values()),
"equip_slots": EQUIP_SLOTS, "eat_below": EAT_BELOW, "class_speed": CLASS_SPEED, "equip_slots": EQUIP_SLOTS, "eat_below": EAT_BELOW, "class_speed": CLASS_SPEED,
"styles": STYLES, "weakness": WEAKNESS, "class_style": CLASS_STYLE, "block_chance": BLOCK_CHANCE,
"regen_per_hour": REGEN_PER_HOUR, "regen_per_hour": REGEN_PER_HOUR,
} }

View file

@ -441,6 +441,17 @@ function toolPanel(skill) {
: `<span class="muted">No tool. A smith can make you one that speeds this up.</span>`}</div>`; : `<span class="muted">No tool. A smith can make you one that speeds this up.</span>`}</div>`;
} }
// What a monster is weak to and shrugs off, and how your weapon fares against it.
function weaknessLine(kind, odds) {
const table = C.weakness[kind];
if (!table) return "";
const names = (pick) => Object.entries(table).filter(([, m]) => pick(m)).map(([s]) => `${C.styles[s].name}s`).join(", ");
const weak = names((m) => m > 1), tough = names((m) => m < 1);
const yours = odds.weakness > 1 ? ` · <b class="good">your ${C.styles[odds.style].name} hits it hard</b>`
: odds.weakness < 1 ? ` · <b class="bad">your ${C.styles[odds.style].name} does half damage</b>` : "";
return `<div class="small muted">${weak ? `Weak to ${weak}` : ""}${weak && tough ? " · " : ""}${tough ? `shrugs off ${tough}` : ""}${yours}</div>`;
}
// The fight in progress, replayed from the server's swing-by-swing record. // The fight in progress, replayed from the server's swing-by-swing record.
function fightPanel() { function fightPanel() {
const f = S.me.action?.fight; const f = S.me.action?.fight;
@ -461,6 +472,7 @@ function fightLine(e, enemy) {
const foe = esc(enemy); const foe = esc(enemy);
if (kind === "eat") return `<li class="good">You eat ${esc(item(food).name.toLowerCase())} (+${amount})</li>`; if (kind === "eat") return `<li class="good">You eat ${esc(item(food).name.toLowerCase())} (+${amount})</li>`;
if (kind === "wind") return `<li class="good">Second wind! Back on your feet</li>`; if (kind === "wind") return `<li class="good">Second wind! Back on your feet</li>`;
if (kind === "block") return `<li class="good">You block ${foe}'s blow</li>`;
if (who === "you") return kind === "miss" ? `<li class="muted">You miss</li>` : `<li>You ${kind === "crit" ? "<b>crit</b>" : "hit"} for <b>${amount}</b></li>`; if (who === "you") return kind === "miss" ? `<li class="muted">You miss</li>` : `<li>You ${kind === "crit" ? "<b>crit</b>" : "hit"} for <b>${amount}</b></li>`;
return kind === "miss" ? `<li class="muted">${foe} misses</li>` : `<li class="bad">${foe} ${kind === "crit" ? "<b>crits</b>" : "hits"} you for <b>${amount}</b></li>`; return kind === "miss" ? `<li class="muted">${foe} misses</li>` : `<li class="bad">${foe} ${kind === "crit" ? "<b>crits</b>" : "hits"} you for <b>${amount}</b></li>`;
} }
@ -498,6 +510,19 @@ function animateFight(now) {
}); });
} }
// How you fight with what's in your hands, and what your trade fights best with.
function styleNote(me) {
const weapon = me.equip.weapon, styleId = (weapon && item(weapon).style) || "sword", st = C.styles[styleId];
const own = C.class_style[me.cls], traits = {
sword: `a swing every ${st.interval}s${me.equip.shield ? `, and your shield blocks ${Math.round(C.block_chance * 100)}% of hits` : ""}`,
hammer: `slow (${st.interval}s) heavy blows, twice the crits`,
staff: `a cast every ${st.interval}s that rarely misses and goes through armour`,
bow: `fast (${st.interval}s), and you shoot first`,
};
return `<p class="small">Fighting with ${weapon ? `a ${esc(st.name)}` : "your fists"}: ${traits[styleId]}.
${own === styleId ? `<b class="good">Your trade's weapon: +15% damage.</b>` : `As a ${esc(C.classes[me.cls].name.toLowerCase())} you hit 15% harder with a ${esc(C.styles[own].name)}.`}</p>`;
}
function combatPanel() { function combatPanel() {
const me = S.me; const me = S.me;
const stat = (id) => [item(id).power && `+${item(id).power} power`, item(id).armour && `+${item(id).armour} armour`].filter(Boolean).join(", "); const stat = (id) => [item(id).power && `+${item(id).power} power`, item(id).armour && `+${item(id).armour} armour`].filter(Boolean).join(", ");
@ -524,6 +549,7 @@ function combatPanel() {
<div class="panel"><h2>Equipment</h2> <div class="panel"><h2>Equipment</h2>
<div class="gear">${slot("weapon", "weapon")}${slot("shield", "shield")}${slot("helmet", "helmet")}${slot("body", "body armour")}${slot("legs", "leg armour")}</div> <div class="gear">${slot("weapon", "weapon")}${slot("shield", "shield")}${slot("helmet", "helmet")}${slot("body", "body armour")}${slot("legs", "leg armour")}</div>
<p class="small muted">Power ${me.power} (level + weapon + shield + half your armour) · armour ${me.armour} takes ${Math.round(me.reduction * 100)}% off the damage you take. Equip gear from the bank.</p> <p class="small muted">Power ${me.power} (level + weapon + shield + half your armour) · armour ${me.armour} takes ${Math.round(me.reduction * 100)}% off the damage you take. Equip gear from the bank.</p>
${styleNote(me)}
</div></div>`; </div></div>`;
} }
@ -534,6 +560,10 @@ function itemStats(id) {
if (it.heal) parts.push(`❤️ Heals ${it.heal}`); if (it.heal) parts.push(`❤️ Heals ${it.heal}`);
if (it.food) parts.push(`feeds ${it.food} ${it.food === 1 ? "person" : "people"} for two days`); if (it.food) parts.push(`feeds ${it.food} ${it.food === 1 ? "person" : "people"} for two days`);
if (it.power) parts.push(`+${it.power} power`); if (it.power) parts.push(`+${it.power} power`);
if (it.style) {
const st = C.styles[it.style], trade = Object.entries(C.class_style).find(([, s]) => s === it.style)?.[0];
parts.push(`${it.two_handed ? "two-handed " : ""}${st.name}, a swing every ${st.interval}s${trade ? ` (the ${C.classes[trade].name.toLowerCase()}'s weapon)` : ""}`);
}
if (it.armour) parts.push(`+${it.armour} armour`); if (it.armour) parts.push(`+${it.armour} armour`);
if (it.tool) parts.push(`${Math.round(it.speed * 100)}% faster ${skillOf(it.tool).name.toLowerCase()}`); if (it.tool) parts.push(`${Math.round(it.speed * 100)}% faster ${skillOf(it.tool).name.toLowerCase()}`);
if (it.req && it.req[1] > 1) parts.push(`needs ${skillOf(it.req[0]).name.toLowerCase()} ${it.req[1]}`); if (it.req && it.req[1] > 1) parts.push(`needs ${skillOf(it.req[0]).name.toLowerCase()} ${it.req[1]}`);
@ -569,7 +599,8 @@ function actionCard(a) {
const o = me.fight_odds[a.id], e = a.enemy, pct = (x) => `${Math.round(x * 100)}%`; const o = me.fight_odds[a.id], e = a.enemy, pct = (x) => `${Math.round(x * 100)}%`;
extra = `<div class="small">${HEART} ${fmt(e.hp)} HP · hits up to <b>${o.their_max}</b> every ${e.interval}s${e.boss ? ` · <span class="tag warn">Boss</span>` : ""}</div> extra = `<div class="small">${HEART} ${fmt(e.hp)} HP · hits up to <b>${o.their_max}</b> every ${e.interval}s${e.boss ? ` · <span class="tag warn">Boss</span>` : ""}</div>
<div class="small">You land <b>${pct(o.hit)}</b> of swings (up to ${o.max_hit}) · it lands <b>${pct(o.their_hit)}</b></div> <div class="small">You land <b>${pct(o.hit)}</b> of swings (up to ${o.max_hit}) · it lands <b>${pct(o.their_hit)}</b></div>
<div class="small">About <b>${dur(o.kill_time)}</b> a kill, <b>${Math.round(o.damage)}</b> damage taken${a.gold ? ` · ${a.gold} gold` : ""}</div>`; <div class="small">About <b>${dur(o.kill_time)}</b> a kill, <b>${Math.round(o.damage)}</b> damage taken${a.gold ? ` · ${a.gold} gold` : ""}</div>
${weaknessLine(e.kind, o)}`;
if (a.drops) io += a.drops.map(([id, q, odds]) => `<span class="item-chip" title="${esc(item(id).name)}: ${Math.round(odds * 100)}% chance">${item(id).icon} ${q} <span class="have">${Math.round(odds * 100)}%</span></span>`).join(""); if (a.drops) io += a.drops.map(([id, q, odds]) => `<span class="item-chip" title="${esc(item(id).name)}: ${Math.round(odds * 100)}% chance">${item(id).icon} ${q} <span class="have">${Math.round(odds * 100)}%</span></span>`).join("");
if (a.special === "sabotage") extra += `<div class="small muted">Each win weakens the coming raid by 3%, up to 30%.</div>`; if (a.special === "sabotage") extra += `<div class="small muted">Each win weakens the coming raid by 3%, up to 30%.</div>`;
} }
@ -1068,6 +1099,7 @@ function characterSheet(uid) {
<p class="small">${esc(cls.bonus)}.</p> <p class="small">${esc(cls.bonus)}.</p>
<p class="small">${esc(cls.masterwork)}.</p> <p class="small">${esc(cls.masterwork)}.</p>
<p class="small">${esc(cls.signature)}.</p> <p class="small">${esc(cls.signature)}.</p>
<p class="small">${esc(cls.combat)}.</p>
</div> </div>
<div class="panel"><h2>Equipment</h2> <div class="panel"><h2>Equipment</h2>
<div class="sheet-gear">${Object.entries(SLOT_NAMES).map(([slot, label]) => gearSlot(slot, label, "Nothing")).join("")}</div> <div class="sheet-gear">${Object.entries(SLOT_NAMES).map(([slot, label]) => gearSlot(slot, label, "Nothing")).join("")}</div>
@ -1085,7 +1117,7 @@ function characterSheet(uid) {
function classCards() { function classCards() {
return Object.entries(C.classes).map(([id, c]) => ` return Object.entries(C.classes).map(([id, c]) => `
<button class="class-card ${pickedClass === id ? "on" : ""}" data-class="${id}"> <button class="class-card ${pickedClass === id ? "on" : ""}" data-class="${id}">
<span class="ico">${c.icon}</span><span><b>${c.name}</b><p>${esc(c.bonus)}.</p><p>${esc(c.masterwork)}.</p><p>${esc(c.signature)}.</p></span> <span class="ico">${c.icon}</span><span><b>${c.name}</b><p>${esc(c.bonus)}.</p><p>${esc(c.masterwork)}.</p><p>${esc(c.signature)}.</p><p>${esc(c.combat)}.</p></span>
</button>`).join(""); </button>`).join("");
} }

View file

@ -89,6 +89,7 @@
<symbol id="padlock" viewBox="0 0 512 512"><path fill="currentColor" d="M254.28 17.313c-81.048 0-146.624 65.484-146.624 146.406V236h49.594v-69.094c0-53.658 43.47-97.187 97.03-97.187c53.563 0 97.032 44.744 97.032 97.186V236h49.594v-72.28c0-78.856-65.717-146.407-146.625-146.407zM85.157 254.688c-14.61 22.827-22.844 49.148-22.844 76.78c0 88.358 84.97 161.5 191.97 161.5c106.998 0 191.968-73.142 191.968-161.5c0-27.635-8.26-53.95-22.875-76.78H85.155zM254 278.625c22.34 0 40.875 17.94 40.875 40.28c0 16.756-10.6 31.23-25.125 37.376l32.72 98.126h-96.376l32.125-98.125c-14.526-6.145-24.532-20.62-24.532-37.374c0-22.338 17.972-40.28 40.312-40.28z"/></symbol> <symbol id="padlock" viewBox="0 0 512 512"><path fill="currentColor" d="M254.28 17.313c-81.048 0-146.624 65.484-146.624 146.406V236h49.594v-69.094c0-53.658 43.47-97.187 97.03-97.187c53.563 0 97.032 44.744 97.032 97.186V236h49.594v-72.28c0-78.856-65.717-146.407-146.625-146.407zM85.157 254.688c-14.61 22.827-22.844 49.148-22.844 76.78c0 88.358 84.97 161.5 191.97 161.5c106.998 0 191.968-73.142 191.968-161.5c0-27.635-8.26-53.95-22.875-76.78H85.155zM254 278.625c22.34 0 40.875 17.94 40.875 40.28c0 16.756-10.6 31.23-25.125 37.376l32.72 98.126h-96.376l32.125-98.125c-14.526-6.145-24.532-20.62-24.532-37.374c0-22.338 17.972-40.28 40.312-40.28z"/></symbol>
<symbol id="palisade" viewBox="0 0 512 512"><path fill="currentColor" d="m112 144.836l-9 48V279h18v-86.164zm36 0l-9 48V279h18v-86.164zm216 0l-9 48V279h18v-86.164zm36 0l-9 48V279h18v-86.164zm-360 64l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm108 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm108 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zM18 297v16h138.96v-16zm156.96 0v16h162.005v-16zm180.005 0v16H494v-16zM31 331v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331z"/></symbol> <symbol id="palisade" viewBox="0 0 512 512"><path fill="currentColor" d="m112 144.836l-9 48V279h18v-86.164zm36 0l-9 48V279h18v-86.164zm216 0l-9 48V279h18v-86.164zm36 0l-9 48V279h18v-86.164zm-360 64l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm108 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zm108 0l-9 48V279h18v-22.164zm36 0l-9 48V279h18v-22.164zM18 297v16h138.96v-16zm156.96 0v16h162.005v-16zm180.005 0v16H494v-16zM31 331v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331zm36 0v156h18V331z"/></symbol>
<symbol id="planks" viewBox="0 0 512 512"><path fill="currentColor" d="M360.602 74.52L63.272 349.44h54.5l42.94-37.573l2.683 37.572h13.468l113.14-123.354c.983-12.407 6.178-21.43 13.087-26.443c6.91-5.017 13.84-6.686 19.08-8.633l62.687-68.35l13.266 12.168l-65.516 71.434l-1.826.76c-7.4 3.094-13.675 4.69-17.116 7.19c-3.44 2.497-5.765 5.124-5.875 15.702l-.036 3.447l-106.467 116.08h33.736L471.098 74.52h-72.37l.637.644l-193.668 191.188c-1.248 8.702-6.653 15.696-12.613 20.435c-6.888 5.477-14.79 9.182-21.656 12.89l-8.555-15.835c7.352-3.972 14.477-7.54 19.008-11.143c4.532-3.603 6.167-6.01 6.102-10.253l-.058-3.843L374.394 74.52zm99.843 40.25L243.357 367.58H225.13l-47.71 49.975l-13.02-12.43l35.846-37.545h-53.742l-1.287-18.05l-20.63 18.05h-18.04l-73.12 69.89h29.778c12.26-14.002 18.418-24.828 27.223-34.67c9.07-10.14 21.11-18.166 41.988-23.89l4.76 17.36c-18.702 5.126-26.09 10.433-33.332 18.53c-5.058 5.653-10.032 13.24-17.342 22.67H210.28l271.43-322.7zM129.97 403.682a9 9 0 0 1 8.202 13.287c-1.728 3.296-3.94 7.49-8.033 11.182c-4.094 3.692-10.005 6.357-17.07 7.06a9 9 0 1 1-1.78-17.913c4.02-.4 5.47-1.32 6.792-2.513c1.32-1.192 2.576-3.18 4.147-6.176a9 9 0 0 1 7.74-4.928z"/></symbol> <symbol id="planks" viewBox="0 0 512 512"><path fill="currentColor" d="M360.602 74.52L63.272 349.44h54.5l42.94-37.573l2.683 37.572h13.468l113.14-123.354c.983-12.407 6.178-21.43 13.087-26.443c6.91-5.017 13.84-6.686 19.08-8.633l62.687-68.35l13.266 12.168l-65.516 71.434l-1.826.76c-7.4 3.094-13.675 4.69-17.116 7.19c-3.44 2.497-5.765 5.124-5.875 15.702l-.036 3.447l-106.467 116.08h33.736L471.098 74.52h-72.37l.637.644l-193.668 191.188c-1.248 8.702-6.653 15.696-12.613 20.435c-6.888 5.477-14.79 9.182-21.656 12.89l-8.555-15.835c7.352-3.972 14.477-7.54 19.008-11.143c4.532-3.603 6.167-6.01 6.102-10.253l-.058-3.843L374.394 74.52zm99.843 40.25L243.357 367.58H225.13l-47.71 49.975l-13.02-12.43l35.846-37.545h-53.742l-1.287-18.05l-20.63 18.05h-18.04l-73.12 69.89h29.778c12.26-14.002 18.418-24.828 27.223-34.67c9.07-10.14 21.11-18.166 41.988-23.89l4.76 17.36c-18.702 5.126-26.09 10.433-33.332 18.53c-5.058 5.653-10.032 13.24-17.342 22.67H210.28l271.43-322.7zM129.97 403.682a9 9 0 0 1 8.202 13.287c-1.728 3.296-3.94 7.49-8.033 11.182c-4.094 3.692-10.005 6.357-17.07 7.06a9 9 0 1 1-1.78-17.913c4.02-.4 5.47-1.32 6.792-2.513c1.32-1.192 2.576-3.18 4.147-6.176a9 9 0 0 1 7.74-4.928z"/></symbol>
<symbol id="pocket-bow" viewBox="0 0 512 512"><path fill="currentColor" d="m77.85 11.848l9.535 70.648l-69.418-11.174l41.508 56.07l-11.127 322.715c-11.712 13.235-20.716 28.85-25.823 47.914c74.198-55.834 152.88-71.602 223.606-101.383l-35.913-35.914c-53.122 25.232-105.774 42.49-142.547 71.347l9.674-280.54l8.06 10.888l2.2 4.47h71.304L358.723 394.03c15.618-13.627 29.605-28.41 42.66-44.645l-229.877-193.78V84.226l-11.86-9.165l273.594-10.66c-29.99 36.36-46.84 89.07-71.39 142.416l36.558 36.56c29.22-70.24 45.014-148.09 100.262-221.507c-18.54 4.97-33.69 13.015-46.604 23.603l-.02-.506l-315.437 12.29zm24.613 42.638l50.355 38.916v54.795H99.236l-.607-.146l-38.357-50.988l49 7.89l-6.81-50.466zm248.103 167.48a369 369 0 0 1-26.586 37.727l30.727 25.903c11.16-8.75 22.568-17.176 34.06-25.432l-38.2-38.2zm100.006 89.74C414.826 368.52 375.184 412.43 315.88 447.67c59.143 20.683 118.488 37.302 178.8 43.98c-8.706-60.66-23.977-120.562-44.108-179.94zm-184.08 5.774c-13.42 10.98-27.58 21.186-42.414 30.674l37.47 37.47c8.748-14.57 18.62-27.954 29.327-40.43z"/></symbol>
<symbol id="pointy-sword" viewBox="0 0 512 512"><path fill="currentColor" d="M45.95 14.553c-19.38.81-30.594 11.357-30.282 30.283l19.768 30.78c4.43-1.213 9.36-3.838 14.248-7.335l42.474 59.935c-17.018 20.83-31.258 44.44-42.71 70.836l26.55 26.552c11.275-23.6 24.634-44.826 39.918-63.864l210.82 297.475l166.807 33.213L460.33 325.62L162.78 114.745c19.907-16.108 41.842-29.91 65.652-41.578l-26.553-26.55c-27.206 11.803-51.442 26.576-72.735 44.292L69.39 48.56c3.443-4.823 6.062-9.735 7.342-14.242l-30.78-19.765zm400.84 86.933v.008l.003-.008zm0 .008l-28.028 124.97l-25.116-80.593l-18.105 70.667l-26.862-49.64l-.584 57.818l128.484 91.69l15.184 87.017l-1.168-186.885l-34.457 39.713l-9.346-154.756zm-300.95 27.98l222.224 196.368l25.645 66.75l-66.75-25.645L130.6 144.734a309 309 0 0 1 15.238-15.26zm32.305 196.274v.004h.005zm.005.004l28.028 22.775l-36.21 4.088l57.82 19.272l-105.706 4.09l115.05 27.45L136.1 422.114l127.316 25.696l-67.164 43.803l208.494 1.752l-87.017-15.185l-104.54-150.676l-35.037-1.752z"/></symbol> <symbol id="pointy-sword" viewBox="0 0 512 512"><path fill="currentColor" d="M45.95 14.553c-19.38.81-30.594 11.357-30.282 30.283l19.768 30.78c4.43-1.213 9.36-3.838 14.248-7.335l42.474 59.935c-17.018 20.83-31.258 44.44-42.71 70.836l26.55 26.552c11.275-23.6 24.634-44.826 39.918-63.864l210.82 297.475l166.807 33.213L460.33 325.62L162.78 114.745c19.907-16.108 41.842-29.91 65.652-41.578l-26.553-26.55c-27.206 11.803-51.442 26.576-72.735 44.292L69.39 48.56c3.443-4.823 6.062-9.735 7.342-14.242l-30.78-19.765zm400.84 86.933v.008l.003-.008zm0 .008l-28.028 124.97l-25.116-80.593l-18.105 70.667l-26.862-49.64l-.584 57.818l128.484 91.69l15.184 87.017l-1.168-186.885l-34.457 39.713l-9.346-154.756zm-300.95 27.98l222.224 196.368l25.645 66.75l-66.75-25.645L130.6 144.734a309 309 0 0 1 15.238-15.26zm32.305 196.274v.004h.005zm.005.004l28.028 22.775l-36.21 4.088l57.82 19.272l-105.706 4.09l115.05 27.45L136.1 422.114l127.316 25.696l-67.164 43.803l208.494 1.752l-87.017-15.185l-104.54-150.676l-35.037-1.752z"/></symbol>
<symbol id="prayer" viewBox="0 0 512 512"><path fill="currentColor" d="M261.78 18.063c-52.004 0-94.686 45.7-94.686 103.156c0 57.455 42.682 103.155 94.687 103.155c52.007 0 94.72-45.7 94.72-103.156s-42.713-103.157-94.72-103.157zM203 159.655c13.276 3.67 26.394 6.046 39.375 7.22v18.75c-14.674-1.21-29.464-3.85-44.375-7.97zm117.375 0l4.906 18.03c-14.452 3.938-29.08 6.583-43.874 7.845v-18.718c13.085-1.223 26.055-3.638 38.97-7.156zM160.22 175.344c-75.308 50.797-110.604 125.208-116.282 220h.218a25 25 0 0 0-.562 5.28c0 13.808 11.19 25 25 25c.22 0 .436-.025.656-.03v.22l179.438-.002V302.406c-25.58 4.82-45.22 28.49-45.22 62.594v9.344H103.096v-18.688h12.718c3.664-35.178 26.522-77.998 45.343-101.344l14.53 11.72c-15.618 19.373-36.603 61.664-40.905 89.624h50.47c4.04-42.08 35.168-72.875 73.22-72.875c34.98 0 68.653 28.958 73.905 72.876h55.75c-5.412-28.305-26.53-70.32-42.094-89.625l14.564-11.717c18.885 23.424 41.643 66.485 46.562 101.343h10.563v18.688H314.593l-.25-9.094c-1.02-35.656-23.57-58.234-46.97-62.875v123.438H448.03v-.22c.22.006.436.032.658.032c13.81 0 25-11.193 25-25c0-2.092-.266-4.12-.75-6.063c-5.566-92.605-39.022-165.662-111.032-216.218c-19.026 38.355-56.592 64.72-100.125 64.72c-44.662 0-83.047-27.74-101.56-67.72zM140.374 444.5l9.188 47.5h220.562l8.47-47.5z"/></symbol> <symbol id="prayer" viewBox="0 0 512 512"><path fill="currentColor" d="M261.78 18.063c-52.004 0-94.686 45.7-94.686 103.156c0 57.455 42.682 103.155 94.687 103.155c52.007 0 94.72-45.7 94.72-103.156s-42.713-103.157-94.72-103.157zM203 159.655c13.276 3.67 26.394 6.046 39.375 7.22v18.75c-14.674-1.21-29.464-3.85-44.375-7.97zm117.375 0l4.906 18.03c-14.452 3.938-29.08 6.583-43.874 7.845v-18.718c13.085-1.223 26.055-3.638 38.97-7.156zM160.22 175.344c-75.308 50.797-110.604 125.208-116.282 220h.218a25 25 0 0 0-.562 5.28c0 13.808 11.19 25 25 25c.22 0 .436-.025.656-.03v.22l179.438-.002V302.406c-25.58 4.82-45.22 28.49-45.22 62.594v9.344H103.096v-18.688h12.718c3.664-35.178 26.522-77.998 45.343-101.344l14.53 11.72c-15.618 19.373-36.603 61.664-40.905 89.624h50.47c4.04-42.08 35.168-72.875 73.22-72.875c34.98 0 68.653 28.958 73.905 72.876h55.75c-5.412-28.305-26.53-70.32-42.094-89.625l14.564-11.717c18.885 23.424 41.643 66.485 46.562 101.343h10.563v18.688H314.593l-.25-9.094c-1.02-35.656-23.57-58.234-46.97-62.875v123.438H448.03v-.22c.22.006.436.032.658.032c13.81 0 25-11.193 25-25c0-2.092-.266-4.12-.75-6.063c-5.566-92.605-39.022-165.662-111.032-216.218c-19.026 38.355-56.592 64.72-100.125 64.72c-44.662 0-83.047-27.74-101.56-67.72zM140.374 444.5l9.188 47.5h220.562l8.47-47.5z"/></symbol>
<symbol id="rat" viewBox="0 0 512 512"><path fill="currentColor" d="M433.5 31.6c-8.5 0-15.1 6.58-15.1 14.81s6.6 14.81 15.1 14.81s15.1-6.58 15.1-14.81S442 31.6 433.5 31.6M267 59.05c6.6 15.84 17.1 18.03 31.1 24.77c-11.2 20.98-23.2 51.08-43.5 59.28c-64.7 26.1-98.7 58.3-112.3 98.7c-13.1 39-7 87.2 13.3 145.4c61.8 4.9 127.3 9.2 159.4 2.8c-1.3-4.4-5.8-7.5-8.6-9c-28.5-9.8-45.2-10.9-71.5-12l1.1-9.6c2.2-19.6.4-44.3-7.7-61.3c-4.1-8.5-9.5-14.9-16.5-18.8s-15.8-5.7-28.4-3.3l-3.2-17.8c13.5-2.4 29.4-.6 40.4 5.4c10.9 6.1 18.7 15.8 23.9 26.7c9.1 18.9 11.1 41.6 9.9 61.8c10 .6 18.9 1.6 26.8 2.9c19.2-30.7 37-60.4 39.5-90.7c-13.8-4-32.4-10.7-34.3-24.4c-2.7-19.6 3.6-45 19.3-55.5c-1 27.8-4.3 43.9-2.3 49.7c5.8 10.9 30.3 15.2 40.1 17.4v.1c17.4 4.8 31.9 7 34.8 25.6c18.2-29.5-14.4-45-36.2-54.5l-.1-5.8c-.3-23.5 5.5-39.4 13.5-53.1c8-13.6 17.7-25 26.9-43.2v-.1c-9.4-1.3-19.4-.1-27.1 1.3c5.7-19.9 23.2-23.73 38.6-16.1c5.9-8.3 13.4-18.83 24.9-29.96c-12.7-9.39-19.9-20.4-18.1-33.92c-28-3.4-57.4-4.45-78.6 9.84l-4-3.72c-15.7-17.87-60.9-12.3-51.1 11.11m67.9-4.17c4 7.92 14.9 12.95 29.2 13.88c-8 6.49-20.7 11.42-30.3 5.24c-7.3-4.71-3.7-13.07 1.1-19.12M129.4 364.6c-14.6 3.2-38.77 7-49.63 16c-8.5 7.4-15.03 19.8-16.19 31.4c-1.17 11.6 1.99 21.6 12.85 28.8C120 469.7 165 466.4 205.4 454.9c40.4-11.6 75.4-32.6 119.4-22.8c8.4 2.5 15.7 6.5 14.5 15.9c-.4 2.8-1.5 4.8-2.7 6.5c-9.7 10.8-30.9 17.7-33.6 21.5c-6.4 9.2 34.2 2.8 45-7.6c4.2-4.2 8.1-13 8.9-21.3s-1.3-15.3-4.9-18.3c-11.2-9.6-24.1-15.1-39.8-15.1c-15.7-.1-34 1.7-53.5 6.5c-39.1 9.6-83.6 27.5-127.4 18.6c-17-3.4-27.4-6.8-33.77-14.9c-3.22-4-4.39-10.6-2.48-15.4c7.45-15.2 28.15-17.8 40.95-20.5c-2.4-7.2-4.6-16.4-6.6-23.4"/></symbol> <symbol id="rat" viewBox="0 0 512 512"><path fill="currentColor" d="M433.5 31.6c-8.5 0-15.1 6.58-15.1 14.81s6.6 14.81 15.1 14.81s15.1-6.58 15.1-14.81S442 31.6 433.5 31.6M267 59.05c6.6 15.84 17.1 18.03 31.1 24.77c-11.2 20.98-23.2 51.08-43.5 59.28c-64.7 26.1-98.7 58.3-112.3 98.7c-13.1 39-7 87.2 13.3 145.4c61.8 4.9 127.3 9.2 159.4 2.8c-1.3-4.4-5.8-7.5-8.6-9c-28.5-9.8-45.2-10.9-71.5-12l1.1-9.6c2.2-19.6.4-44.3-7.7-61.3c-4.1-8.5-9.5-14.9-16.5-18.8s-15.8-5.7-28.4-3.3l-3.2-17.8c13.5-2.4 29.4-.6 40.4 5.4c10.9 6.1 18.7 15.8 23.9 26.7c9.1 18.9 11.1 41.6 9.9 61.8c10 .6 18.9 1.6 26.8 2.9c19.2-30.7 37-60.4 39.5-90.7c-13.8-4-32.4-10.7-34.3-24.4c-2.7-19.6 3.6-45 19.3-55.5c-1 27.8-4.3 43.9-2.3 49.7c5.8 10.9 30.3 15.2 40.1 17.4v.1c17.4 4.8 31.9 7 34.8 25.6c18.2-29.5-14.4-45-36.2-54.5l-.1-5.8c-.3-23.5 5.5-39.4 13.5-53.1c8-13.6 17.7-25 26.9-43.2v-.1c-9.4-1.3-19.4-.1-27.1 1.3c5.7-19.9 23.2-23.73 38.6-16.1c5.9-8.3 13.4-18.83 24.9-29.96c-12.7-9.39-19.9-20.4-18.1-33.92c-28-3.4-57.4-4.45-78.6 9.84l-4-3.72c-15.7-17.87-60.9-12.3-51.1 11.11m67.9-4.17c4 7.92 14.9 12.95 29.2 13.88c-8 6.49-20.7 11.42-30.3 5.24c-7.3-4.71-3.7-13.07 1.1-19.12M129.4 364.6c-14.6 3.2-38.77 7-49.63 16c-8.5 7.4-15.03 19.8-16.19 31.4c-1.17 11.6 1.99 21.6 12.85 28.8C120 469.7 165 466.4 205.4 454.9c40.4-11.6 75.4-32.6 119.4-22.8c8.4 2.5 15.7 6.5 14.5 15.9c-.4 2.8-1.5 4.8-2.7 6.5c-9.7 10.8-30.9 17.7-33.6 21.5c-6.4 9.2 34.2 2.8 45-7.6c4.2-4.2 8.1-13 8.9-21.3s-1.3-15.3-4.9-18.3c-11.2-9.6-24.1-15.1-39.8-15.1c-15.7-.1-34 1.7-53.5 6.5c-39.1 9.6-83.6 27.5-127.4 18.6c-17-3.4-27.4-6.8-33.77-14.9c-3.22-4-4.39-10.6-2.48-15.4c7.45-15.2 28.15-17.8 40.95-20.5c-2.4-7.2-4.6-16.4-6.6-23.4"/></symbol>
@ -123,10 +124,12 @@
<symbol id="two-coins" viewBox="0 0 512 512"><path fill="currentColor" d="M264.4 95.01c-35.6-.06-80.2 11.19-124.2 34.09C96.27 152 61.45 182 41.01 211.3c-20.45 29.2-25.98 56.4-15.92 75.8c10.07 19.3 35.53 30.4 71.22 30.4c35.69.1 80.29-11.2 124.19-34c44-22.9 78.8-53 99.2-82.2c20.5-29.2 25.9-56.4 15.9-75.8c-10.1-19.3-35.5-30.49-71.2-30.49m91.9 70.29c-3.5 15.3-11.1 31-21.8 46.3c-22.6 32.3-59.5 63.8-105.7 87.8c-46.2 24.1-93.1 36.2-132.5 36.2c-18.6 0-35.84-2.8-50.37-8.7l10.59 20.4c10.08 19.4 35.47 30.5 71.18 30.5c35.7 0 80.3-11.2 124.2-34.1c44-22.8 78.8-52.9 99.2-82.2c20.4-29.2 26-56.4 15.9-75.7zm28.8 16.8c11.2 26.7 2.2 59.2-19.2 89.7c-18.9 27.1-47.8 53.4-83.6 75.4c11.1 1.2 22.7 1.8 34.5 1.8c49.5 0 94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9s-17.4-43.4-49.1-59.9c-16.1-8.4-35.7-15.3-57.6-20m106.7 124.8c-10.2 11.9-24.2 22.4-40.7 31c-35 18.2-82.2 29.1-134.3 29.1c-21.2 0-41.6-1.8-60.7-5.2c-23.2 11.7-46.5 20.4-68.9 26.1c1.2.7 2.4 1.3 3.7 2c31.6 16.5 76.4 27.1 125.9 27.1s94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9z"/></symbol> <symbol id="two-coins" viewBox="0 0 512 512"><path fill="currentColor" d="M264.4 95.01c-35.6-.06-80.2 11.19-124.2 34.09C96.27 152 61.45 182 41.01 211.3c-20.45 29.2-25.98 56.4-15.92 75.8c10.07 19.3 35.53 30.4 71.22 30.4c35.69.1 80.29-11.2 124.19-34c44-22.9 78.8-53 99.2-82.2c20.5-29.2 25.9-56.4 15.9-75.8c-10.1-19.3-35.5-30.49-71.2-30.49m91.9 70.29c-3.5 15.3-11.1 31-21.8 46.3c-22.6 32.3-59.5 63.8-105.7 87.8c-46.2 24.1-93.1 36.2-132.5 36.2c-18.6 0-35.84-2.8-50.37-8.7l10.59 20.4c10.08 19.4 35.47 30.5 71.18 30.5c35.7 0 80.3-11.2 124.2-34.1c44-22.8 78.8-52.9 99.2-82.2c20.4-29.2 26-56.4 15.9-75.7zm28.8 16.8c11.2 26.7 2.2 59.2-19.2 89.7c-18.9 27.1-47.8 53.4-83.6 75.4c11.1 1.2 22.7 1.8 34.5 1.8c49.5 0 94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9s-17.4-43.4-49.1-59.9c-16.1-8.4-35.7-15.3-57.6-20m106.7 124.8c-10.2 11.9-24.2 22.4-40.7 31c-35 18.2-82.2 29.1-134.3 29.1c-21.2 0-41.6-1.8-60.7-5.2c-23.2 11.7-46.5 20.4-68.9 26.1c1.2.7 2.4 1.3 3.7 2c31.6 16.5 76.4 27.1 125.9 27.1s94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9z"/></symbol>
<symbol id="visored-helm" viewBox="0 0 512 512"><path fill="currentColor" d="M258.094 18.5c-74.34 0-138.073 62.498-156.188 148.438c52.758-7.697 102.23-22.044 153.938-45.094l4.125-1.813l3.967 2.064c49.424 25.667 97.648 41.026 150.657 46.406c-17.66-86.744-81.71-150-156.5-150zm1.28 122.156c-57.41 25.148-112.883 39.993-172.53 47c6.724 32.847 6.91 65.935-.5 98.938c89.29 41.602 231.648 43.154 340.594-.125c-10.762-32.516-11.727-65.66-1.188-98.408c-59.03-4.235-112.628-20.06-166.375-47.406zm-13.5 33.125h18.72v127.75h-18.72V173.78zm-58.78 11.19h18.687v101.655h-18.686V184.97zm115.72 0H321.5v101.655h-18.688V184.97zm-171.72 14.905h18.687v79.28h-18.686zm227.72 0H377.5v79.28h-18.688v-79.28zm38.748 116.75c-14.302 4.282-28.96 7.873-43.78 10.844l-19.22 64.06c26.114-17.337 48.002-43.31 63-74.905zm-277.53 2.875c13.95 28.257 33.448 51.85 56.562 68.53l-17.688-58.905c-13.397-2.61-26.387-5.826-38.875-9.625zm213.156 11.656c-51.63 8.175-104.745 8.588-153.72 1.438l20.845 69.5c18 8.52 37.49 13.187 57.78 13.187c18.588 0 36.507-3.92 53.22-11.124zm-195.5 47.156c-19.436 21.562-36.416 44.367-48.594 72.157c70.233-8.736 133.743 14.684 168.03 50.75c39.684-35.607 103.71-55.685 170.876-44.25c-15.08-29.372-33.32-51.982-53.938-74c-31.187 31.75-71.53 51-115.968 51c-46.568 0-88.65-21.142-120.406-55.658z"/></symbol> <symbol id="visored-helm" viewBox="0 0 512 512"><path fill="currentColor" d="M258.094 18.5c-74.34 0-138.073 62.498-156.188 148.438c52.758-7.697 102.23-22.044 153.938-45.094l4.125-1.813l3.967 2.064c49.424 25.667 97.648 41.026 150.657 46.406c-17.66-86.744-81.71-150-156.5-150zm1.28 122.156c-57.41 25.148-112.883 39.993-172.53 47c6.724 32.847 6.91 65.935-.5 98.938c89.29 41.602 231.648 43.154 340.594-.125c-10.762-32.516-11.727-65.66-1.188-98.408c-59.03-4.235-112.628-20.06-166.375-47.406zm-13.5 33.125h18.72v127.75h-18.72V173.78zm-58.78 11.19h18.687v101.655h-18.686V184.97zm115.72 0H321.5v101.655h-18.688V184.97zm-171.72 14.905h18.687v79.28h-18.686zm227.72 0H377.5v79.28h-18.688v-79.28zm38.748 116.75c-14.302 4.282-28.96 7.873-43.78 10.844l-19.22 64.06c26.114-17.337 48.002-43.31 63-74.905zm-277.53 2.875c13.95 28.257 33.448 51.85 56.562 68.53l-17.688-58.905c-13.397-2.61-26.387-5.826-38.875-9.625zm213.156 11.656c-51.63 8.175-104.745 8.588-153.72 1.438l20.845 69.5c18 8.52 37.49 13.187 57.78 13.187c18.588 0 36.507-3.92 53.22-11.124zm-195.5 47.156c-19.436 21.562-36.416 44.367-48.594 72.157c70.233-8.736 133.743 14.684 168.03 50.75c39.684-35.607 103.71-55.685 170.876-44.25c-15.08-29.372-33.32-51.982-53.938-74c-31.187 31.75-71.53 51-115.968 51c-46.568 0-88.65-21.142-120.406-55.658z"/></symbol>
<symbol id="war-pick" viewBox="0 0 512 512"><path fill="currentColor" d="M136.48 27.746c-2.108.024-4.174.152-6.242.272c42.927 23.035 87.233 59.434 121.902 96.57c8.66 9.276 12.358 18.765 16.371 27.44c2.486 5.37 5.173 10.658 9.297 16.37l30.65-26.373c-3.067-5.031-5.213-10.567-6.044-16.386c-.919-6.432.09-13.283 3.039-19.48c-32.92-24.035-68.653-47.25-102.75-62.026c-22.779-9.871-44.547-15.843-64.1-16.371q-1.07-.029-2.123-.016m226.463 99.256c-2.825 0-5.562.505-8.092 1.293l28.91 28.91c.788-2.53 1.293-5.266 1.293-8.092c0-6.485-2.314-12.726-5.85-16.262s-9.776-5.85-16.261-5.85zm-23.088 11.754l-21.89 18.836c9.951-2.533 20.985.059 28.712 7.787s10.32 18.761 7.788 28.713l18.835-21.89zm-14.39 35.78c-3.053 0-6.104 1.189-8.485 3.57c-4.762 4.761-4.762 12.208 0 16.97s12.21 4.762 16.97 0c4.763-4.762 4.763-12.209 0-16.97c-2.38-2.381-5.433-3.57-8.485-3.57m-27.582.335l-9.846 8.47l-5.352 46.03l46.03-5.352l8.468-9.841c-10.923 4.588-24.09 2.467-32.931-6.373c-8.842-8.842-10.959-22.01-6.37-32.934zm72.148 28.727l-26.373 30.65c5.712 4.124 11 6.812 16.371 9.297c8.674 4.013 18.163 7.711 27.44 16.37c37.136 34.67 73.534 78.977 96.57 121.903c1.254-21.638-4.803-46.36-16.115-72.465c-14.776-34.097-37.992-69.829-62.026-102.75c-6.198 2.95-13.049 3.958-19.48 3.04c-5.82-.832-11.355-2.978-16.387-6.045m-103.375 7.79l-28.398 26.588L274.08 273.8l26.588-28.399l-38.489 4.477zm-41.545 38.897l-11.686 10.941l37.405 37.405l10.941-11.686zm-24.832 23.252l-90.564 84.797l44.007 44.008l84.797-90.565zM96.566 370.643l-21.91 20.515l46.242 46.242l20.516-21.91zm-28.09 39.79l-5.656 16.971l21.832 21.832l16.97-5.656zm-18.789 29.295l-18.49 9.686a106 106 0 0 0-2.746 13.676c-.608 4.548-.852 9.29-.469 12.92s1.496 5.735 1.912 6.152c.417.417 2.523 1.53 6.153 1.912c3.63.383 8.372.139 12.92-.469a106 106 0 0 0 13.675-2.746l9.686-18.49z"/></symbol> <symbol id="war-pick" viewBox="0 0 512 512"><path fill="currentColor" d="M136.48 27.746c-2.108.024-4.174.152-6.242.272c42.927 23.035 87.233 59.434 121.902 96.57c8.66 9.276 12.358 18.765 16.371 27.44c2.486 5.37 5.173 10.658 9.297 16.37l30.65-26.373c-3.067-5.031-5.213-10.567-6.044-16.386c-.919-6.432.09-13.283 3.039-19.48c-32.92-24.035-68.653-47.25-102.75-62.026c-22.779-9.871-44.547-15.843-64.1-16.371q-1.07-.029-2.123-.016m226.463 99.256c-2.825 0-5.562.505-8.092 1.293l28.91 28.91c.788-2.53 1.293-5.266 1.293-8.092c0-6.485-2.314-12.726-5.85-16.262s-9.776-5.85-16.261-5.85zm-23.088 11.754l-21.89 18.836c9.951-2.533 20.985.059 28.712 7.787s10.32 18.761 7.788 28.713l18.835-21.89zm-14.39 35.78c-3.053 0-6.104 1.189-8.485 3.57c-4.762 4.761-4.762 12.208 0 16.97s12.21 4.762 16.97 0c4.763-4.762 4.763-12.209 0-16.97c-2.38-2.381-5.433-3.57-8.485-3.57m-27.582.335l-9.846 8.47l-5.352 46.03l46.03-5.352l8.468-9.841c-10.923 4.588-24.09 2.467-32.931-6.373c-8.842-8.842-10.959-22.01-6.37-32.934zm72.148 28.727l-26.373 30.65c5.712 4.124 11 6.812 16.371 9.297c8.674 4.013 18.163 7.711 27.44 16.37c37.136 34.67 73.534 78.977 96.57 121.903c1.254-21.638-4.803-46.36-16.115-72.465c-14.776-34.097-37.992-69.829-62.026-102.75c-6.198 2.95-13.049 3.958-19.48 3.04c-5.82-.832-11.355-2.978-16.387-6.045m-103.375 7.79l-28.398 26.588L274.08 273.8l26.588-28.399l-38.489 4.477zm-41.545 38.897l-11.686 10.941l37.405 37.405l10.941-11.686zm-24.832 23.252l-90.564 84.797l44.007 44.008l84.797-90.565zM96.566 370.643l-21.91 20.515l46.242 46.242l20.516-21.91zm-28.09 39.79l-5.656 16.971l21.832 21.832l16.97-5.656zm-18.789 29.295l-18.49 9.686a106 106 0 0 0-2.746 13.676c-.608 4.548-.852 9.29-.469 12.92s1.496 5.735 1.912 6.152c.417.417 2.523 1.53 6.153 1.912c3.63.383 8.372.139 12.92-.469a106 106 0 0 0 13.675-2.746l9.686-18.49z"/></symbol>
<symbol id="warhammer" viewBox="0 0 512 512"><path fill="currentColor" d="m351.4 31.4l-55.9 27.75l54 34.62zM143.2 67.33l20 33.47L182 71.5zm57 9.16l-7.6 11.82l100.2 64.19l-9.7 15.1l-100.2-64.1l-24.8 38.7l100.2 64.1l-9.7 15.2l-100.2-64.1l-7.5 11.7l150 96.1l37.9-7.6l44.8-70zm93.2 2.73l-16.2 25.28l38.7 24.7l16.2-25.2zM108.7 121.2l20 33.5l18.8-29.3zm280.1 76.1L346.7 263l11.8 7.5l42.1-65.7zm-224.1 8.5l.6 36l72.8 46.6l33-14.5zm250.4 9.9l-33.2 51.8c11.7 2.8 24 7.3 36.5 12.3c19.3 7.6 39.1 16.7 56.6 24c-9.5-27.2-22.2-57.9-59.9-88.1m-242.5 52.1L27.77 494h54.61L211.4 292.6z"/></symbol>
<symbol id="water-tank" viewBox="0 0 512 512"><path fill="currentColor" d="M160 25c-14.5 0-38 3.89-56.7 11.36c-9.29 3.73-17.41 8.37-22.69 13.25A30 30 0 0 0 75.99 55H244c-1.2-1.77-2.6-3.55-4.6-5.39c-5.3-4.88-13.4-9.52-22.7-13.25C198 28.89 174.5 25 160 25M89 73v129.9l71 42.6l71-42.6V73zm167 78v18h23v14h-30v18h51.3l29.3 29.4l12.8-12.8l-34.7-34.6H297v-14h23v-18zM84.65 221.3L39.12 494.5l17.76 3L74.3 393h171.4l17.4 104.5l17.8-3l-45.5-273.2l-16.7 10l13.7 81.8l-72.4 26.4l-72.38-26.3l13.68-81.9zm263.15 22.4s-10.2 49.6 5.2 59.7c9.8 6.4 28.8-2.9 31-15.4c3.8-19.6-36.2-44.3-36.2-44.3M377 329s-13.4 29.1-5.8 38.5c4.9 5.9 17.4 3.7 20.6-3.6C397 352.3 377 329 377 329m-292.41 2.3l48.91 17.8l-55.22 20.1zm150.81 0l6.3 37.9l-55.2-20.1zm179 7.5s1.4 32.1 12.4 36.9c7.2 3 17.2-4.7 16.8-12.7c-.8-12.6-29.2-24.2-29.2-24.2M160 358.7l44.8 16.3h-89.6zm251.7 40.5s-3.4 21.5 3.4 26.2c4.3 2.9 12.1-1 12.8-6.3c1.3-8.6-16.2-19.9-16.2-19.9"/></symbol> <symbol id="water-tank" viewBox="0 0 512 512"><path fill="currentColor" d="M160 25c-14.5 0-38 3.89-56.7 11.36c-9.29 3.73-17.41 8.37-22.69 13.25A30 30 0 0 0 75.99 55H244c-1.2-1.77-2.6-3.55-4.6-5.39c-5.3-4.88-13.4-9.52-22.7-13.25C198 28.89 174.5 25 160 25M89 73v129.9l71 42.6l71-42.6V73zm167 78v18h23v14h-30v18h51.3l29.3 29.4l12.8-12.8l-34.7-34.6H297v-14h23v-18zM84.65 221.3L39.12 494.5l17.76 3L74.3 393h171.4l17.4 104.5l17.8-3l-45.5-273.2l-16.7 10l13.7 81.8l-72.4 26.4l-72.38-26.3l13.68-81.9zm263.15 22.4s-10.2 49.6 5.2 59.7c9.8 6.4 28.8-2.9 31-15.4c3.8-19.6-36.2-44.3-36.2-44.3M377 329s-13.4 29.1-5.8 38.5c4.9 5.9 17.4 3.7 20.6-3.6C397 352.3 377 329 377 329m-292.41 2.3l48.91 17.8l-55.22 20.1zm150.81 0l6.3 37.9l-55.2-20.1zm179 7.5s1.4 32.1 12.4 36.9c7.2 3 17.2-4.7 16.8-12.7c-.8-12.6-29.2-24.2-29.2-24.2M160 358.7l44.8 16.3h-89.6zm251.7 40.5s-3.4 21.5 3.4 26.2c4.3 2.9 12.1-1 12.8-6.3c1.3-8.6-16.2-19.9-16.2-19.9"/></symbol>
<symbol id="well" viewBox="0 0 512 512"><path fill="currentColor" d="m86.236 28.564l-41.248 110h422.024l-41.248-110zm32.764 128v176.07c76.024 28.87 197.976 28.87 274 0v-176.07h-18v137.428c-7.16-3.66-15.96-6.65-26.307-9.236c-24.208-6.052-56.74-9.64-92.693-9.64c-7.85 0-15.526.18-23 .51c-.017-12.01.002-24.02.04-36.032l24.013-60.03H238.05L215 237.194v39.566c-19.528 1.612-37.125 4.354-51.693 7.996c-10.346 2.586-19.147 5.577-26.307 9.236V156.564zm89 23v16h4.266l6.4-16zm68.44 0l-25.6 64h17.867l25.602-64zm-196.44 23v18h21v-18zm75 0v18h42v-18zm149.492 0l-16.4 41H304v-23h53v-18zm106.508 0v18h12v80h57v-18h-39v-80zm-155 90.55c34.738 0 66.208 3.575 88.326 9.105c11.06 2.763 19.795 6.09 25.035 9.186c4.377 2.587 5.365 4.425 5.576 4.71c.04-.057.064-.074.064 0c0 .073-.023.055-.064 0c-.21.283-1.2 2.12-5.575 4.706c-5.24 3.098-13.975 6.425-25.034 9.19c-22.118 5.53-53.588 9.103-88.326 9.103s-66.208-3.574-88.326-9.103c-11.06-2.765-19.795-6.092-25.035-9.19c-4.377-2.586-5.365-4.423-5.576-4.707c-.04.056-.064.074-.064 0c0-.073.023-.056.064 0c.21-.284 1.2-2.122 5.575-4.71c5.24-3.096 13.975-6.422 25.034-9.186c12.965-3.243 29.16-5.805 47.326-7.376v28.72h18v-29.91c7.456-.347 15.138-.54 23-.54zm137 58.665c-32.96 11.616-71.95 18.42-112 20.417v27.45c40.88-2.024 80.4-9.035 112-21.038zm-274 .02v26.83c9.95 3.777 20.683 7.063 32 9.852V361.16c-11.143-2.664-21.856-5.785-32-9.36zm50 13.202v27.408c29.46 5.657 61.842 8.253 94 7.81v-27.447c-31.99.444-64.16-2.134-94-7.77zm224 32.777a303 303 0 0 1-16 5.146v25.158a254 254 0 0 0 16-5.46zm-274 .01v24.827c27.454 10.426 60.89 17.082 96 19.98v-25.44c-34.372-2.842-67.45-9.302-96-19.366zm240 9.837c-38.988 9.09-83.038 12.637-126 10.67v25.445c43.22 1.968 87.805-1.613 126-10.777zM119 441.78c1.642 9.154 8.428 17.585 16 21.704v-16.558a303 303 0 0 1-16-5.147zm274 .007c-12.8 4.513-26.5 8.312-40.834 11.373v19.73c16.52-4.255 40.596-15.226 40.834-31.103m-240 9.84v19.275c33.85 9.257 73.556 12.422 103 12.534c29.185 0 56.113-2.365 78.166-6.493v-20.37c-58.66 9.767-125.146 8.115-181.166-4.946"/></symbol> <symbol id="well" viewBox="0 0 512 512"><path fill="currentColor" d="m86.236 28.564l-41.248 110h422.024l-41.248-110zm32.764 128v176.07c76.024 28.87 197.976 28.87 274 0v-176.07h-18v137.428c-7.16-3.66-15.96-6.65-26.307-9.236c-24.208-6.052-56.74-9.64-92.693-9.64c-7.85 0-15.526.18-23 .51c-.017-12.01.002-24.02.04-36.032l24.013-60.03H238.05L215 237.194v39.566c-19.528 1.612-37.125 4.354-51.693 7.996c-10.346 2.586-19.147 5.577-26.307 9.236V156.564zm89 23v16h4.266l6.4-16zm68.44 0l-25.6 64h17.867l25.602-64zm-196.44 23v18h21v-18zm75 0v18h42v-18zm149.492 0l-16.4 41H304v-23h53v-18zm106.508 0v18h12v80h57v-18h-39v-80zm-155 90.55c34.738 0 66.208 3.575 88.326 9.105c11.06 2.763 19.795 6.09 25.035 9.186c4.377 2.587 5.365 4.425 5.576 4.71c.04-.057.064-.074.064 0c0 .073-.023.055-.064 0c-.21.283-1.2 2.12-5.575 4.706c-5.24 3.098-13.975 6.425-25.034 9.19c-22.118 5.53-53.588 9.103-88.326 9.103s-66.208-3.574-88.326-9.103c-11.06-2.765-19.795-6.092-25.035-9.19c-4.377-2.586-5.365-4.423-5.576-4.707c-.04.056-.064.074-.064 0c0-.073.023-.056.064 0c.21-.284 1.2-2.122 5.575-4.71c5.24-3.096 13.975-6.422 25.034-9.186c12.965-3.243 29.16-5.805 47.326-7.376v28.72h18v-29.91c7.456-.347 15.138-.54 23-.54zm137 58.665c-32.96 11.616-71.95 18.42-112 20.417v27.45c40.88-2.024 80.4-9.035 112-21.038zm-274 .02v26.83c9.95 3.777 20.683 7.063 32 9.852V361.16c-11.143-2.664-21.856-5.785-32-9.36zm50 13.202v27.408c29.46 5.657 61.842 8.253 94 7.81v-27.447c-31.99.444-64.16-2.134-94-7.77zm224 32.777a303 303 0 0 1-16 5.146v25.158a254 254 0 0 0 16-5.46zm-274 .01v24.827c27.454 10.426 60.89 17.082 96 19.98v-25.44c-34.372-2.842-67.45-9.302-96-19.366zm240 9.837c-38.988 9.09-83.038 12.637-126 10.67v25.445c43.22 1.968 87.805-1.613 126-10.777zM119 441.78c1.642 9.154 8.428 17.585 16 21.704v-16.558a303 303 0 0 1-16-5.147zm274 .007c-12.8 4.513-26.5 8.312-40.834 11.373v19.73c16.52-4.255 40.596-15.226 40.834-31.103m-240 9.84v19.275c33.85 9.257 73.556 12.422 103 12.534c29.185 0 56.113-2.365 78.166-6.493v-20.37c-58.66 9.767-125.146 8.115-181.166-4.946"/></symbol>
<symbol id="wheat" viewBox="0 0 512 512"><path fill="currentColor" d="M98.344 16.688C79.692 43.785 68.498 69.01 65.5 89.56l23.938 39.157l28.624-33.47c.868-21.213-5.49-48.677-19.718-78.563zM472.5 19.625C444.04 36.055 423.112 54 411.562 71.25l4.75 45.688L456.563 99c9.89-18.777 15.938-46.29 15.938-79.375zm-91.75 27.28c-10.153 21.036-16.8 40.84-20.156 58.314l18.375 57.686l19.78-34.25l-6.5-62.22h.03a277 277 0 0 0-11.53-19.53zM27.25 80.782c-.125 23.364 2.393 44.102 6.875 61.314L75.5 186.25l3.125-39.406L46 93.47l.03-.032a280 280 0 0 0-18.78-12.657zm132.844 10.532c-8.415 3.504-16.29 7.213-23.594 11.094l-39.25 45.97l-3.094 39.374l50.438-39.094c6.712-15.904 12.09-35.263 15.5-57.344m177.22 21.626c-24.024 58.09-16.16 97.86 7.873 108.5l21.157-36.625l-19.594-61.438a274 274 0 0 0-9.438-10.438zm146.03.218c-4.55-.028-8.97.084-13.28.28L414.935 138l-19.78 34.28l62.343-13.655c12.897-11.47 26.09-26.626 38.656-45.094c-4.358-.216-8.64-.348-12.812-.374zm-226.094 8.72c-23.24 23.238-38.832 46.003-45.53 65.655l16.436 42.907l34.22-27.75c4.695-20.704 3.436-48.856-5.126-80.812M16.406 159.06c3.28 62.77 27.482 95.31 53.75 94.594l3.344-42.22l-44.063-47a279 279 0 0 0-13.03-5.374zm143.22 11.375a272 272 0 0 0-18.5 4.563l-48.97 37.938l-3.312 41.75c26.492 7.51 57.16-20.567 70.78-84.25zm16.06 1.563c-4.36 22.935-5.65 43.762-4.374 61.5l32.688 51l10.22-38.188l-22.407-58.437h.03a277 277 0 0 0-16.155-15.875zm267.408 8.938l-60.563 13.218l-20.936 36.25c20.682 18.195 60.438 6.035 100.125-45.625a275 275 0 0 0-18.626-3.843m-138.688 25.53c-8.912 1.92-17.304 4.16-25.187 6.657l-46.97 38.03l-10.22 38.19l56.69-29.283c9.493-14.424 18.323-32.49 25.686-53.593zm155.125 25.063c-25.85 20.324-44.046 41.06-53.03 59.782l11.22 44.532l37.28-23.47c7.126-19.99 9.236-48.088 4.53-80.843zm-123.342 8.595c-34.435 77.573-59.394 159.06-62.97 253.03h18.72c3.558-90.792 27.573-169.428 61.312-245.436l-17.063-7.595zm-185.375 6.906c-8.173 62.347 9.714 98.713 35.687 102.75l10.97-40.874l-34.814-54.25a279 279 0 0 0-11.844-7.625zm221.75 24.532c-7.053 22.243-10.817 42.77-11.657 60.532l26.406 54.594L402 349.967l-15.28-60.687h.06c-4.3-5.848-9.033-11.76-14.217-17.717zm-302.47 1.532c-8.664 74.584-8.13 147.835 12.188 220.062h19.44c-20.877-70.772-21.764-143.02-13.064-217.906l-18.562-2.156zm219.47 11.094c-6.613.16-12.953.54-19.032 1.125L215.5 313.78l-10.844 40.408c24.69 12.23 59.938-9.82 84.906-70zm206.718 36.937c-9.072.844-17.664 2.052-25.78 3.594l-51.156 32.217l-14.688 36.657l59.75-22.313c11.14-13.193 22.055-30.075 31.875-50.155zm-157.31 22c-15.528 60.938-2.096 99.19 23.217 106.28l15.72-39.28l-28.094-58.03c-3.43-3-7.053-5.985-10.844-8.97zM183.25 368.72c-12.674 41.233-22.26 82.547-26.844 124.436h18.813c4.507-39.722 13.69-79.23 25.905-118.97l-17.875-5.467zm270 26.655l-58 21.688l-15.563 38.875c23.056 15.098 60.673-2.606 92.625-59.407a273 273 0 0 0-19.062-1.155zM356.5 469.03c-1.874 7.713-3.185 15.757-3.656 24.126h18.687c.45-6.686 1.55-13.206 3.126-19.687l-18.156-4.44z"/></symbol> <symbol id="wheat" viewBox="0 0 512 512"><path fill="currentColor" d="M98.344 16.688C79.692 43.785 68.498 69.01 65.5 89.56l23.938 39.157l28.624-33.47c.868-21.213-5.49-48.677-19.718-78.563zM472.5 19.625C444.04 36.055 423.112 54 411.562 71.25l4.75 45.688L456.563 99c9.89-18.777 15.938-46.29 15.938-79.375zm-91.75 27.28c-10.153 21.036-16.8 40.84-20.156 58.314l18.375 57.686l19.78-34.25l-6.5-62.22h.03a277 277 0 0 0-11.53-19.53zM27.25 80.782c-.125 23.364 2.393 44.102 6.875 61.314L75.5 186.25l3.125-39.406L46 93.47l.03-.032a280 280 0 0 0-18.78-12.657zm132.844 10.532c-8.415 3.504-16.29 7.213-23.594 11.094l-39.25 45.97l-3.094 39.374l50.438-39.094c6.712-15.904 12.09-35.263 15.5-57.344m177.22 21.626c-24.024 58.09-16.16 97.86 7.873 108.5l21.157-36.625l-19.594-61.438a274 274 0 0 0-9.438-10.438zm146.03.218c-4.55-.028-8.97.084-13.28.28L414.935 138l-19.78 34.28l62.343-13.655c12.897-11.47 26.09-26.626 38.656-45.094c-4.358-.216-8.64-.348-12.812-.374zm-226.094 8.72c-23.24 23.238-38.832 46.003-45.53 65.655l16.436 42.907l34.22-27.75c4.695-20.704 3.436-48.856-5.126-80.812M16.406 159.06c3.28 62.77 27.482 95.31 53.75 94.594l3.344-42.22l-44.063-47a279 279 0 0 0-13.03-5.374zm143.22 11.375a272 272 0 0 0-18.5 4.563l-48.97 37.938l-3.312 41.75c26.492 7.51 57.16-20.567 70.78-84.25zm16.06 1.563c-4.36 22.935-5.65 43.762-4.374 61.5l32.688 51l10.22-38.188l-22.407-58.437h.03a277 277 0 0 0-16.155-15.875zm267.408 8.938l-60.563 13.218l-20.936 36.25c20.682 18.195 60.438 6.035 100.125-45.625a275 275 0 0 0-18.626-3.843m-138.688 25.53c-8.912 1.92-17.304 4.16-25.187 6.657l-46.97 38.03l-10.22 38.19l56.69-29.283c9.493-14.424 18.323-32.49 25.686-53.593zm155.125 25.063c-25.85 20.324-44.046 41.06-53.03 59.782l11.22 44.532l37.28-23.47c7.126-19.99 9.236-48.088 4.53-80.843zm-123.342 8.595c-34.435 77.573-59.394 159.06-62.97 253.03h18.72c3.558-90.792 27.573-169.428 61.312-245.436l-17.063-7.595zm-185.375 6.906c-8.173 62.347 9.714 98.713 35.687 102.75l10.97-40.874l-34.814-54.25a279 279 0 0 0-11.844-7.625zm221.75 24.532c-7.053 22.243-10.817 42.77-11.657 60.532l26.406 54.594L402 349.967l-15.28-60.687h.06c-4.3-5.848-9.033-11.76-14.217-17.717zm-302.47 1.532c-8.664 74.584-8.13 147.835 12.188 220.062h19.44c-20.877-70.772-21.764-143.02-13.064-217.906l-18.562-2.156zm219.47 11.094c-6.613.16-12.953.54-19.032 1.125L215.5 313.78l-10.844 40.408c24.69 12.23 59.938-9.82 84.906-70zm206.718 36.937c-9.072.844-17.664 2.052-25.78 3.594l-51.156 32.217l-14.688 36.657l59.75-22.313c11.14-13.193 22.055-30.075 31.875-50.155zm-157.31 22c-15.528 60.938-2.096 99.19 23.217 106.28l15.72-39.28l-28.094-58.03c-3.43-3-7.053-5.985-10.844-8.97zM183.25 368.72c-12.674 41.233-22.26 82.547-26.844 124.436h18.813c4.507-39.722 13.69-79.23 25.905-118.97l-17.875-5.467zm270 26.655l-58 21.688l-15.563 38.875c23.056 15.098 60.673-2.606 92.625-59.407a273 273 0 0 0-19.062-1.155zM356.5 469.03c-1.874 7.713-3.185 15.757-3.656 24.126h18.687c.45-6.686 1.55-13.206 3.126-19.687l-18.156-4.44z"/></symbol>
<symbol id="wind-hole" viewBox="0 0 512 512"><path fill="currentColor" d="M19.842 17.184v61.42C29.59 124.187 54.08 177.31 96.35 234.948c-19.817-18.264-37.322-36.358-52.72-54.082c25.615 59.5 69.548 119.182 123.13 162.795c48.123 31.57 119.676 29.46 162.902-10.613c6.732-7.988 13.065-16.54 18.98-25.682c-20.605 78.87-90.272 129.942-216.61 139.61c22.292 6.705 46.503 10.895 72.36 12.234c-74.885 23.496-140.058 19.362-187.47-3.782v38.822h344.572c12.548-25.422 22.592-53.765 29.526-84.895c4.948-48.52-4.294-110.44-32.512-182.982c17.547 27.72 31.866 54.315 43.36 79.518c-.008-16.152-.728-32.81-2.237-49.982c-.084-5.56-.53-11.03-1.29-16.398c-33.654-52.997-81.454-71.595-133.21-64.133c59.48-17.147 105.816-5.343 143.067 40.62c61.71 66.54 84.012 167.01 60.17 278.837h25.113V184.81c-31.772-28.644-73.986-47.578-126.732-52.068c32.298-9.65 61.865-13.936 88.188-13.43c4.774.09 9.442.34 14.002.74c-29.598-8.21-60.133-11.63-90.846-11.398c-12.44.095-24.907.807-37.354 2.024l.088.05c-47.7 10.48-91.986 38.815-126.73 88.68c6.15-25.89 14.357-48.62 24.226-68.144c-29.95 7.29-55.854 24.91-73.71 48.888c-12.354 53.054 9.742 114.704 56.314 126.26c-16.457-8.185-27.838-25.188-27.838-44.73c0-27.46 22.46-49.918 49.92-49.918s49.92 22.46 49.92 49.918c0 17.3-8.92 32.61-22.385 41.576c-38.712 29.777-80.068 19.58-109.082-19.545c-31.807-42.892-33.913-88.063-8.812-146.24c-13.99 18.068-25.763 39.423-34.736 64.257c-2.735-95.686 31.315-157.842 82.412-184.546z"/></symbol> <symbol id="wind-hole" viewBox="0 0 512 512"><path fill="currentColor" d="M19.842 17.184v61.42C29.59 124.187 54.08 177.31 96.35 234.948c-19.817-18.264-37.322-36.358-52.72-54.082c25.615 59.5 69.548 119.182 123.13 162.795c48.123 31.57 119.676 29.46 162.902-10.613c6.732-7.988 13.065-16.54 18.98-25.682c-20.605 78.87-90.272 129.942-216.61 139.61c22.292 6.705 46.503 10.895 72.36 12.234c-74.885 23.496-140.058 19.362-187.47-3.782v38.822h344.572c12.548-25.422 22.592-53.765 29.526-84.895c4.948-48.52-4.294-110.44-32.512-182.982c17.547 27.72 31.866 54.315 43.36 79.518c-.008-16.152-.728-32.81-2.237-49.982c-.084-5.56-.53-11.03-1.29-16.398c-33.654-52.997-81.454-71.595-133.21-64.133c59.48-17.147 105.816-5.343 143.067 40.62c61.71 66.54 84.012 167.01 60.17 278.837h25.113V184.81c-31.772-28.644-73.986-47.578-126.732-52.068c32.298-9.65 61.865-13.936 88.188-13.43c4.774.09 9.442.34 14.002.74c-29.598-8.21-60.133-11.63-90.846-11.398c-12.44.095-24.907.807-37.354 2.024l.088.05c-47.7 10.48-91.986 38.815-126.73 88.68c6.15-25.89 14.357-48.62 24.226-68.144c-29.95 7.29-55.854 24.91-73.71 48.888c-12.354 53.054 9.742 114.704 56.314 126.26c-16.457-8.185-27.838-25.188-27.838-44.73c0-27.46 22.46-49.918 49.92-49.918s49.92 22.46 49.92 49.918c0 17.3-8.92 32.61-22.385 41.576c-38.712 29.777-80.068 19.58-109.082-19.545c-31.807-42.892-33.913-88.063-8.812-146.24c-13.99 18.068-25.763 39.423-34.736 64.257c-2.735-95.686 31.315-157.842 82.412-184.546z"/></symbol>
<symbol id="wizard-staff" viewBox="0 0 512 512"><path fill="currentColor" d="M335.656 19.53c-24.51.093-48.993 5.235-71.062 15.626c-22.46 10.577-43.112 34.202-58.375 62.563c-15.264 28.36-25.182 61.262-27.69 88.75c-7.487 82.112-51.926 155.352-159.78 252.56l-.188 21.44C89.216 403.443 139.915 346.632 176.313 290l.063.03c-9.293 32.473-22.623 63.18-43.594 87.97c-31.47 35.584-69.222 71.1-114.468 106.53l-.062 8.25l25 .064h.47l1.28-1.156c24.405-16.498 48.607-31.488 72.594-41.5l.187.187l-46.436 42.5l28.937.063c48.372-41.685 94.714-90.58 129.626-137c33.587-44.658 56.02-87.312 60.688-116.844c-1.268-2.32-2.552-4.628-3.656-7.094c-18.833-42.06-4.273-96.424 40.218-116.063c32.73-14.45 74.854-3.165 90.438 31.344c.15.333.324.634.47.97c13.302 24.062 6.175 49.48-9.345 61.97c-7.866 6.328-18.442 9.528-28.75 6.56c-10.31-2.966-19.043-11.772-24.5-25.124l17.28-7.062c3.992 9.764 8.667 13.15 12.375 14.22c3.708 1.066 7.767.148 11.875-3.158c8.216-6.61 14.282-21.91 4.406-39.03l-.28-.47l-.22-.5c-10.7-24.82-41.96-33.333-66.22-22.625c-34.063 15.037-45.594 58.052-30.686 91.345c20.527 45.846 77.97 61.177 122.375 40.875c60.157-27.5 80.13-103.328 53.094-161.813c-24.737-53.503-81.41-82.484-138.908-83.843c-1.633-.04-3.272-.07-4.906-.063zm-25.75 26.72c3.238.035 6.363.348 9.406.906c10.343 1.898 19.946 6.753 29.032 13.25c-30.623-5.437-58.324 4.612-80.78 24.782c-22.44 20.152-39.16 50.59-45.783 84.718c-4.655-11.358-7.166-21.462-6.686-31.72c.296-6.343 1.715-12.956 4.78-20.217c9.094-18.016 21.032-33.946 35.22-46.69c7.824-7.026 16.39-13.07 25.53-17.905c10.932-5.212 20.522-7.22 29.282-7.125zm122.938 62.313c22.583 13.167 34.365 41.86 32.937 70.656c-.564 11.395-3.466 22.975-8.905 33.624c-12.48 18.937-35.53 25.51-49.97 20.875l-.092-.25c27.943-10.365 39.18-32.377 40.312-55.19c.124-2.5.115-4.994-.03-7.468c1.447-13.31-.412-28.793-5.47-43.437c-2.244-6.496-5.15-12.89-8.844-18.72l.064-.093zm-135.563 1.312c-20.97 19.342-29.406 35.252-33.25 51.25c-3.848 16.023-2.788 32.84-2.905 52.875c-.14 23.79-2.56 51.542-18.438 85.688c-.005.012-.025.018-.03.03c-21.095 26.753-45.276 52.25-68.907 67.376l-.063-.03c64.195-71.545 68.527-114.792 68.75-153.19c.112-19.197-1.253-37.594 3.438-57.124a98 98 0 0 1 2-7.125h.03c8.098-17.036 16.572-26.058 25.47-31.563c7.18-4.44 15.035-6.697 23.906-8.187z"/></symbol>
<symbol id="wolf-head" viewBox="0 0 512 512"><path fill="currentColor" d="M179.3 38.94C154.7 77.7 142.7 139.7 168.4 185.9l-16.3 9.2c-6.7-11.9-11.2-24.4-13.9-37.2c-34.5-6.3-69.42-7.5-104.98-2.1c34.07 10.1 52.77 23.7 76.68 46.7c-26.82 9.7-60.25 30.2-92.93 70.2c35.47-8.8 64.83-11.5 89.43-6.3c-36.94 22.5-64.06 56.1-88.34 114.1c35.9-17.2 64.89-18.8 102.94-18.8c-23.07 32.7-35.27 77.2-36.31 112.8c24.51-26 57.61-60.2 87.21-79c3 29.9 15 58.3 35.9 85.3c-.2-43.9 10.3-88.3 31.6-133.4c-18.8 9-32.4 18.1-49.9 29.3c6.2-27.9 12.4-55.8 18.7-83.7c-23.3 2.4-39 10-60.5 18.5c16.3-33.1 32.7-66.1 49.1-99.2l16.8 8.3l-28.4 57.4c18.4-4.4 28.7-4.1 45.7-1.3c-4.5 20.4-9 40.7-13.6 61c65.3-36.2 148.3-45.9 226.7-50c7.6-12.9 13.8-24.2 18.8-34.8l-6.3-24.4l-24.4 30.8l-7.8-27.5l-22.5 29.2l-7.5-26.1l-23.9 31.5l-7.7-28.2l-23.8 31.4l1.2-41.1l22.6-42.7l7.6 28.3l23.9-31.5l7.6 28.2l23.5-30l6.5 26.9l24.5-30.8l7.8 27.5l24.6-32c2.3-10.8 4.6-22.4 7.4-35.7c-55.5-3.7-106.3 4.8-154 9.8c-38-20.8-80.8-26.8-121.9-18.5c-13.6-29.69-27.2-59.38-40.9-89.06M325.5 158.3c-4.5 14.2-13 18.3-24.7 20.6c-16.1-4.4-28.3-15.5-34.4-30.2c20.4-3.8 42.4 3.4 59.1 9.6"/></symbol> <symbol id="wolf-head" viewBox="0 0 512 512"><path fill="currentColor" d="M179.3 38.94C154.7 77.7 142.7 139.7 168.4 185.9l-16.3 9.2c-6.7-11.9-11.2-24.4-13.9-37.2c-34.5-6.3-69.42-7.5-104.98-2.1c34.07 10.1 52.77 23.7 76.68 46.7c-26.82 9.7-60.25 30.2-92.93 70.2c35.47-8.8 64.83-11.5 89.43-6.3c-36.94 22.5-64.06 56.1-88.34 114.1c35.9-17.2 64.89-18.8 102.94-18.8c-23.07 32.7-35.27 77.2-36.31 112.8c24.51-26 57.61-60.2 87.21-79c3 29.9 15 58.3 35.9 85.3c-.2-43.9 10.3-88.3 31.6-133.4c-18.8 9-32.4 18.1-49.9 29.3c6.2-27.9 12.4-55.8 18.7-83.7c-23.3 2.4-39 10-60.5 18.5c16.3-33.1 32.7-66.1 49.1-99.2l16.8 8.3l-28.4 57.4c18.4-4.4 28.7-4.1 45.7-1.3c-4.5 20.4-9 40.7-13.6 61c65.3-36.2 148.3-45.9 226.7-50c7.6-12.9 13.8-24.2 18.8-34.8l-6.3-24.4l-24.4 30.8l-7.8-27.5l-22.5 29.2l-7.5-26.1l-23.9 31.5l-7.7-28.2l-23.8 31.4l1.2-41.1l22.6-42.7l7.6 28.3l23.9-31.5l7.6 28.2l23.5-30l6.5 26.9l24.5-30.8l7.8 27.5l24.6-32c2.3-10.8 4.6-22.4 7.4-35.7c-55.5-3.7-106.3 4.8-154 9.8c-38-20.8-80.8-26.8-121.9-18.5c-13.6-29.69-27.2-59.38-40.9-89.06M325.5 158.3c-4.5 14.2-13 18.3-24.7 20.6c-16.1-4.4-28.3-15.5-34.4-30.2c20.4-3.8 42.4 3.4 59.1 9.6"/></symbol>
<symbol id="wood-axe" viewBox="0 0 512 512"><path fill="currentColor" d="M215.344 22.813L205.03 37.906l71.782 46.375l8.938-12.81c-15.62-23.633-44.153-40.97-70.406-48.657zm-38.47 18.843c-28.32 35.34-79.16 105.16-105.718 145.313c61.96 26.364 113.013 69.562 133.22 119.593c5.064 12.54 8.125 25.566 8.78 38.75c36.873-9.75 80.34-36.93 117.25-70.5c30.105-27.38 55.912-59.115 71.406-87.75L176.875 41.655zm240.657 155.53c-16.836 31.038-43.713 63.084-74.717 91.283c-40.21 36.57-87.238 66.474-130.47 76.03a105.8 105.8 0 0 1-6.343 24.72c-8.91 22.832-26.23 44.633-52.656 64.592c64.678 10.955 135.135-13.105 195.844-53.687c64.21-42.923 116.84-104.112 139.28-157.063l-70.937-45.875zM84.814 213.782L16.5 313.72v143.717l135.875-194.812c-18.23-18.513-41.412-35.295-67.563-48.844z"/></symbol> <symbol id="wood-axe" viewBox="0 0 512 512"><path fill="currentColor" d="M215.344 22.813L205.03 37.906l71.782 46.375l8.938-12.81c-15.62-23.633-44.153-40.97-70.406-48.657zm-38.47 18.843c-28.32 35.34-79.16 105.16-105.718 145.313c61.96 26.364 113.013 69.562 133.22 119.593c5.064 12.54 8.125 25.566 8.78 38.75c36.873-9.75 80.34-36.93 117.25-70.5c30.105-27.38 55.912-59.115 71.406-87.75L176.875 41.655zm240.657 155.53c-16.836 31.038-43.713 63.084-74.717 91.283c-40.21 36.57-87.238 66.474-130.47 76.03a105.8 105.8 0 0 1-6.343 24.72c-8.91 22.832-26.23 44.633-52.656 64.592c64.678 10.955 135.135-13.105 195.844-53.687c64.21-42.923 116.84-104.112 139.28-157.063l-70.937-45.875zM84.814 213.782L16.5 313.72v143.717l135.875-194.812c-18.23-18.513-41.412-35.295-67.563-48.844z"/></symbol>
<symbol id="wood-beam" viewBox="0 0 512 512"><path fill="currentColor" d="M268.4 48.99L42.55 335H82.2l75.9-104.2l14.6 10.6l-68.3 93.6h27.5l28.2-30.4l-1.6 30.4h116.8L470.9 48.99h-50.6l-150 219.91l-14.8-10.2L398.6 48.99h-34.9l-47.8 66.51l-14.6-10.6l40.2-55.91zM479 69.08L289 346.8v30.7l68.9-100.8l14.8 10.2L289 409.3v32.3l190-292.3v-11.7l-22 5.8l22-33.3zM32.98 353v110h23.83l10.54-38.1L78.48 463h37.62c-2.2-5.7-3.4-11.8-3.4-18.2c0-18.6 10.4-35 25.9-46.3c15.5-11.2 36.2-17.8 58.9-17.8s43.4 6.6 58.9 17.8c5.6 4.1 10.6 8.9 14.6 14.2V353zm164.52 45.7c-19.2 0-36.4 5.7-48.3 14.4c-12 8.7-18.5 19.8-18.5 31.7c0 6.4 1.9 12.5 5.5 18.2h16.3c-3.3-4.7-5.4-10.1-5.4-16.1c0-11.2 7.1-20.4 16.5-26.3c9.3-6 21.3-9.2 34.4-9.2s25.1 3.2 34.4 9.2c9.4 5.9 16.5 15.1 16.5 26.3c0 6-2.1 11.4-5.4 16.1h15.3c3.6-5.7 5.5-11.8 5.5-18.2c0-11.9-6.5-23-18.5-31.7c-11.9-8.7-29.1-14.4-48.3-14.4m.5 30.7c-10 0-19 2.7-24.8 6.4s-8.1 7.6-8.1 11.1s2.3 7.4 8.1 11.1c3.3 2.1 7.6 3.9 12.5 5h24.6c4.9-1.1 9.2-2.9 12.5-5c5.8-3.7 8.1-7.6 8.1-11.1s-2.3-7.4-8.1-11.1s-14.8-6.4-24.8-6.4"/></symbol> <symbol id="wood-beam" viewBox="0 0 512 512"><path fill="currentColor" d="M268.4 48.99L42.55 335H82.2l75.9-104.2l14.6 10.6l-68.3 93.6h27.5l28.2-30.4l-1.6 30.4h116.8L470.9 48.99h-50.6l-150 219.91l-14.8-10.2L398.6 48.99h-34.9l-47.8 66.51l-14.6-10.6l40.2-55.91zM479 69.08L289 346.8v30.7l68.9-100.8l14.8 10.2L289 409.3v32.3l190-292.3v-11.7l-22 5.8l22-33.3zM32.98 353v110h23.83l10.54-38.1L78.48 463h37.62c-2.2-5.7-3.4-11.8-3.4-18.2c0-18.6 10.4-35 25.9-46.3c15.5-11.2 36.2-17.8 58.9-17.8s43.4 6.6 58.9 17.8c5.6 4.1 10.6 8.9 14.6 14.2V353zm164.52 45.7c-19.2 0-36.4 5.7-48.3 14.4c-12 8.7-18.5 19.8-18.5 31.7c0 6.4 1.9 12.5 5.5 18.2h16.3c-3.3-4.7-5.4-10.1-5.4-16.1c0-11.2 7.1-20.4 16.5-26.3c9.3-6 21.3-9.2 34.4-9.2s25.1 3.2 34.4 9.2c9.4 5.9 16.5 15.1 16.5 26.3c0 6-2.1 11.4-5.4 16.1h15.3c3.6-5.7 5.5-11.8 5.5-18.2c0-11.9-6.5-23-18.5-31.7c-11.9-8.7-29.1-14.4-48.3-14.4m.5 30.7c-10 0-19 2.7-24.8 6.4s-8.1 7.6-8.1 11.1s2.3 7.4 8.1 11.1c3.3 2.1 7.6 3.9 12.5 5h24.6c4.9-1.1 9.2-2.9 12.5-5c5.8-3.7 8.1-7.6 8.1-11.1s-2.3-7.4-8.1-11.1s-14.8-6.4-24.8-6.4"/></symbol>

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 214 KiB

Before After
Before After

View file

@ -708,9 +708,10 @@ class TierTest(unittest.TestCase):
def test_every_tier_has_full_kit(self): def test_every_tier_has_full_kit(self):
for key, *_ in game.METALS: 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"{key}_{piece}", game.ITEMS)
self.assertIn(f"smith_{key}_{piece}", game.ACTION_BY_ID) 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 *_, prefix, _label, _level, _armour in game.LEATHERS:
for piece in ("cap", "legs", "body"): for piece in ("cap", "legs", "body"):
self.assertIn(f"{prefix}_{piece}", game.ITEMS) self.assertIn(f"{prefix}_{piece}", game.ITEMS)
@ -1317,6 +1318,62 @@ class TradeSkillsTest(unittest.TestCase):
self.assertNotIn("plot2", h["action"]) 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): class FittingTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.world = world_with(("fred", "miner")) self.world = world_with(("fred", "miner"))