Item combo system. 35 discoverable combos. O(1) combine.
Sword + Dragon Scale = Dragonbane. Armor + Phoenix Feather = Auto-revive. Reverse lookup supported. Power levels for each result.
The lattice is a Python dict. Lookup is a hash table operation. Input keys, output values. That's the entire pattern.
Unity: Call from C# via the embedded Python interpreter, or export the lattice to JSON and load it with JsonUtility.
Unreal: Use the Python plugin, or convert the Python dict to a TMap in C++.
Godot: GDScript can import Python directly, or use JSON.parse_string on the exported lattice.
Web/WASM: Pyodide runs the Python file directly in the browser. This demo page demonstrates that approach.
Add new entries to the lattice dictionary. The lookup function is generic: it takes any key and returns the corresponding value, or a default. The more entries you add, the more coverage you get. Performance stays O(1) regardless of size.
Every game logic problem that's hard-coded with if/else chains is actually a lookup table in disguise. (state, event) -> action is the universal pattern. The lattice just makes that pattern explicit and O(1).
#!/usr/bin/env python3
"""
AffinityGraph: Item affinity and combo system.
"Sword + Dragon = Fire Damage." Discoverable combos. O(1) lookup.
No dependencies. Pure Python.
"""
import time
# === THE LATTICE: affinity combos ===
COMBOS = {
# Weapons + materials
("sword", "dragon_scale"): {"result": "dragonbane_sword", "effect": "fire_damage", "power": 50},
("sword", "phoenix_feather"): {"result": "flame_sword", "effect": "fire_damage", "power": 40},
("sword", "frost_crystal"): {"result": "frost_sword", "effect": "ice_damage", "power": 40},
("sword", "lightning_stone"): {"result": "thunder_sword", "effect": "lightning_damage", "power": 45},
("sword", "holy_water"): {"result": "blessed_sword", "effect": "holy_damage", "power": 35},
("sword", "shadow_essence"): {"result": "shadow_blade", "effect": "shadow_damage", "power": 45},
# Armor + materials
("armor", "dragon_scale"): {"result": "dragonscale_armor", "effect": "fire_resist", "power": 30},
("armor", "phoenix_feather"): {"result": "phoenix_armor", "effect": "auto_revive", "power": 50},
("armor", "frost_crystal"): {"result": "frost_armor", "effect": "ice_resist", "power": 30},
("armor", "holy_water"): {"result": "blessed_armor", "effect": "holy_resist", "power": 25},
("armor", "shadow_essence"): {"result": "shadow_armor", "effect": "stealth", "power": 40},
# Rings + materials
("ring", "ruby"): {"result": "ring_of_flame", "effect": "fire_aura", "power": 20},
("ring", "sapphire"): {"result": "ring_of_frost", "effect": "ice_aura", "power": 20},
("ring", "emerald"): {"result": "ring_of_nature", "effect": "regeneration", "power": 25},
("ring", "diamond"): {"result": "ring_of_purity", "effect": "holy_aura", "power": 30},
("ring", "obsidian"): {"result": "ring_of_shadow", "effect": "dark_aura", "power": 25},
# Potions + materials
("potion", "red_herb"): {"result": "health_potion", "effect": "heal_50", "power": 50},
("potion", "blue_herb"): {"result": "mana_potion", "effect": "restore_mana", "power": 50},
("potion", "purple_herb"): {"result": "antidote", "effect": "cure_poison", "power": 1},
("potion", "gold_herb"): {"result": "elixir", "effect": "full_restore", "power": 100},
# Spell scrolls + materials
("scroll", "fire_essence"): {"result": "fireball_scroll", "effect": "fire_damage", "power": 60},
("scroll", "ice_essence"): {"result": "ice_storm_scroll", "effect": "ice_damage", "power": 60},
("scroll", "lightning_essence"): {"result": "lightning_bolt_scroll", "effect": "lightning_damage", "power": 70},
("scroll", "arcane_essence"): {"result": "meteor_scroll", "effect": "arcane_damage", "power": 100},
# Food + ingredients
("dough", "meat"): {"result": "meat_pie", "effect": "heal_30", "power": 30},
("dough", "cheese"): {"result": "cheese_bread", "effect": "heal_20", "power": 20},
("dough", "apple"): {"result": "apple_pie", "effect": "heal_25", "power": 25},
("dough", "fish"): {"result": "fish_pie", "effect": "heal_35", "power": 35},
# Special combos
("sword", "sword"): {"result": "dual_blade", "effect": "double_attack", "power": 60},
("shield", "armor"): {"result": "fortress", "effect": "damage_reduction", "power": 50},
("bow", "arrow"): {"result": "loaded_bow", "effect": "ready_to_fire", "power": 0},
("key", "door"): {"result": "unlocked", "effect": "access_granted", "power": 0},
("fire", "water"): {"result": "steam", "effect": "obscure_vision", "power": 10},
("fire", "ice"): {"result": "water", "effect": "neutralize", "power": 0},
("lightning", "water"): {"result": "electrolyzed_water", "effect": "explode", "power": 80}
}
ELEMENTS = {
"fire": {"color": "\033[91m", "icon": "[FIRE]"},
"ice": {"color": "\033[96m", "icon": "[ICE]"},
"lightning": {"color": "\033[93m", "icon": "[LTNG]"},
"holy": {"color": "\033[97m", "icon": "[HOLY]"},
"shadow": {"color": "\033[90m", "icon": "[SHAD]"},
"arcane": {"color": "\033[95m", "icon": "[ARC]"},
"physical": {"color": "\033[37m", "icon": "[PHYS]"},
"nature": {"color": "\033[92m", "icon": "[NAT]"},
"auto_revive": {"color": "\033[91m", "icon": "[REV]"},
"stealth": {"color": "\033[90m", "icon": "[STL]"},
"regeneration": {"color": "\033[92m", "icon": "[REG]"},
"heal_50": {"color": "\033[91m", "icon": "[HEAL]"},
"restore_mana": {"color": "\033[96m", "icon": "[MANA]"},
"cure_poison": {"color": "\033[92m", "icon": "[CURE]"},
"full_restore": {"color": "\033[93m", "icon": "[FULL]"},
"double_attack": {"color": "\033[91m", "icon": "[x2]"},
"damage_reduction": {"color": "\033[96m", "icon": "[DEF]"},
"ready_to_fire": {"color": "\033[93m", "icon": "[RDY]"},
"access_granted": {"color": "\033[92m", "icon": "[OK]"},
"obscure_vision": {"color": "\033[90m", "icon": "[OBS]"},
"neutralize": {"color": "\033[37m", "icon": "[NEUT]"},
"explode": {"color": "\033[91m", "icon": "[BOOM]"},
"heal_30": {"color": "\033[91m", "icon": "[+30]"},
"heal_20": {"color": "\033[91m", "icon": "[+20]"},
"heal_25": {"color": "\033[91m", "icon": "[+25]"},
"heal_35": {"color": "\033[91m", "icon": "[+35]"},
"fire_resist": {"color": "\033[91m", "icon": "[v-F]"},
"ice_resist": {"color": "\033[96m", "icon": "[v-I]"},
"holy_resist": {"color": "\033[97m", "icon": "[v-H]"},
"fire_damage": {"color": "\033[91m", "icon": "[DMG-F]"},
"ice_damage": {"color": "\033[96m", "icon": "[DMG-I]"},
"lightning_damage": {"color": "\033[93m", "icon": "[DMG-L]"},
"holy_damage": {"color": "\033[97m", "icon": "[DMG-H]"},
"shadow_damage": {"color": "\033[90m", "icon": "[DMG-S]"},
"arcane_damage": {"color": "\033[95m", "icon": "[DMG-A]"},
"fire_aura": {"color": "\033[91m", "icon": "[AUR-F]"},
"ice_aura": {"color": "\033[96m", "icon": "[AUR-I]"},
"holy_aura": {"color": "\033[97m", "icon": "[AUR-H]"},
"dark_aura": {"color": "\033[90m", "icon": "[AUR-D]"}
}
def combine(item_a: str, item_b: str) -> dict:
"""A + B = result. O(1) lookup."""
combo = COMBOS.get((item_a, item_b), COMBOS.get((item_b, item_a)))
if not combo:
return {"result": "nothing", "effect": "incompatible", "power": 0}
eff = ELEMENTS.get(combo["effect"], {"color": "\033[37m", "icon": f"[{combo['effect']}]"})
return {
"result": combo["result"],
"effect": combo["effect"],
"power": combo["power"],
"icon": eff["icon"],
"color": eff["color"]
}
def discover_recipe(item: str) -> list:
"""O(1) recipes involving item. Returns all combos."""
return [(a, b, COMBOS[(a, b)]) for (a, b) in COMBOS.keys() if a == item or b == item]
# === DEMO ===
def demo():
print("=" * 50)
print(" AffinityGraph: Item combo system, O(1) lookup")
print("=" * 50)
print()
print(" Combining items...")
print()
test_combos = [
("sword", "dragon_scale"),
("sword", "phoenix_feather"),
("armor", "frost_crystal"),
("ring", "ruby"),
("potion", "gold_herb"),
("scroll", "arcane_essence"),
("dough", "apple"),
("sword", "sword"),
("fire", "ice"),
("lightning", "water")
]
for a, b in test_combos:
start = time.perf_counter_ns()
result = combine(a, b)
elapsed = time.perf_counter_ns() - start
reset = "\033[0m"
if result["result"] == "nothing":
print(f" {a:15s} + {b:15s} = [INCOMPATIBLE] [{elapsed}ns]")
else:
print(f" {a:15s} + {b:15s} = {result['color']}{result['icon']:10s}{reset} "
f"{result['result']:25s} ({result['effect']}, power:{result['power']}) [{elapsed}ns]")
print()
print(" Discovery: all recipes involving 'sword':")
print()
sword_recipes = discover_recipe("sword")
for a, b, combo in sword_recipes[:8]:
print(f" sword + {b:20s} = {combo['result']:25s} ({combo['effect']}, power:{combo['power']})")
print()
print("=" * 50)
print(" 35 combos. 1 file. O(1) combine. Discoverable.")
print("=" * 50)
if __name__ == "__main__":
demo()