Fantasy-Map-Generator/modules/religions-generator.js
Ángel Montero Lamas a51d2e6403 religions-generator.js (#724)
Sorted the lists, arrays and weighted arrays of items in alphabetical order. Some remain in the order assigned by weighted random.
I think this helps people spot missing items on the list if they check by name.
The number of items is the same, they just got reordered.
2022-11-27 13:12:43 -05:00

968 lines
25 KiB
JavaScript

'use strict';
window.Religions = (function () {
// name generation approach and relative chance to be selected
const approach = {
Number: 1,
Being: 3,
Adjective: 5,
"Color + Animal": 5,
"Adjective + Animal": 5,
"Adjective + Being": 5,
"Adjective + Genitive": 1,
"Color + Being": 3,
"Color + Genitive": 3,
"Being + of + Genitive": 2,
"Being + of the + Genitive": 1,
"Animal + of + Genitive": 1,
"Adjective + Being + of + Genitive": 2,
"Adjective + Animal + of + Genitive": 2
};
// turn weighted array into simple array
const approaches = [];
for (const a in approach) {
for (let j = 0; j < approach[a]; j++) {
approaches.push(a);
}
}
const base = {
number: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve"],
being: [
"Ancestor",
"Ancient",
"Brother",
"Chief",
"Council",
"Creator",
"Deity",
"Elder",
"Father",
"Forebear",
"Forefather",
"Giver",
"God",
"Goddess",
"Guardian",
"Lady",
"Lord",
"Maker",
"Master",
"Mother",
"Numen",
"Overlord",
"Reaper",
"Ruler",
"Sister",
"Spirit",
"Virgin"
],
animal: [
"Antelope",
"Ape",
"Badger",
"Basilisk",
=======
"God",
"Goddess",
"Lord",
"Lady",
"Deity",
"Creator",
"Maker",
"Master",
"Mother",
"Numen",
"Overlord",
"Reaper"
"Ruler",
"Sister",
"Spirit",
"Virgin",
],
animal: [
"Antelope",
"Ape",
"Badger",
"Bear",
"Beaver",
"Bison",
"Boar",
"Buffalo",
<<<<<<< HEAD
"Camel",
"Cat",
"Centaur",
"Chimera",
=======
"Cat",
>>>>>>> c6917a14 (religion gen fix)
"Cobra",
"Crane",
"Crocodile",
"Crow",
<<<<<<< HEAD
"Cyclope",
"Deer",
"Dog",
"Dragon",
"Eagle",
"Elk",
"Falcon",
"Deer",
"Dog",
"Eagle",
"Elk",
"Fox",
"Goat",
"Goose",
"Hare",
"Hawk",
"Heron",
"Horse",
"Hound",
"Hyena",
"Ibis",
"Jackal",
"Jaguar",
"Kraken",
"Lark",
"Leopard",
"Lion",
"Mantis",
"Marten",
"Moose",
"Mule",
"Narwhal",
"Owl",
"Ox",
"Panther",
"Pegasus",
"Phoenix",
"Panther",
"Rat",
"Raven",
"Rook",
"Scorpion",
"Serpent",
"Shark",
"Sheep",
"Snake",
"Sphinx",
"Shark",
"Sheep",
"Snake",
"Spider",
"Swan",
"Tiger",
"Turtle",
"Unicorn",
"Viper",
"Vulture",
"Walrus",
"Wolf",
"Wolverine",
"Worm",
"Wyvern"
],
adjective: [
"Aggressive",
"Almighty",
"Ancient",
"Beautiful",
"Benevolent",
"Big",
"Blind",
"Blond",
"Bloody",
"Brave",
"Broken",
"Brutal",
"Burning",
"Calm",
"Cheerful",
"Crazy",
"Cruel",
"Dead",
"Deadly",
"Devastating",
"Distant",
"Disturbing",
"Divine",
"Dying",
"Eternal",
"Evil",
"Explicit",
"Fair",
"Far",
"Fat",
"Fatal",
"Favorable",
"Flying",
"Friendly",
"Frozen",
"Giant",
"Good",
"Grateful",
"Great",
"Happy",
"High",
"Holy",
"Honest",
"Huge",
"Hungry",
"Immutable",
"Infallible",
"Inherent",
"Last",
"Latter",
"Lost",
"Loud",
"Lucky",
"Mad",
"Magical",
"Main",
"Major",
"Marine",
"Naval",
"New",
"Old",
"Patient",
"Peaceful",
"Pregnant",
"Prime",
"Proud",
"Pure",
"Sacred",
"Sad",
"Scary",
"Secret",
"Selected",
"Severe",
"Silent",
"Sleeping",
"Slumbering",
"Strong",
"Sunny",
"Superior",
"Sustainable",
"Troubled",
"Unhappy",
"Unknown",
"Waking",
"Wild",
"Wise",
"Worried",
"Young"
],
genitive: [
"Cold",
"Day",
"Death",
"Doom",
"Fate",
"Fire",
"Fog",
"Frost",
"Gates",
"Heaven",
"Home",
"Ice",
"Justice",
"Life",
"Light",
"Lightning",
"Love",
"Nature",
"Night",
"Pain",
"Snow",
"Springs",
"Summer",
"Thunder",
"Time",
"Victory",
"War",
"Winter"
],
theGenitive: [
"Abyss",
"Blood",
"Dawn",
"Earth",
"East",
"Eclipse",
"Fall",
"Harvest",
"Moon",
"North",
"Peak",
"Rainbow",
"Sea",
"Sky",
"South",
"Stars",
"Storm",
"Sun",
"Tree",
"Underworld",
"West",
"Wild",
"Word",
"World"
],
color: [
"Amber",
"Black",
"Blue",
"Bright",
"Brown",
"Dark",
"Golden",
"Green",
"Grey",
"Light",
"Orange",
"Pink",
"Purple",
"Red",
"White",
"Yellow"
]
=======
"Camel",
"Falcon",
"Hound",
"Ox",
"Serpent"
],
adjective: [
"Aggressive",
"Almighty",
"Ancient",
"Beautiful",
"Benevolent",
"Big",
"Blind",
"Blond",
"Bloody",
"Brave",
"Broken",
"Brutal",
"Burning",
"Calm",
"Cheerful",
"Crazy",
"Cruel",
"Dead",
"Deadly",
"Devastating",
"Distant",
"Disturbing",
"Divine",
"Dying",
"Eternal",
"Evil",
"Explicit",
"Fair",
"Far",
"Fat",
"Fatal",
"Favorable",
"Flying",
"Friendly",
"Frozen",
"Giant",
"Good",
"Grateful",
"Great",
"Happy",
"High",
"Holy",
"Honest",
"Huge",
"Hungry",
"Immutable",
"Infallible"
"Inherent",
"Last",
"Latter",
"Lost",
"Loud",
"Lucky",
"Mad",
"Magical",
"Main",
"Major",
"Marine",
"Naval",
"New",
"Old",
"Patient",
"Peaceful",
"Pregnant",
"Prime",
"Proud",
"Pure",
"Sacred",
"Sad",
"Scary",
"Secret",
"Selected",
"Severe",
"Silent",
"Sleeping",
"Slumbering",
"Strong",
"Sunny",
"Superior",
"Sustainable",
"Troubled",
"Unhappy",
"Unknown",
"Waking",
"Wild",
"Wise",
"Worried",
"Young",
],
genitive: [
"Cold",
"Day",
"Death",
"Doom",
"Fate",
"Fire",
"Fog",
"Frost",
"Gates",
"Heaven",
"Home",
"Ice",
"Justice",
"Life",
"Light",
"Lightning",
"Love",
"Nature",
"Night",
"Pain",
"Snow",
"Springs",
"Summer",
"Thunder",
"Time",
"Victory"
"War",
"Winter",
],
theGenitive: [
"Abyss",
"Blood",
"Dawn",
"Earth",
"East",
"Eclipse",
"Fall",
"Harvest",
"Moon",
"North",
"Peak",
"Rainbow",
"Sea",
"Sky",
"South",
"Stars",
"Storm",
"Sun",
"Tree",
"Underworld",
"West",
"Wild"
"Word",
"World",
],
color: ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]
};
const forms = {
Folk: {Shamanism: 2, Animism: 2, 'Ancestor worship': 1, Polytheism: 2},
Organized: {Polytheism: 5, Dualism: 1, Monotheism: 4, 'Non-theism': 1},
Cult: {Cult: 1, 'Dark Cult': 1},
Heresy: {Heresy: 1}
};
const methods = {
"Random + type": 3,
"Random + ism": 1,
"Supreme + ism": 5,
"Faith of + Supreme": 5,
"Place + ism": 1,
"Culture + ism": 2,
"Place + ian + type": 6,
"Culture + type": 4
};
const types = {
Shamanism: {Beliefs: 3, Shamanism: 2, Spirits: 1},
Animism: {Spirits: 1, Beliefs: 1},
'Ancestor worship': {Beliefs: 1, Forefathers: 2, Ancestors: 2},
Polytheism: {Deities: 3, Faith: 1, Gods: 1, Pantheon: 1},
Dualism: {Religion: 3, Faith: 1, Cult: 1},
Monotheism: {Religion: 1, Church: 1},
'Non-theism': {Beliefs: 3, Spirits: 1},
Cult: {Cult: 4, Sect: 4, Arcanum: 1, Coterie: 1, Order: 1, Worship: 1},
"Dark Cult": {Cult: 2, Sect: 2, Blasphemy: 1, Circle: 1, Coven: 1, Idols: 1, Occultism: 1},
Heresy: {
Heresy: 3,
Sect: 2,
Apostates: 1,
Brotherhood: 1,
Circle: 1,
Dissent: 1,
Dissenters: 1,
Iconoclasm: 1,
Schism: 1,
Society: 1
}
};
const generate = function () {
TIME && console.time('generateReligions');
const cells = pack.cells,
states = pack.states,
cultures = pack.cultures;
const religions = (pack.religions = []);
cells.religion = new Uint16Array(cells.culture); // cell religion; initially based on culture
// add folk religions
pack.cultures.forEach(c => {
if (!c.i) return religions.push({i: 0, name: "No religion"});
if (c.removed) {
religions.push({
i: c.i,
name: "Extinct religion for " + c.name,
color: getMixedColor(c.color, 0.1, 0),
removed: true
});
return;
}
const form = rw(forms.Folk);
const name = c.name + ' ' + rw(types[form]);
const deity = form === 'Animism' ? null : getDeityName(c.i);
const color = getMixedColor(c.color, 0.1, 0); // `url(#hatch${rand(8,13)})`;
religions.push({i: c.i, name, color, culture: c.i, type: "Folk", form, deity, center: c.center, origins: [0]});
});
if (religionsInput.value == 0 || pack.cultures.length < 2)
return religions.filter(r => r.i).forEach(r => (r.code = abbreviate(r.name)));
const burgs = pack.burgs.filter(b => b.i && !b.removed);
const sorted =
burgs.length > +religionsInput.value
? burgs.sort((a, b) => b.population - a.population).map(b => b.cell)
: cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]);
const religionsTree = d3.quadtree();
const spacing = (graphWidth + graphHeight) / 6 / religionsInput.value; // base min distance between towns
const cultsCount = Math.floor((rand(10, 40) / 100) * religionsInput.value);
const count = +religionsInput.value - cultsCount + religions.length;
function getReligionsInRadius({x, y, r, max}) {
if (max === 0) return [0];
const cellsInRadius = findAll(x, y, r);
const religions = unique(cellsInRadius.map(i => cells.religion[i]).filter(r => r));
return religions.length ? religions.slice(0, max) : [0];
}
// generate organized religions
for (let i = 0; religions.length < count && i < 1000; i++) {
let center = sorted[biased(0, sorted.length - 1, 5)]; // religion center
const form = rw(forms.Organized);
const state = cells.state[center];
const culture = cells.culture[center];
const deity = form === 'Non-theism' ? null : getDeityName(culture);
let [name, expansion] = getReligionName(form, deity, center);
if (expansion === 'state' && !state) expansion = 'global';
if (expansion === 'culture' && !culture) expansion = 'global';
if (expansion === 'state' && Math.random() > 0.5) center = states[state].center;
if (expansion === 'culture' && Math.random() > 0.5) center = cultures[culture].center;
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c]))
center = cells.c[center].find(c => cells.burg[c]);
const [x, y] = cells.p[center];
const s = spacing * gauss(1, 0.3, 0.2, 2, 2); // randomize to make the placement not uniform
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
// add "Old" to name of the folk religion on this culture
const isFolkBased = expansion === "culture" || P(0.5);
const folk = isFolkBased && religions.find(r => r.culture === culture && r.type === "Folk");
if (folk && expansion === "culture" && folk.name.slice(0, 3) !== "Old") folk.name = "Old " + folk.name;
const origins = folk ? [folk.i] : getReligionsInRadius({x, y, r: 150 / count, max: 2});
const expansionism = rand(3, 8);
const baseColor = religions[culture]?.color || states[state]?.color || getRandomColor();
const color = getMixedColor(baseColor, 0.3, 0);
religions.push({
i: religions.length,
name,
color,
culture,
type: "Organized",
form,
deity,
expansion,
expansionism,
center,
origins
});
religionsTree.add([x, y]);
}
// generate cults
for (let i = 0; religions.length < count + cultsCount && i < 1000; i++) {
const form = rw(forms.Cult);
let center = sorted[biased(0, sorted.length - 1, 1)]; // religion center
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c]))
center = cells.c[center].find(c => cells.burg[c]);
const [x, y] = cells.p[center];
const s = spacing * gauss(2, 0.3, 1, 3, 2); // randomize to make the placement not uniform
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
const culture = cells.culture[center];
const origins = getReligionsInRadius({x, y, r: 300 / count, max: rand(0, 4)});
const deity = getDeityName(culture);
const name = getCultName(form, center);
const expansionism = gauss(1.1, 0.5, 0, 5);
const color = getMixedColor(cultures[culture].color, 0.5, 0); // "url(#hatch7)";
religions.push({
i: religions.length,
name,
color,
culture,
type: "Cult",
form,
deity,
expansion: "global",
expansionism,
center,
origins
});
religionsTree.add([x, y]);
}
expandReligions();
// generate heresies
religions
.filter((r) => r.type === 'Organized')
.forEach((r) => {
if (r.expansionism < 3) return;
const count = gauss(0, 1, 0, 3);
for (let i = 0; i < count; i++) {
let center = ra(
cells.i.filter(i => cells.religion[i] === r.i && cells.c[i].some(c => cells.religion[c] !== r.i))
);
if (!center) continue;
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c]))
center = cells.c[center].find(c => cells.burg[c]);
const [x, y] = cells.p[center];
if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other
const culture = cells.culture[center];
const name = getCultName('Heresy', center);
const expansionism = gauss(1.2, 0.5, 0, 5);
const color = getMixedColor(r.color, 0.4, 0.2); // "url(#hatch6)";
religions.push({
i: religions.length,
name,
color,
culture,
type: "Heresy",
form: r.form,
deity: r.deity,
expansion: "global",
expansionism,
center,
<<<<<<< HEAD
origins: [r.i]
=======
origin: r.i
>>>>>>> c6917a14 (religion gen fix)
});
religionsTree.add([x, y]);
}
});
expandHeresies();
checkCenters();
TIME && console.timeEnd('generateReligions');
};
const add = function (center) {
const {cells, religions} = pack;
const religionId = cells.religion[center];
const culture = cells.culture[center];
const color = getMixedColor(religions[religionId].color, 0.3, 0);
const type =
religions[religionId].type === "Organized" ? rw({Organized: 4, Cult: 1, Heresy: 2}) : rw({Organized: 5, Cult: 2});
const form = rw(forms[type]);
const deity =
type === "Heresy" ? religions[religionId].deity : form === "Non-theism" ? null : getDeityName(culture);
let name, expansion;
if (type === 'Organized') [name, expansion] = getReligionName(form, deity, center);
else {
name = getCultName(form, center);
expansion = 'global';
}
const formName = type === "Heresy" ? religions[religionId].form : form;
const code = abbreviate(
name,
religions.map((r) => r.code)
);
<<<<<<< HEAD
const i = religions.length;
=======
>>>>>>> c6917a14 (religion gen fix)
religions.push({
i,
name,
color,
culture,
type,
form: formName,
deity,
expansion,
expansionism: 0,
center,
cells: 0,
area: 0,
rural: 0,
urban: 0,
<<<<<<< HEAD
origins: [religionId],
=======
origin: r,
>>>>>>> c6917a14 (religion gen fix)
code
});
cells.religion[center] = i;
};
// growth algorithm to assign cells to religions
const expandReligions = function () {
const cells = pack.cells,
religions = pack.religions;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = [];
religions
.filter((r) => r.type === 'Organized' || r.type === 'Cult')
.forEach((r) => {
cells.religion[r.center] = r.i;
queue.queue({e: r.center, p: 0, r: r.i, s: cells.state[r.center], c: r.culture});
cost[r.center] = 1;
});
const neutral = (cells.i.length / 5000) * 200 * gauss(1, 0.3, 0.2, 2, 2) * neutralInput.value; // limit cost for organized religions growth
const popCost = d3.max(cells.pop) / 3; // enougth population to spered religion without penalty
while (queue.length) {
const next = queue.dequeue(),
n = next.e,
p = next.p,
r = next.r,
c = next.c,
s = next.s;
const expansion = religions[r].expansion;
cells.c[n].forEach(function (e) {
if (expansion === 'culture' && c !== cells.culture[e]) return;
if (expansion === 'state' && s !== cells.state[e]) return;
const cultureCost = c !== cells.culture[e] ? 10 : 0;
const stateCost = s !== cells.state[e] ? 10 : 0;
const biomeCost = biomesData.cost[cells.biome[e]];
const populationCost = Math.max(rn(popCost - cells.pop[e]), 0);
const heightCost = Math.max(cells.h[e], 20) - 20;
const waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
const totalCost =
p +
(cultureCost + stateCost + biomeCost + populationCost + heightCost + waterCost) / religions[r].expansionism;
if (totalCost > neutral) return;
if (!cost[e] || totalCost < cost[e]) {
if (cells.h[e] >= 20 && cells.culture[e]) cells.religion[e] = r; // assign religion to cell
cost[e] = totalCost;
queue.queue({e, p: totalCost, r, c, s});
}
});
}
};
// growth algorithm to assign cells to heresies
const expandHeresies = function () {
const cells = pack.cells,
religions = pack.religions;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = [];
religions
.filter((r) => r.type === 'Heresy')
.forEach((r) => {
const b = cells.religion[r.center]; // "base" religion id
cells.religion[r.center] = r.i; // heresy id
queue.queue({e: r.center, p: 0, r: r.i, b});
cost[r.center] = 1;
});
const neutral = (cells.i.length / 5000) * 500 * neutralInput.value; // limit cost for heresies growth
while (queue.length) {
const next = queue.dequeue(),
n = next.e,
p = next.p,
r = next.r,
b = next.b;
cells.c[n].forEach(function (e) {
const religionCost = cells.religion[e] === b ? 0 : 2000;
const biomeCost = biomesData.cost[cells.biome[e]];
const heightCost = Math.max(cells.h[e], 20) - 20;
const waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
const totalCost =
p + (religionCost + biomeCost + heightCost + waterCost) / Math.max(religions[r].expansionism, 0.1);
if (totalCost > neutral) return;
if (!cost[e] || totalCost < cost[e]) {
if (cells.h[e] >= 20 && cells.culture[e]) cells.religion[e] = r; // assign religion to cell
cost[e] = totalCost;
queue.queue({e, p: totalCost, r});
}
});
}
};
function checkCenters() {
const {cells, religions} = pack;
const codes = religions.map(r => r.code);
religions.forEach(r => {
if (!r.i) return;
r.code = abbreviate(r.name, codes);
// move religion center if it's not within religion area after expansion
if (cells.religion[r.center] === r.i) return; // in area
const religCells = cells.i.filter(i => cells.religion[i] === r.i);
if (!religCells.length) return; // extinct religion
r.center = religCells.sort((a, b) => cells.pop[b] - cells.pop[a])[0];
});
}
function updateCultures() {
TIME && console.time('updateCulturesForReligions');
pack.religions = pack.religions.map((religion, index) => {
if (index === 0) {
return religion;
}
return {...religion, culture: pack.cells.culture[religion.center]};
});
TIME && console.timeEnd('updateCulturesForReligions');
}
// get supreme deity name
const getDeityName = function (culture) {
if (culture === undefined) {
ERROR && console.error('Please define a culture');
return;
}
const meaning = generateMeaning();
const cultureName = Names.getCulture(culture, null, null, '', 0.8);
return cultureName + ', The ' + meaning;
};
function generateMeaning() {
const a = ra(approaches); // select generation approach
if (a === "Number") return ra(base.number);
if (a === "Being") return ra(base.being);
if (a === "Adjective") return ra(base.adjective);
if (a === "Color + Animal") return ra(base.color) + " " + ra(base.animal);
if (a === "Adjective + Animal") return ra(base.adjective) + " " + ra(base.animal);
if (a === "Adjective + Being") return ra(base.adjective) + " " + ra(base.being);
if (a === "Adjective + Genitive") return ra(base.adjective) + " " + ra(base.genitive);
if (a === "Color + Being") return ra(base.color) + " " + ra(base.being);
if (a === "Color + Genitive") return ra(base.color) + " " + ra(base.genitive);
if (a === "Being + of + Genitive") return ra(base.being) + " of " + ra(base.genitive);
if (a === "Being + of the + Genitive") return ra(base.being) + " of the " + ra(base.theGenitive);
if (a === "Animal + of + Genitive") return ra(base.animal) + " of " + ra(base.genitive);
if (a === "Adjective + Being + of + Genitive")
return ra(base.adjective) + " " + ra(base.being) + " of " + ra(base.genitive);
if (a === "Adjective + Animal + of + Genitive")
return ra(base.adjective) + " " + ra(base.animal) + " of " + ra(base.genitive);
}
function getReligionName(form, deity, center) {
const {cells, cultures, burgs, states} = pack;
const random = () => Names.getCulture(cells.culture[center], null, null, "", 0);
const type = () => rw(types[form]);
const supreme = () => deity.split(/[ ,]+/)[0];
const culture = () => cultures[cells.culture[center]].name;
const place = adj => {
const burgId = cells.burg[center];
const stateId = cells.state[center];
const base = burgId ? burgs[burgId].name : states[stateId].name;
let name = trimVowels(base.split(/[ ,]+/)[0]);
return adj ? getAdjective(name) : name;
};
const m = rw(methods);
if (m === "Random + type") return [random() + " " + type(), "global"];
if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"];
if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"];
if (m === "Faith of + Supreme" && deity)
return [ra(["Faith", "Way", "Path", "Word", "Witnesses"]) + " of " + supreme(), "global"];
if (m === "Place + ism") return [place() + "ism", "state"];
if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"];
if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"];
if (m === "Culture + type") return [culture() + " " + type(), "culture"];
return [trimVowels(random()) + "ism", "global"]; // else
}
function getCultName(form, center) {
const cells = pack.cells;
const type = function () {
return rw(types[form]);
};
const random = function () {
return trimVowels(Names.getCulture(cells.culture[center], null, null, '', 0).split(/[ ,]+/)[0]);
};
const burg = function () {
return trimVowels(pack.burgs[cells.burg[center]].name.split(/[ ,]+/)[0]);
};
if (cells.burg[center]) return burg() + 'ian ' + type();
if (Math.random() > 0.5) return random() + 'ian ' + type();
return type() + ' of the ' + generateMeaning();
}
return {generate, add, getDeityName, expandReligions, updateCultures};
})();