Hunting and leatherworking on the tier ladder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-21 20:56:39 +01:00
parent 82616157fb
commit e0e0a824a9
2 changed files with 25 additions and 19 deletions

42
game.py
View file

@ -186,16 +186,16 @@ def _fuelled(inputs: dict, tier: int) -> dict:
return {**inputs, FIREWOOD[tier]: inputs.get(FIREWOOD[tier], 0) + 1} return {**inputs, FIREWOOD[tier]: inputs.get(FIREWOOD[tier], 0) + 1}
# Every tier's hide comes from Hunting. raw hide (id, name, icon, value), leather (id, name, value), # Every tier's hide comes from Hunting. raw hide (id, name, icon, value), leather (id, name, value),
# armour id prefix, armour name prefix, leatherworking level # armour id prefix, armour name prefix
LEATHERS = [ LEATHERS = [
(("hide", "Hide", "🟫", 3), ("leather", "Leather", 5), "leather", "Leather", 1), (("hide", "Hide", "🟫", 3), ("leather", "Leather", 5), "leather", "Leather"),
(("boar_hide", "Boar hide", "🐗", 8), ("hard_leather", "Hard leather", 12), "hard_leather", "Hard leather", 20), (("boar_hide", "Boar hide", "🐗", 8), ("hard_leather", "Hard leather", 12), "hard_leather", "Hard leather"),
(("bear_pelt", "Bear pelt", "🐻", 16), ("bear_leather", "Bear leather", 24), "bear_leather", "Bear leather", 35), (("bear_pelt", "Bear pelt", "🐻", 16), ("bear_leather", "Bear leather", 24), "bear_leather", "Bear leather"),
(("elk_hide", "Elk hide", "🦌", 35), ("elk_leather", "Elk leather", 50), "elk_leather", "Elk leather", 50), (("elk_hide", "Elk hide", "🦌", 35), ("elk_leather", "Elk leather", 50), "elk_leather", "Elk leather"),
(("sabrecat_pelt", "Sabrecat pelt", "🐆", 60), ("sabrecat_leather", "Sabrecat leather", 85), (("sabrecat_pelt", "Sabrecat pelt", "🐆", 60), ("sabrecat_leather", "Sabrecat leather", 85),
"sabrecat_leather", "Sabrecat leather", 65), "sabrecat_leather", "Sabrecat leather"),
(("mammoth_hide", "Mammoth hide", "🦣", 100), ("mammoth_leather", "Mammoth leather", 140), (("mammoth_hide", "Mammoth hide", "🦣", 100), ("mammoth_leather", "Mammoth leather", 140),
"mammoth_leather", "Mammoth leather", 80), "mammoth_leather", "Mammoth leather"),
] ]
# piece suffix, slot, noun, leather used, level above the tier, icon # piece suffix, slot, noun, leather used, level above the tier, icon
LEATHER_PIECES = [("cap", "helmet", "cap", 2, 2, "🧢"), ("legs", "legs", "trousers", 3, 7, "👖"), LEATHER_PIECES = [("cap", "helmet", "cap", 2, 2, "🧢"), ("legs", "legs", "trousers", 3, 7, "👖"),
@ -359,7 +359,7 @@ for _tier, _wood in enumerate(WOODS):
for _tier, (_fibre, _level, _time, _xp, _cloth, _prefix, _label) in enumerate(CLOTHS): for _tier, (_fibre, _level, _time, _xp, _cloth, _prefix, _label) in enumerate(CLOTHS):
ITEMS[f"{_prefix}_bag"] = {"name": f"{_label} bag", "icon": "👜", "tier": _tier, "slot": "bag", ITEMS[f"{_prefix}_bag"] = {"name": f"{_label} bag", "icon": "👜", "tier": _tier, "slot": "bag",
"stack": BAG_STACK[_tier], "value": 0} "stack": BAG_STACK[_tier], "value": 0}
for _tier, (_raw, _leather, _prefix, _label, _level) in enumerate(LEATHERS): for _tier, (_raw, _leather, _prefix, _label) 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]}
for _suffix, _slot, _noun, _used, _offset, _icon in LEATHER_PIECES: for _suffix, _slot, _noun, _used, _offset, _icon in LEATHER_PIECES:
@ -584,13 +584,14 @@ def _tiered_actions() -> list[dict]:
for tier, (log, _name, _icon, _value, action_id, verb) in enumerate(TREES): for tier, (log, _name, _icon, _value, action_id, verb) in enumerate(TREES):
actions.append(_action(action_id, "woodcutting", verb, TIER_LEVELS[tier], [20, 35, 40, 50, 60, 75][tier], actions.append(_action(action_id, "woodcutting", verb, TIER_LEVELS[tier], [20, 35, 40, 50, 60, 75][tier],
[5, 15, 24, 36, 52, 75][tier], outputs={log: 1})) [5, 15, 24, 36, 52, 75][tier], outputs={log: 1}))
for tier, (raw, leather, prefix, label, level) in enumerate(LEATHERS): for tier, (raw, leather, prefix, label) in enumerate(LEATHERS):
actions.append(_action("tan_leather" if tier == 0 else f"tan_{leather[0]}", "leatherworking", actions.append(_action("tan_leather" if tier == 0 else f"tan_{leather[0]}", "leatherworking",
f"Tan {leather[1].lower()}", level, 25 + 3 * tier, bar_xp[tier], f"Tan {leather[1].lower()}", TIER_LEVELS[tier], 25 + 3 * tier, bar_xp[tier],
{raw[0]: 1}, {leather[0]: 1}, group="Tanning")) {raw[0]: 1}, {leather[0]: 1}, group="Tanning"))
for suffix, slot, noun, used, offset, _icon in LEATHER_PIECES: for suffix, slot, noun, used, offset, _icon in LEATHER_PIECES:
actions.append(_action(f"lw_{suffix}" if tier == 0 else f"lw_{prefix}_{suffix}", "leatherworking", actions.append(_action(f"lw_{suffix}" if tier == 0 else f"lw_{prefix}_{suffix}", "leatherworking",
f"{label} {noun}", level + offset, 25 + 5 * used + 2 * tier, used * piece_xp[tier], f"{label} {noun}", TIER_LEVELS[tier] + offset,
25 + 5 * used + 2 * tier, used * piece_xp[tier],
{leather[0]: used, **({reagent("medium", tier): REAGENT_COUNTS[slot]} if tier else {})}, {leather[0]: used, **({reagent("medium", tier): REAGENT_COUNTS[slot]} if tier else {})},
{f"{prefix}_{suffix}": 1}, group=label)) {f"{prefix}_{suffix}": 1}, group=label))
for tier, (fibre, level, seconds, fibre_xp, cloth, prefix, label) in enumerate(CLOTHS): for tier, (fibre, level, seconds, fibre_xp, cloth, prefix, label) in enumerate(CLOTHS):
@ -854,7 +855,7 @@ def _weapon_actions() -> list[dict]:
45 + 2 * tier, [12, 26, 42, 60, 80, 105][tier], 45 + 2 * tier, [12, 26, 42, 60, 80, 105][tier],
{plank: 2, herb: 3, **extra("staff", 2 + tier)}, {f"{WOODS[tier]}_staff": 1}, {plank: 2, herb: 3, **extra("staff", 2 + tier)}, {f"{WOODS[tier]}_staff": 1},
group="Staves")) group="Staves"))
actions.append(_action(f"lw_{WOODS[tier]}_bow", "leatherworking", BOWS[tier], LEATHERS[tier][4] + 4, actions.append(_action(f"lw_{WOODS[tier]}_bow", "leatherworking", BOWS[tier], TIER_LEVELS[tier] + 4,
40 + 2 * tier, [12, 26, 42, 60, 80, 105][tier], 40 + 2 * tier, [12, 26, 42, 60, 80, 105][tier],
{plank: 2, leather: 2, **extra("bow", 2 + tier)}, {f"{WOODS[tier]}_bow": 1}, {plank: 2, leather: 2, **extra("bow", 2 + tier)}, {f"{WOODS[tier]}_bow": 1},
group="Bows")) group="Bows"))
@ -972,12 +973,12 @@ ACTIONS = [
fire="still", fuel=POTION_TIER[potion]) fire="still", fuel=POTION_TIER[potion])
for potion, name, level, herb, second, skill, _effect in POTIONS], for potion, name, level, herb, second, skill, _effect in POTIONS],
_action("hunt_birds", "hunting", "Snare birds", 1, 25, 6, outputs={"feathers": 3}), _action("hunt_birds", "hunting", "Snare birds", 1, 25, 6, outputs={"feathers": 3}),
_action("hunt_deer", "hunting", "Hunt deer", 8, 40, 13, outputs={"raw_meat": 2, "hide": 1}), _action("hunt_deer", "hunting", "Hunt deer", 1, 25, 6, outputs={"raw_meat": 2, "hide": 1}),
_action("hunt_boar", "hunting", "Hunt boar", 25, 50, 30, outputs={"raw_meat": 2, "boar_hide": 1}), _action("hunt_boar", "hunting", "Hunt boar", 15, 35, 15, outputs={"raw_meat": 2, "boar_hide": 1}),
_action("hunt_bear", "hunting", "Hunt bears", 40, 60, 48, outputs={"raw_meat": 3, "bear_pelt": 1}), _action("hunt_bear", "hunting", "Hunt bears", 30, 45, 28, outputs={"raw_meat": 3, "bear_pelt": 1}),
_action("hunt_elk", "hunting", "Hunt elk", 50, 70, 64, outputs={"raw_meat": 3, "elk_hide": 1}), _action("hunt_elk", "hunting", "Hunt elk", 45, 55, 45, outputs={"raw_meat": 3, "elk_hide": 1}),
_action("hunt_sabrecat", "hunting", "Track sabrecats", 65, 80, 84, outputs={"raw_meat": 3, "sabrecat_pelt": 1}), _action("hunt_sabrecat", "hunting", "Track sabrecats", 60, 65, 62, outputs={"raw_meat": 3, "sabrecat_pelt": 1}),
_action("hunt_mammoth", "hunting", "Hunt mammoths", 80, 90, 108, outputs={"raw_meat": 5, "mammoth_hide": 1}), _action("hunt_mammoth", "hunting", "Hunt mammoths", 75, 80, 85, outputs={"raw_meat": 5, "mammoth_hide": 1}),
*_tiered_actions(), *_tiered_actions(),
_action("smith_arrows", "smithing", "Arrows", 5, 30, 10, _action("smith_arrows", "smithing", "Arrows", 5, 30, 10,
{"copper_bar": 1, "logs": 1, "feathers": 2}, {"arrows": 15}, group="Hardware"), {"copper_bar": 1, "logs": 1, "feathers": 2}, {"arrows": 15}, group="Hardware"),
@ -4472,6 +4473,11 @@ PATCH_NOTES = [
("balance", "Combat XP reduced to keep it in line with professions. Eating now delays your next swing; eat higher tier food to reduce the impact."), ("balance", "Combat XP reduced to keep it in line with professions. Eating now delays your next swing; eat higher tier food to reduce the impact."),
("balance", "Construction workbench now also affects labour on building sites."), ("balance", "Construction workbench now also affects labour on building sites."),
("balance", "Weapon trophies drop more often, since the town needs weapons too: 3% → 10% from races, 6% → 20% per weapon type from bosses."), ("balance", "Weapon trophies drop more often, since the town needs weapons too: 3% → 10% from races, 6% → 20% per weapon type from bosses."),
("balance", "Hunting and Leatherworking tiers now unlock at 1 / 15 / 30 / 45 / 60 / 75, like every other trade. "
"Hunting: deer 8 → 1, boar 25 → 15, bears 40 → 30, elk 50 → 45, sabrecats 65 → 60, mammoths 80 → 75. "
"Leatherworking: tanning, armour and bows 5 levels lower from hard leather up."),
("balance", "Hunting time and XP now match Fishing: deer 40s · 13 XP → 25s · 6 XP (same as birds), boar 50s · 30 → 35s · 15, "
"bears 60s · 48 → 45s · 28, elk 70s · 64 → 55s · 45, sabrecats 80s · 84 → 65s · 62, mammoths 90s · 108 → 80s · 85."),
]}, ]},
] ]

View file

@ -755,7 +755,7 @@ class TierTest(unittest.TestCase):
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 self.assertIn(f"make_{key}_shield", game.ACTION_BY_ID) # builders make shields
for *_, prefix, _label, _level in game.LEATHERS: for *_, prefix, _label 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)
for *_, prefix, _label in game.CLOTHS: for *_, prefix, _label in game.CLOTHS: