refactor: religions start

This commit is contained in:
max 2022-08-24 00:09:40 +03:00
parent 03809e56ab
commit 70e8296c48
7 changed files with 449 additions and 18 deletions

339
src/config/religionsData.ts Normal file
View file

@ -0,0 +1,339 @@
// 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 data into a flat array
const approaches: string[] = Object.entries<number>(approach)
.map(([approach, weight]) => new Array(weight).fill(approach))
.flat();
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",
"Bear",
"Beaver",
"Bison",
"Boar",
"Buffalo",
"Camel",
"Cat",
"Centaur",
"Chimera",
"Cobra",
"Crane",
"Crocodile",
"Crow",
"Cyclope",
"Deer",
"Dog",
"Dragon",
"Eagle",
"Elk",
"Falcon",
"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",
"Rat",
"Raven",
"Rook",
"Scorpion",
"Serpent",
"Shark",
"Sheep",
"Snake",
"Sphinx",
"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"
]
};
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
};
export 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
}
};
export const religionsData = {approaches, base, forms, methods, types};

View file

@ -0,0 +1,70 @@
import {TIME} from "config/logging";
import {religionsData} from "config/religionsData";
import {getMixedColor} from "utils/colorUtils";
import {ra, rw} from "utils/probabilityUtils";
type TCellsData = Pick<IPack["cells"], "c" | "p" | "g" | "h" | "t" | "biome" | "burg">;
const {Names} = window;
const {approaches, base, forms, methods, types} = religionsData;
export function generateReligions(states: TStates, cultures: TCultures, cells: TCellsData) {
TIME && console.time("generateReligions");
const religionIds = new Uint16Array(cells.c.length);
const folkReligions = generateFolkReligions(cultures, cells);
console.log(folkReligions);
TIME && console.timeEnd("generateReligions");
return {religionIds};
}
function generateFolkReligions(cultures: TCultures, cells: TCellsData) {
const isValidCulture = (culture: TWilderness | ICulture): culture is ICulture =>
culture.i !== 0 && !(culture as ICulture).removed;
return cultures.filter(isValidCulture).map((culture, index) => {
const {i: cultureId, name: cultureName, center} = culture;
const id = index + 1;
const form = rw(forms.Folk);
const type: {[key: string]: number} = types[form];
const name = cultureName + " " + rw(type);
const deity = form === "Animism" ? null : getDeityName(cultures, cultureId);
const color = getMixedColor(culture.color, 0.1, 0);
return {i: id, name, color, culture: cultureId, type: "Folk", form, deity, center: center, origins: [0]};
});
}
function getDeityName(cultures: TCultures, cultureId: number) {
if (cultureId === undefined) throw "CultureId is undefined";
const meaning = generateMeaning();
const base = cultures[cultureId].base;
const cultureName = Names.getBase(base);
return cultureName + ", The " + meaning;
}
function generateMeaning() {
const approach = ra(approaches);
if (approach === "Number") return ra(base.number);
if (approach === "Being") return ra(base.being);
if (approach === "Adjective") return ra(base.adjective);
if (approach === "Color + Animal") return `${ra(base.color)} ${ra(base.animal)}`;
if (approach === "Adjective + Animal") return `${ra(base.adjective)} ${ra(base.animal)}`;
if (approach === "Adjective + Being") return `${ra(base.adjective)} ${ra(base.being)}`;
if (approach === "Adjective + Genitive") return `${ra(base.adjective)} ${ra(base.genitive)}`;
if (approach === "Color + Being") return `${ra(base.color)} ${ra(base.being)}`;
if (approach === "Color + Genitive") return `${ra(base.color)} ${ra(base.genitive)}`;
if (approach === "Being + of + Genitive") return `${ra(base.being)} of ${ra(base.genitive)}`;
if (approach === "Being + of the + Genitive") return `${ra(base.being)} of the ${ra(base.theGenitive)}`;
if (approach === "Animal + of + Genitive") return `${ra(base.animal)} of ${ra(base.genitive)}`;
if (approach === "Adjective + Being + of + Genitive")
return `${ra(base.adjective)} ${ra(base.being)} of ${ra(base.genitive)}`;
if (approach === "Adjective + Animal + of + Genitive")
return `${ra(base.adjective)} ${ra(base.animal)} of ${ra(base.genitive)}`;
throw "Unknown generation approach";
}

View file

@ -5,7 +5,7 @@ import {TIME} from "config/logging";
import {ELEVATION, MIN_LAND_HEIGHT, ROUTES} from "config/generation"; import {ELEVATION, MIN_LAND_HEIGHT, ROUTES} from "config/generation";
import {dist2} from "utils/functionUtils"; import {dist2} from "utils/functionUtils";
type TCellsData = Pick<IPack["cells"], "c" | "p" | "g" | "h" | "t" | "haven" | "biome" | "state" | "burg">; type TCellsData = Pick<IPack["cells"], "c" | "p" | "g" | "h" | "t" | "biome" | "burg">;
export function generateRoutes(burgs: TBurgs, temp: Int8Array, cells: TCellsData) { export function generateRoutes(burgs: TBurgs, temp: Int8Array, cells: TCellsData) {
const cellRoutes = new Uint8Array(cells.h.length); const cellRoutes = new Uint8Array(cells.h.length);

View file

@ -13,6 +13,7 @@ import {generateCultures, expandCultures} from "./cultures";
import {generateRivers} from "./rivers"; import {generateRivers} from "./rivers";
import {generateBurgsAndStates} from "./burgsAndStates/generateBurgsAndStates"; import {generateBurgsAndStates} from "./burgsAndStates/generateBurgsAndStates";
import {generateRoutes} from "./generateRoutes"; import {generateRoutes} from "./generateRoutes";
import {generateReligions} from "./generateReligions";
const {LAND_COAST, WATER_COAST, DEEPER_WATER} = DISTANCE_FIELD; const {LAND_COAST, WATER_COAST, DEEPER_WATER} = DISTANCE_FIELD;
const {Biomes} = window; const {Biomes} = window;
@ -124,7 +125,16 @@ export function createPack(grid: IGrid): IPack {
h: heights, h: heights,
t: distanceField, t: distanceField,
biome, biome,
state: stateIds, burg: burgIds
});
const {religionIds} = generateReligions(states, cultures, {
c: cells.c,
p: cells.p,
g: cells.g,
h: heights,
t: distanceField,
biome,
burg: burgIds burg: burgIds
}); });
@ -167,8 +177,9 @@ export function createPack(grid: IGrid): IPack {
culture: cultureIds, culture: cultureIds,
burg: burgIds, burg: burgIds,
state: stateIds, state: stateIds,
route: cellRoutes route: cellRoutes,
// religion, province religion: religionIds
// province
}, },
features: mergedFeatures, features: mergedFeatures,
rivers: rawRivers, // "name" | "basin" | "type" rivers: rawRivers, // "name" | "basin" | "type"

View file

@ -6,7 +6,7 @@ interface IPack extends IGraph {
provinces: IProvince[]; provinces: IProvince[];
burgs: TBurgs; burgs: TBurgs;
rivers: IRiver[]; rivers: IRiver[];
religions: IReligion[]; religions: TReligions;
routes: TRoutes; routes: TRoutes;
} }
@ -23,9 +23,9 @@ interface IPackCells {
conf: Uint16Array; // conluence, defined by defineRivers() in river-generator.ts conf: Uint16Array; // conluence, defined by defineRivers() in river-generator.ts
biome: Uint8Array; biome: Uint8Array;
area: UintArray; area: UintArray;
state: UintArray; state: Uint16Array;
culture: Uint16Array; culture: Uint16Array;
religion: UintArray; religion: Uint16Array;
province: UintArray; province: UintArray;
burg: UintArray; burg: UintArray;
haven: UintArray; haven: UintArray;
@ -46,13 +46,6 @@ interface IProvince {
removed?: boolean; removed?: boolean;
} }
interface IReligion {
i: number;
name: string;
type: "Folk" | "Orgamized" | "Cult" | "Heresy";
removed?: boolean;
}
interface IRiver { interface IRiver {
i: number; i: number;
name: string; name: string;

19
src/types/pack/religions.d.ts vendored Normal file
View file

@ -0,0 +1,19 @@
interface IReligion {
i: number;
name: string;
type: "Folk" | "Orgamized" | "Cult" | "Heresy";
color: string;
culture: number;
form: any;
deity: string | null;
center: number;
origins: number[];
removed?: boolean;
}
type TNoReligion = {
i: 0;
name: string;
};
type TReligions = [TNoReligion, ...IReligion[]];

View file

@ -42,10 +42,9 @@ export function ra<T>(array: T[]) {
} }
// return random value from weighted array // return random value from weighted array
export function rw(object: {[key: string]: number}) { export function rw<T extends string>(object: {[key in T]: number}) {
const weightedArray = Object.entries(object) const entries = Object.entries<number>(object);
.map(([choise, weight]) => new Array(weight).fill(choise)) const weightedArray: T[] = entries.map(([choise, weight]) => new Array(weight).fill(choise)).flat();
.flat();
return ra(weightedArray); return ra(weightedArray);
} }