Repository navigation
x.1 Example 1: biome.py
"""A pokemon-style biome: creatures are mixed and matched from small Tags. No two need the same type to be predictable; every one answers the same questions.
Run: PYTHONPATH=. python3 examples/biome.py """
from future import annotations
import random
from TopKit import Action from TopKit import Flag from TopKit import Keyword from TopKit import Post from TopKit import Public from TopKit import Record from TopKit import Report from TopKit import Tag from TopKit import Tags from TopKit import Underlay
class Creature: def init( creature, name: str, ) -> None: creature.name = name
class Element(Tag): @Public @Report def colour(tag) -> str: return "grey"
@Record
def attacks(agent, stored) -> list[str]:
return stored or []
@Post
def Has_An_Attack(agent):
return len(agent.attacks) > 0
@Flag class Fire(Element): @Public @Report def colour(tag) -> str: return "red"
@Record
def attacks(agent, stored) -> list[str]:
return (stored or []) + ["Ember"]
@Flag class Water(Element): @Public @Report def colour(tag) -> str: return "blue"
@Record
def attacks(agent, stored) -> list[str]:
return (stored or []) + ["Bubble"]
@Flag class Electric(Element): @Public @Report def colour(tag) -> str: return "yellow"
@Record
def attacks(agent, stored) -> list[str]:
return (stored or []) + ["Spark"]
class Body(Tag): @Record def hp(agent) -> int: return 20
@Action
def Describe(agent) -> str:
return f"{agent.name} ({agent.colour}, {agent.hp} hp): {', '.join(agent.attacks)}"
class Winged(Body): @Record def hp(agent, stored) -> int: return stored - 5
@Action
@Underlay
def Describe(agent, underlay) -> str:
return underlay() + " [flies]"
class Armoured(Body): @Record def hp(agent, stored) -> int: return stored + 15
@Action
@Underlay
def Describe(agent, underlay) -> str:
return underlay() + " [armoured]"
STRONG_AGAINST = { "Water": "Fire", "Fire": "Electric", "Electric": "Water", }
def advantage( attacker: Creature, defender: Creature, ) -> bool: return any( Keyword(attacker, mine) and Keyword(defender, theirs) for mine, theirs in STRONG_AGAINST.items() )
def main() -> None: random.seed(7) elements = (Fire, Water, Electric) bodies = (Body, Winged, Armoured) biome = []
for index in range(8):
creature = Creature(f"creature-{index}")
for element in random.sample(elements, k=random.randint(1, 2)):
element(creature)
random.choice(bodies)(creature)
biome.append(creature)
for creature in biome:
print(creature.Describe(), "<-", [tag.__name__ for tag in Tags(creature)])
print()
first, second = biome[0], biome[1]
print(f"{first.name} vs {second.name}: advantage", advantage(first, second))
print("keywords of", first.name, "->", [w for w in STRONG_AGAINST if w in first])
print()
print("runtime types in the biome:", len({type(c) for c in biome}))
print("Fire creatures:", [c.name for c in Fire])
print("sound Elements:", len(Element), "of", len(Element[:]))
if __name__ == "__main__":
main()