From 70e8296c48170fa125854b7bc29781334bcde190 Mon Sep 17 00:00:00 2001 From: max Date: Wed, 24 Aug 2022 00:09:40 +0300 Subject: [PATCH] refactor: religions start --- src/config/religionsData.ts | 339 ++++++++++++++++++ .../generation/pack/generateReligions.ts | 70 ++++ src/scripts/generation/pack/generateRoutes.ts | 2 +- src/scripts/generation/pack/pack.ts | 17 +- src/types/pack/pack.d.ts | 13 +- src/types/pack/religions.d.ts | 19 + src/utils/probabilityUtils.ts | 7 +- 7 files changed, 449 insertions(+), 18 deletions(-) create mode 100644 src/config/religionsData.ts create mode 100644 src/scripts/generation/pack/generateReligions.ts create mode 100644 src/types/pack/religions.d.ts diff --git a/src/config/religionsData.ts b/src/config/religionsData.ts new file mode 100644 index 00000000..8efaed90 --- /dev/null +++ b/src/config/religionsData.ts @@ -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(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}; diff --git a/src/scripts/generation/pack/generateReligions.ts b/src/scripts/generation/pack/generateReligions.ts new file mode 100644 index 00000000..7fd1414c --- /dev/null +++ b/src/scripts/generation/pack/generateReligions.ts @@ -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; + +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"; +} diff --git a/src/scripts/generation/pack/generateRoutes.ts b/src/scripts/generation/pack/generateRoutes.ts index 94ca3adc..d80b6ad1 100644 --- a/src/scripts/generation/pack/generateRoutes.ts +++ b/src/scripts/generation/pack/generateRoutes.ts @@ -5,7 +5,7 @@ import {TIME} from "config/logging"; import {ELEVATION, MIN_LAND_HEIGHT, ROUTES} from "config/generation"; import {dist2} from "utils/functionUtils"; -type TCellsData = Pick; +type TCellsData = Pick; export function generateRoutes(burgs: TBurgs, temp: Int8Array, cells: TCellsData) { const cellRoutes = new Uint8Array(cells.h.length); diff --git a/src/scripts/generation/pack/pack.ts b/src/scripts/generation/pack/pack.ts index 0b42466d..b6fd80d7 100644 --- a/src/scripts/generation/pack/pack.ts +++ b/src/scripts/generation/pack/pack.ts @@ -13,6 +13,7 @@ import {generateCultures, expandCultures} from "./cultures"; import {generateRivers} from "./rivers"; import {generateBurgsAndStates} from "./burgsAndStates/generateBurgsAndStates"; import {generateRoutes} from "./generateRoutes"; +import {generateReligions} from "./generateReligions"; const {LAND_COAST, WATER_COAST, DEEPER_WATER} = DISTANCE_FIELD; const {Biomes} = window; @@ -124,7 +125,16 @@ export function createPack(grid: IGrid): IPack { h: heights, t: distanceField, 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 }); @@ -167,8 +177,9 @@ export function createPack(grid: IGrid): IPack { culture: cultureIds, burg: burgIds, state: stateIds, - route: cellRoutes - // religion, province + route: cellRoutes, + religion: religionIds + // province }, features: mergedFeatures, rivers: rawRivers, // "name" | "basin" | "type" diff --git a/src/types/pack/pack.d.ts b/src/types/pack/pack.d.ts index d1a3302a..6c205904 100644 --- a/src/types/pack/pack.d.ts +++ b/src/types/pack/pack.d.ts @@ -6,7 +6,7 @@ interface IPack extends IGraph { provinces: IProvince[]; burgs: TBurgs; rivers: IRiver[]; - religions: IReligion[]; + religions: TReligions; routes: TRoutes; } @@ -23,9 +23,9 @@ interface IPackCells { conf: Uint16Array; // conluence, defined by defineRivers() in river-generator.ts biome: Uint8Array; area: UintArray; - state: UintArray; + state: Uint16Array; culture: Uint16Array; - religion: UintArray; + religion: Uint16Array; province: UintArray; burg: UintArray; haven: UintArray; @@ -46,13 +46,6 @@ interface IProvince { removed?: boolean; } -interface IReligion { - i: number; - name: string; - type: "Folk" | "Orgamized" | "Cult" | "Heresy"; - removed?: boolean; -} - interface IRiver { i: number; name: string; diff --git a/src/types/pack/religions.d.ts b/src/types/pack/religions.d.ts new file mode 100644 index 00000000..215395a1 --- /dev/null +++ b/src/types/pack/religions.d.ts @@ -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[]]; diff --git a/src/utils/probabilityUtils.ts b/src/utils/probabilityUtils.ts index 08695bdc..95cffd7d 100644 --- a/src/utils/probabilityUtils.ts +++ b/src/utils/probabilityUtils.ts @@ -42,10 +42,9 @@ export function ra(array: T[]) { } // return random value from weighted array -export function rw(object: {[key: string]: number}) { - const weightedArray = Object.entries(object) - .map(([choise, weight]) => new Array(weight).fill(choise)) - .flat(); +export function rw(object: {[key in T]: number}) { + const entries = Object.entries(object); + const weightedArray: T[] = entries.map(([choise, weight]) => new Array(weight).fill(choise)).flat(); return ra(weightedArray); }