Icons: game-icons.net glyphs tinted per tier, built into one sprite

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-19 10:04:38 +01:00
parent 2eed9b7ec4
commit 5cc5b98d61
7 changed files with 314 additions and 18 deletions

124
game.py
View file

@ -2363,6 +2363,130 @@ def buy_perk(player: dict, perk: str) -> str | None:
return None
# --- icons ------------------------------------------------------------------------
# Every item, skill, class, building, prayer and output-less action gets a
# game-icons.net glyph (CC BY 3.0) and a tint. Families share a shape and are
# told apart by colour: a rune sword is the copper sword in cyan. The sprite
# with just these glyphs is built by tools/build_icons.py into static/icons.svg.
METAL_TINTS = {"copper": "#d07a3c", "iron": "#9aa1ab", "steel": "#d4dae2",
"mithril": "#6f8fec", "adamant": "#4cb878", "rune": "#3fd0e0"}
WOOD_TINTS = ["#b9844e", "#8f5e30", "#a3b86c", "#d0663a", "#6f9a4a", "#a77be8"]
LEATHER_TINTS = ["#b07a4a", "#8a5a32", "#6b4a33", "#5fae5a", "#4f86d6", "#d0503c"]
HERB_TINTS = {"guam_leaf": "#7fbf5a", "marrentill": "#e7c84a", "tarromin": "#d05a8a",
"harralander": "#f0b030", "ranarr": "#8a6fd0", "snapdragon": "#e86a9a"}
PIECE_GLYPHS = {"sword": "pointy-sword", "shield": "round-shield", "helmet": "visored-helm",
"legs": "leg-armor", "body": "breastplate"}
TOOL_GLYPHS = {"pickaxe": "war-pick", "axe": "wood-axe", "hoe": "sickle", "fishing rod": "fishing-pole",
"hunting knife": "bowie-knife", "hammer": "claw-hammer"}
LEATHER_GLYPHS = {"cap": "hood", "legs": "trousers", "body": "leather-vest"}
GLYPHS = {
"stone": ("stone-block", "#a8a29e"), "wheat": ("wheat", "#e3c060"), "vegetables": ("carrot", "#f08a3c"),
"feathers": ("feather", "#e8e8ee"), "raw_meat": ("meat", "#e06a6a"), "arrows": ("arrow-cluster", "#c9b28a"),
"bricks": ("brick-pile", "#c66a45"), "cut_stone": ("stone-stack", "#b8b2aa"), "beam": ("wood-beam", "#9a6a3a"),
"bread": ("bread", "#deb064"), "cooked_meat": ("ham-shank", "#cf8f50"), "stew": ("hot-meal", "#c9884a"),
"bones": ("broken-bone", "#e9dfc6"), "big_bones": ("crossed-bones", "#e9dfc6"),
"dragon_bones": ("dinosaur-bones", "#a6d98f"), "studded_body": ("leather-armor", "#a3825a"),
"coal": ("ore", "#5d626b"), "water_barrel": ("barrel", "#5aa0d8"),
"raw_shrimp": ("shrimp", "#f39a82"), "raw_trout": ("flatfish", "#9fb5c8"), "raw_salmon": ("salmon", "#f08a6a"),
"raw_eel": ("eel", "#7f9a6a"), "raw_lobster": ("crab", "#e05a3a"), "raw_swordfish": ("angler-fish", "#7fa3c8"),
"cooked_shrimp": ("shrimp", "#f0b07a"), "cooked_trout": ("fish-cooked", "#d9a060"),
"cooked_salmon": ("fish-cooked", "#f09a6a"), "smoked_eel": ("eel", "#b07a4a"),
"cooked_lobster": ("crab", "#f07a4a"), "cooked_swordfish": ("fish-cooked", "#c8a070"),
}
SKILL_GLYPHS = {
"mining": ("mining", "#b8b2aa"), "woodcutting": ("wood-axe", "#c98a4a"), "farming": ("wheat", "#e3c060"),
"hunting": ("deer-head", "#c49a6c"), "fishing": ("fishing-pole", "#5aa0d8"), "smithing": ("anvil", "#d07a3c"),
"masonry": ("brick-wall", "#c66a45"), "construction": ("hammer-nails", "#d1a46a"),
"cooking": ("cooking-pot", "#e0703a"), "leatherworking": ("sewing-needle", "#d6a26e"),
"herblore": ("cauldron", "#7fbf5a"), "combat": ("crossed-swords", "#e05a5a"), "prayer": ("prayer", "#e9dfc6"),
"reconnaissance": ("spyglass", "#6f8fec"),
}
CLASS_GLYPHS = {"warrior": ("black-knight-helm", "#c0c6d0"), "scout": ("bow-arrow", "#8fbf6a"),
"artisan": ("anvil-impact", "#e0a050"), "pioneer": ("compass", "#4fb3d9")}
BUILDING_GLYPHS = {
"houses": ("house", "#d0a060"), "walls": ("stone-wall", "#a8a29e"), "barracks": ("barracks-tent", "#c06a4a"),
"smithy": ("anvil", "#d07a3c"), "temple": ("temple-gate", "#e9dfc6"), "granary": ("granary", "#e3c060"),
"lumber_shed": ("wood-pile", "#b9844e"), "well": ("well", "#5aa0d8"), "spymaster": ("hooded-figure", "#8a7fd0"),
"storehouse": ("wooden-crate", "#b9844e"),
}
ACTION_GLYPHS = {
"fight_wolves": ("wolf-head", "#9aa1ab"), "fight_scouts": ("hooded-assassin", "#a08060"),
"fight_ruins": ("castle-ruins", "#a8a29e"), "fight_stronghold": ("castle", "#8a8f98"),
"fight_green_dragon": ("dragon-head", "#5fae5a"), "fight_blue_dragon": ("dragon-head", "#4f86d6"),
"fight_red_dragon": ("dragon-head", "#d0503c"), "fight_black_dragon": ("dragon-head", "#8a8f98"),
"sabotage": ("fire-bomb", "#e0703a"), "recon_roads": ("spyglass", "#6f8fec"), "recon_camps": ("spyglass", "#8a7fd0"),
"labour": ("hammer-nails", "#d1a46a"), "clear_wolves": ("wolf-head", "#9aa1ab"),
"catch_goblins": ("goblin-head", "#8fbf6a"), "drive_bear": ("bear-head", "#8a5a32"), "cull_boars": ("boar", "#a06a4a"),
"catch_rats": ("rat", "#9aa1ab"), "clear_rockslide": ("falling-rocks", "#a8a29e"),
}
PRAYER_GLYPHS = {"thick_skin": ("shield", "#a8a29e"), "burst_of_strength": ("biceps", "#e06a6a"),
"rapid_heal": ("heart-plus", "#e06a8a"), "steel_skin": ("armor-upgrade", "#d4dae2"),
"superhuman_strength": ("biceps", "#ff8a3a"), "second_wind": ("wind-hole", "#8fd0e0"),
"protection": ("aura", "#f0d060"), "piety": ("angel-wings", "#f0e6c0")}
UI_GLYPHS = ["two-coins", "sparkles", "hearts", "prayer", "checked-shield"]
def _assign_glyphs() -> None:
for item, (glyph, tint) in GLYPHS.items():
ITEMS[item].update(glyph=glyph, tint=tint)
for key, _name, ore, *_rest in METALS:
tint = METAL_TINTS[key]
if ore:
ITEMS[ore[0]].update(glyph="ore", tint=tint)
ITEMS[f"{key}_bar"].update(glyph="metal-bar", tint=tint)
for piece, glyph in PIECE_GLYPHS.items():
ITEMS[f"{key}_{piece}"].update(glyph=glyph, tint=tint)
for tool, glyph in TOOL_GLYPHS.items():
ITEMS[f"{key}_{tool.replace(' ', '_')}"].update(glyph=glyph, tint=tint)
for (log, *_tree), (plank, _name), tint in zip(TREES, PLANKS, WOOD_TINTS):
ITEMS[log].update(glyph="log", tint=tint)
ITEMS[plank].update(glyph="planks", tint=tint)
for (raw, leather, prefix, *_rest), tint in zip(LEATHERS, LEATHER_TINTS):
ITEMS[raw[0]].update(glyph="animal-hide", tint=tint)
ITEMS[leather[0]].update(glyph="rolled-cloth", tint=tint)
for suffix, glyph in LEATHER_GLYPHS.items():
ITEMS[f"{prefix}_{suffix}"].update(glyph=glyph, tint=tint)
for herb, tint in HERB_TINTS.items():
ITEMS[herb].update(glyph="herbs-bundle", tint=tint)
for potion, *_rest, skill, _effect in POTIONS:
if skill == "combat":
ITEMS[potion].update(glyph="potion-ball", tint="#e05a5a")
else:
ITEMS[potion].update(glyph="round-bottom-flask", tint=SKILL_GLYPHS[skill][1])
for skill in SKILLS:
skill["glyph"], skill["tint"] = SKILL_GLYPHS[skill["id"]]
for key, spec in CLASSES.items():
spec["glyph"], spec["tint"] = CLASS_GLYPHS[key]
for key, spec in BUILDINGS.items():
spec["glyph"], spec["tint"] = BUILDING_GLYPHS[key]
for prayer in PRAYERS:
prayer["glyph"], prayer["tint"] = PRAYER_GLYPHS[prayer["id"]]
for action in ACTIONS:
if action["id"] in ACTION_GLYPHS:
action["glyph"], action["tint"] = ACTION_GLYPHS[action["id"]]
elif action["outputs"]:
first = ITEMS[next(iter(action["outputs"]))]
action["glyph"], action["tint"] = first["glyph"], first["tint"]
elif action.get("special") in ("bury", "offer"):
bone = ITEMS[next(iter(action["inputs"]))]
action["glyph"] = "tombstone" if action["special"] == "bury" else "candle-holder"
action["tint"] = bone["tint"] if action["special"] == "bury" else "#f0c060"
else:
action["glyph"], action["tint"] = SKILL_GLYPHS[action["skill"]]
def all_glyphs() -> set[str]:
"""Every glyph the game draws, for building the sprite."""
names = set(UI_GLYPHS)
for collection in (ITEMS.values(), SKILLS, CLASSES.values(), BUILDINGS.values(), PRAYERS, ACTIONS):
names.update(entry["glyph"] for entry in collection)
return names
_assign_glyphs()
def content() -> dict:
"""The static tables the client renders from."""
buildings = {