Skip to content

Instantly share code, notes, and snippets.

Created Aug 4, 2017

What would you like to do?
Procedural Pantheon by acidicrhyme
# WordNet/Jung Pantheon Generator copyright 2017 Adam Biltcliffe
# Released under the terms of the MIT License -
from nltk.corpus import wordnet as wn
import textblob as tb
import random
import graphviz
# convenience methods for identifying seed synsets
def s(word):
for synset in wn.synsets(word):
print(, synset.definition())
# hand-selected seed words based on Jungian archetypes
archetypes = [
# innocent
# everyman
# hero
# caregiver
# explorer
# rebel
# jester
# sage
# magician
# ruler
# also add a few extras in so that the structure of the pantheon is
# less repetitive
extra_concepts = ['animal.n.01', 'birth.n.02', 'death.n.01', 'ocean.n.01',
'plant.n.02', 'weather.n.01']
# This list is very hard to get right and almost certainly imperfect
to_pluralise = [wn.synset('physical_entity.n.01'),
def should_pluralise(thing):
return any(c in c.lowest_common_hypernyms(thing) for c in to_pluralise)
def choose_domains(m, d, focus):
if len(m) == 0:
n = min(random.choice([1, 1, 1, 1, 2, 2, 3]), len(d))
return random.sample(d, n)
hypos = m[0].hyponyms()
if len(hypos) == 0 or random.random() < focus:
return choose_domains(m[1:], d+[m[0]], focus)
return choose_domains(m[1:], d+hypos, focus)
def name_domain(d):
lemma = ' '.join([word.capitalize() for word in random.choice(d.lemma_names()).split('_')])
if should_pluralise(d):
return tb.Word(lemma).pluralize()
return lemma
def domain_importance(d):
return max(len(p) for p in d.hypernym_paths())
titles = ['God', 'Goddess', 'Deity', 'Demigod']
# this brief experiment generated "The Goddess of Attraction appears in the form of a window washer."
#forms = list(wn.synset('organism.n.01').closure(lambda s: s.hyponyms()))
class Deity(object):
def __init__(self, domains):
domains = sorted(domains, key=domain_importance) = domains
if len(domains) == 1:
domain_name_string = name_domain(domains[0])
domain_names = [name_domain(d) for d in domains]
domain_name_string = ', '.join(domain_names[:-1]) + " and " + domain_names[-1]
self.title = random.choice(titles) = "{0} of {1}".format(self.title, domain_name_string)
self.rank = sum(domain_importance(d) for d in domains) / len(domains)
#self.form = max(random.sample(forms, 250), key=lambda f: self.affinity(f))
#print("The {0} appears in the form of a {1}".format(, self.form))
self.children = []
def affinity(self, other):
if isinstance(other, Deity):
return min(a.path_similarity(b) for a in for b in
else: #if isinstance(other, nltk.corpus.reader.wordnet.Synset):
return min(a.path_similarity(other) for a in
deities = []
for a in archetypes:
q = [wn.synset(c) for c in a]
domains = choose_domains(q, [], 0.9)
extra = random.sample(extra_concepts, random.randrange(4))
for q in [[wn.synset(c)] for c in extra]:
domains = choose_domains(q, [], 0.3)
#deities.sort(key=lambda d: d.affinity(wn.synset('leadership.n.04')))
deities.sort(key=lambda d: d.rank)
root = deities.pop(0)
root.nodename = "R"
pantheon = [root]
while len(deities) > 0:
d = deities.pop(0)
d.nodename = "D{0}".format(n)
n += 1
parent = max(pantheon, key=d.affinity)
dot = graphviz.Digraph(comment="The Pantheon")
def visit(deity, indent=0):
#print(" " * indent +
for c in deity.children:
visit(c, indent+1)
dot.edge(deity.nodename, c.nodename)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.