From fe2f8428adfe6ed4f51fc5f5c547b57596f5b67a Mon Sep 17 00:00:00 2001 From: Azgaar Date: Tue, 6 Sep 2022 23:16:21 +0300 Subject: [PATCH] refactor: generateCoreProvinces --- package.json | 2 + .../pack/burgsAndStates/defineStateForm.ts | 2 +- src/scripts/generation/pack/pack.ts | 2 +- .../generation/pack/provinces/config.ts | 8 +++ .../pack/provinces/expandProvinces.ts | 9 +++ .../pack/provinces/generateCoreProvinces.ts | 67 +++++++++++++++++++ .../pack/provinces/generateProvinces.ts | 30 ++++----- src/types/pack/burgs.d.ts | 1 + src/types/pack/provinces.d.ts | 6 ++ src/types/pack/states.d.ts | 4 +- yarn.lock | 17 +++++ 11 files changed, 129 insertions(+), 19 deletions(-) create mode 100644 src/scripts/generation/pack/provinces/config.ts create mode 100644 src/scripts/generation/pack/provinces/expandProvinces.ts create mode 100644 src/scripts/generation/pack/provinces/generateCoreProvinces.ts diff --git a/package.json b/package.json index 5754d5fc..417e5623 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@rollup/plugin-node-resolve": "^13.3.0", "@rollup/plugin-replace": "^4.0.0", "@types/d3": "^5.9.0", + "@types/d3-array": "^3.0.3", "@types/delaunator": "^5.0.0", "@types/jquery": "^3.5.14", "@types/jqueryui": "^1.12.16", @@ -35,6 +36,7 @@ }, "dependencies": { "d3": "5.8.0", + "d3-array": "^3.2.0", "delaunator": "^5.0.0", "flatqueue": "^2.0.3", "lineclip": "^1.1.5", diff --git a/src/scripts/generation/pack/burgsAndStates/defineStateForm.ts b/src/scripts/generation/pack/burgsAndStates/defineStateForm.ts index 0610edd0..a434434e 100644 --- a/src/scripts/generation/pack/burgsAndStates/defineStateForm.ts +++ b/src/scripts/generation/pack/burgsAndStates/defineStateForm.ts @@ -40,7 +40,7 @@ export function defineStateForm( const generic = {Monarchy: 25, Republic: 2, Union: 1}; const naval = {Monarchy: 6, Republic: 2, Union: 1}; -function defineForm(type: TCultureType, areaTier: AreaTiers) { +function defineForm(type: TCultureType, areaTier: AreaTiers): TStateForm { const isAnarchy = P((1 - areaTier / 5) / 100); // [1% - 0.2%] chance if (isAnarchy) return "Anarchy"; diff --git a/src/scripts/generation/pack/pack.ts b/src/scripts/generation/pack/pack.ts index 4c53e1f8..c79f20e5 100644 --- a/src/scripts/generation/pack/pack.ts +++ b/src/scripts/generation/pack/pack.ts @@ -143,7 +143,7 @@ export function createPack(grid: IGrid): IPack { } }); - const {provinceIds, provinces} = generateProvinces(); + const {provinceIds, provinces} = generateProvinces(states, burgs, cultures, {i: cells.i}); // BurgsAndStates.generateProvinces(); // BurgsAndStates.defineBurgFeatures(); diff --git a/src/scripts/generation/pack/provinces/config.ts b/src/scripts/generation/pack/provinces/config.ts new file mode 100644 index 00000000..a2ea85d9 --- /dev/null +++ b/src/scripts/generation/pack/provinces/config.ts @@ -0,0 +1,8 @@ +export const provinceForms = { + Monarchy: {County: 22, Earldom: 6, Shire: 2, Landgrave: 2, Margrave: 2, Barony: 2, Captaincy: 1, Seneschalty: 1}, + Republic: {Province: 6, Department: 2, Governorate: 2, District: 1, Canton: 1, Prefecture: 1}, + Theocracy: {Parish: 3, Deanery: 1}, + Union: {Province: 1, State: 1, Canton: 1, Republic: 1, County: 1, Council: 1}, + Anarchy: {Council: 1, Commune: 1, Community: 1, Tribe: 1}, + Wild: {Territory: 10, Land: 5, Region: 2, Tribe: 1, Clan: 1, Dependency: 1, Area: 1} +}; diff --git a/src/scripts/generation/pack/provinces/expandProvinces.ts b/src/scripts/generation/pack/provinces/expandProvinces.ts new file mode 100644 index 00000000..7e996d1d --- /dev/null +++ b/src/scripts/generation/pack/provinces/expandProvinces.ts @@ -0,0 +1,9 @@ +import {gauss} from "utils/probabilityUtils"; + +export function expandProvinces(percentage: number, cells: Pick) { + const provinceIds = new Uint16Array(cells.i.length); + + const maxGrowth = percentage === 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; + + return provinceIds; +} diff --git a/src/scripts/generation/pack/provinces/generateCoreProvinces.ts b/src/scripts/generation/pack/provinces/generateCoreProvinces.ts new file mode 100644 index 00000000..ce53c068 --- /dev/null +++ b/src/scripts/generation/pack/provinces/generateCoreProvinces.ts @@ -0,0 +1,67 @@ +import {group} from "d3-array"; + +import {brighter, getMixedColor} from "utils/colorUtils"; +import {gauss, P, rw} from "utils/probabilityUtils"; +import {isBurg, isState} from "utils/typeUtils"; +import {provinceForms} from "./config"; + +const {COA, Names} = window; + +export function generateCoreProvinces(states: TStates, burgs: TBurgs, cultures: TCultures, percentage: number) { + const provinces = [] as IProvince[]; + + const validBurgs = burgs.filter(isBurg); + const burgsToStateMap = group(validBurgs, (burg: IBurg) => burg.state); + + states.filter(isState).forEach(state => { + const stateBurgs = burgsToStateMap.get(state.i); + if (!stateBurgs || stateBurgs.length < 2) return; // at least 2 provinces are required + + stateBurgs + .sort((a, b) => b.population * gauss(1, 0.2, 0.5, 1.5, 3) - a.population) + .sort((a, b) => b.capital - a.capital); + + const provincesNumber = Math.max(Math.ceil((stateBurgs.length * percentage) / 100), 2); + const formsPool: Dict = structuredClone(provinceForms[state.form]); + + for (let i = 0; i < provincesNumber; i++) { + const {i: burg, cell: center, culture: cultureId, coa: burgEmblem, name: burgName, type} = stateBurgs[i]; + const nameByBurg = P(0.5); + const name = nameByBurg ? burgName : generateName(cultureId, cultures); + 3; + const formName = rw(formsPool); + formsPool[formName] += 10; // increase chance to get the same form again + + const fullName = name + " " + formName; + const color = brighter(getMixedColor(state.color, 0.2), 0.3); + const coa = generateEmblem(nameByBurg, burgEmblem, type, cultures, cultureId, state); + + provinces.push({i: provinces.length, name, formName, center, burg, state: state.i, fullName, color, coa}); + } + }); + + return provinces; +} + +function generateName(cultureId: number, cultures: TCultures) { + const base = cultures[cultureId].base; + return Names.getState(Names.getBaseShort(base), base); +} + +function generateEmblem( + nameByBurg: boolean, + burgEmblem: ICoa | "string", + type: TCultureType, + cultures: TCultures, + cultureId: number, + state: IState +) { + const kinship = nameByBurg ? 0.8 : 0.4; + const coa: ICoa = COA.generate(burgEmblem, kinship, null, type); + + const cultureShield = cultures[cultureId].shield; + const stateShield = (state.coa as ICoa)?.shield; + coa.shield = COA.getShield(cultureShield, stateShield); + + return coa; +} diff --git a/src/scripts/generation/pack/provinces/generateProvinces.ts b/src/scripts/generation/pack/provinces/generateProvinces.ts index 5cbc37eb..e93d6cac 100644 --- a/src/scripts/generation/pack/provinces/generateProvinces.ts +++ b/src/scripts/generation/pack/provinces/generateProvinces.ts @@ -1,26 +1,24 @@ import {TIME} from "config/logging"; import {getInputNumber} from "utils/nodeUtils"; -import {gauss} from "utils/probabilityUtils"; +import {expandProvinces} from "./expandProvinces"; +import {generateCoreProvinces} from "./generateCoreProvinces"; -const forms = { - Monarchy: {County: 22, Earldom: 6, Shire: 2, Landgrave: 2, Margrave: 2, Barony: 2, Captaincy: 1, Seneschalty: 1}, - Republic: {Province: 6, Department: 2, Governorate: 2, District: 1, Canton: 1, Prefecture: 1}, - Theocracy: {Parish: 3, Deanery: 1}, - Union: {Province: 1, State: 1, Canton: 1, Republic: 1, County: 1, Council: 1}, - Anarchy: {Council: 1, Commune: 1, Community: 1, Tribe: 1}, - Wild: {Territory: 10, Land: 5, Region: 2, Tribe: 1, Clan: 1, Dependency: 1, Area: 1} -}; - -export function generateProvinces(states: TStates, cells: Pick) { +export function generateProvinces( + states: TStates, + burgs: TBurgs, + cultures: TCultures, + cells: Pick +) { TIME && console.time("generateProvinces"); - const provinceIds = new Uint16Array(cells.i.length); - const provinces = [] as TProvinces; - const percentage = getInputNumber("provincesInput"); - if (states.length < 2 || percentage === 0) return {provinceIds, provinces}; + if (states.length < 2 || percentage === 0) + return {provinceIds: new Uint16Array(cells.i.length), provinces: [] as TProvinces[]}; - const maxGrowth = percentage === 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; + const coreProvinces = generateCoreProvinces(states, burgs, cultures, percentage); + const provinceIds = expandProvinces(percentage, cells); + + const provinces = [...coreProvinces]; TIME && console.timeEnd("generateProvinces"); return {provinceIds, provinces}; diff --git a/src/types/pack/burgs.d.ts b/src/types/pack/burgs.d.ts index 01e39700..8b1a5237 100644 --- a/src/types/pack/burgs.d.ts +++ b/src/types/pack/burgs.d.ts @@ -3,6 +3,7 @@ interface IBurg { name: string; feature: number; state: number; + culture: number; cell: number; x: number; y: number; diff --git a/src/types/pack/provinces.d.ts b/src/types/pack/provinces.d.ts index 502b5b80..a055a542 100644 --- a/src/types/pack/provinces.d.ts +++ b/src/types/pack/provinces.d.ts @@ -1,7 +1,13 @@ interface IProvince { i: number; name: string; + burg: number; + formName: string; fullName: string; + color: Hex | CssUrls; + state: number; + center: number; + coa: ICoa | string; removed?: boolean; } diff --git a/src/types/pack/states.d.ts b/src/types/pack/states.d.ts index 8136e6ce..f001f711 100644 --- a/src/types/pack/states.d.ts +++ b/src/types/pack/states.d.ts @@ -7,7 +7,7 @@ interface IState { type: TCultureType; culture: number; expansionism: number; - form: string; + form: TStateForm; formName: string; fullName: string; coa: ICoa | string; @@ -38,6 +38,8 @@ interface ICoa { t1: string; } +type TStateForm = "Monarchy" | "Republic" | "Theocracy" | "Union" | "Anarchy"; + type TRelation = | "Ally" | "Friendly" diff --git a/yarn.lock b/yarn.lock index e5e80b0e..2de78906 100644 --- a/yarn.lock +++ b/yarn.lock @@ -155,6 +155,11 @@ resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.9.tgz#c7dc78992cd8ca5c850243a265fd257ea56df1fa" integrity sha512-E/7RgPr2ylT5dWG0CswMi9NpFcjIEDqLcUSBgNHe/EMahfqYaTx4zhcggG3khqoEB/leY4Vl6nTSbwLUPjXceA== +"@types/d3-array@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac" + integrity sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ== + "@types/d3-axis@^1": version "1.0.16" resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-1.0.16.tgz#93d7a28795c2f8b0e2fd550fcc4d29b7f174e693" @@ -738,6 +743,13 @@ d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0: resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== +d3-array@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.0.tgz#15bf96cd9b7333e02eb8de8053d78962eafcff14" + integrity sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g== + dependencies: + internmap "1 - 2" + d3-axis@1: version "1.0.12" resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9" @@ -1469,6 +1481,11 @@ inherits@2, inherits@^2.0.3, inherits@~2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + is-builtin-module@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.1.0.tgz#6fdb24313b1c03b75f8b9711c0feb8c30b903b00"