From 9b3a3f2e481c33516085c57d76d0e5de5a2e6ef1 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 5 Sep 2022 21:00:09 +0300 Subject: [PATCH] refactor: generate historical conflicts --- public/libs/define-globals.js | 4 +- src/modules/markers-generator.js | 1 + src/modules/names-generator.js | 7 +-- src/scripts/generation/generation.ts | 3 +- .../generation/pack/burgsAndStates/config.ts | 12 +++++ .../burgsAndStates/generateBurgsAndStates.ts | 9 ++-- .../pack/burgsAndStates/generateConflicts.ts | 47 +++++++++++++++++-- .../pack/burgsAndStates/specifyStates.ts | 8 ++-- src/scripts/generation/pack/pack.ts | 6 +-- src/types/events.d.ts | 8 ++-- src/types/globals.d.ts | 4 +- 11 files changed, 81 insertions(+), 28 deletions(-) diff --git a/public/libs/define-globals.js b/public/libs/define-globals.js index d1cf0020..fb1890a0 100644 --- a/public/libs/define-globals.js +++ b/public/libs/define-globals.js @@ -4,13 +4,15 @@ let grid = {}; // initial graph based on jittered square grid and data let pack = {}; // packed graph and data +let notes = []; +let events = {}; + let seed; let mapId; let mapHistory = []; let elSelected; -let notes = []; let customization = 0; let rulers; diff --git a/src/modules/markers-generator.js b/src/modules/markers-generator.js index bcd12577..fdef557f 100644 --- a/src/modules/markers-generator.js +++ b/src/modules/markers-generator.js @@ -559,6 +559,7 @@ window.Markers = (function () { const {cells, states} = pack; const state = states[cells.state[cell]]; + // TODO: use events if (!state.campaigns) state.campaigns = BurgsAndStates.generateCampaign(state); const campaign = ra(state.campaigns); const date = generateDate(campaign.start, campaign.end); diff --git a/src/modules/names-generator.js b/src/modules/names-generator.js index 21e8e062..a480ac77 100644 --- a/src/modules/names-generator.js +++ b/src/modules/names-generator.js @@ -149,11 +149,8 @@ window.Names = (function () { // generate short name for base const getBaseShort = function (base) { if (nameBases[base] === undefined) { - tip( - `Namebase ${base} does not exist. Please upload custom namebases of change the base in Cultures Editor`, - false, - "error" - ); + const message = `Namebase ${base} does not exist. Please upload custom namebases of change the base in Cultures Editor`; + tip(message, false, "error"); base = 1; } const min = nameBases[base].min - 1; diff --git a/src/scripts/generation/generation.ts b/src/scripts/generation/generation.ts index 5d90ff9a..209afeb2 100644 --- a/src/scripts/generation/generation.ts +++ b/src/scripts/generation/generation.ts @@ -53,13 +53,14 @@ async function generate(options?: IGenerationOptions) { window.mapCoordinates = calculateMapCoordinates(); const newGrid = await createGrid(grid, precreatedGraph); - const newPack = createPack(newGrid); + const {pack: newPack, conflicts} = createPack(newGrid); // TODO: draw default ruler // redefine global grid and pack grid = newGrid; pack = newPack; + events = {conflicts}; // temp rendering for debug // renderLayer("cells"); diff --git a/src/scripts/generation/pack/burgsAndStates/config.ts b/src/scripts/generation/pack/burgsAndStates/config.ts index daf09ca0..8d038625 100644 --- a/src/scripts/generation/pack/burgsAndStates/config.ts +++ b/src/scripts/generation/pack/burgsAndStates/config.ts @@ -113,3 +113,15 @@ export const relations = { farStates: {Friendly: 1, Neutral: 12, Suspicion: 2}, navalToNaval: {Neutral: 2, Suspicion: 2, Rival: 1} }; + +export const conflictTypes = { + War: 6, + Conflict: 2, + Campaign: 4, + Invasion: 2, + Rebellion: 2, + Conquest: 2, + Intervention: 1, + Expedition: 1, + Crusade: 1 +}; diff --git a/src/scripts/generation/pack/burgsAndStates/generateBurgsAndStates.ts b/src/scripts/generation/pack/burgsAndStates/generateBurgsAndStates.ts index 341e70c7..d2d2dc8f 100644 --- a/src/scripts/generation/pack/burgsAndStates/generateBurgsAndStates.ts +++ b/src/scripts/generation/pack/burgsAndStates/generateBurgsAndStates.ts @@ -21,7 +21,7 @@ export function generateBurgsAndStates( rivers: Omit[], vertices: IGraphVertices, cells: TCellsData -): {burgIds: Uint16Array; stateIds: Uint16Array; burgs: TBurgs; states: TStates} { +): {burgIds: Uint16Array; stateIds: Uint16Array; burgs: TBurgs; states: TStates; conflicts: IConflict[]} { const cellsNumber = cells.i.length; const scoredCellIds = getScoredCellIds(); @@ -31,7 +31,8 @@ export function generateBurgsAndStates( burgIds: new Uint16Array(cellsNumber), stateIds: new Uint16Array(cellsNumber), burgs: [NO_BURG], - states: [NEUTRALS] + states: [NEUTRALS], + conflicts: [] }; } @@ -69,9 +70,9 @@ export function generateBurgsAndStates( const statistics = collectStatistics({...cells, state: stateIds, burg: burgIds}, burgs); const diplomacy = generateRelations(statesData, statistics, pick(cells, "f")); - const states = specifyStates(statesData, statistics, diplomacy, cultures, burgs); + const {states, conflicts} = specifyStates(statesData, statistics, diplomacy, cultures, burgs); - return {burgIds, stateIds, burgs, states}; + return {burgIds, stateIds, burgs, states, conflicts}; function getScoredCellIds() { const score = new Int16Array(cells.s.map(s => s * Math.random())); diff --git a/src/scripts/generation/pack/burgsAndStates/generateConflicts.ts b/src/scripts/generation/pack/burgsAndStates/generateConflicts.ts index 46bfeba0..30f7f8c8 100644 --- a/src/scripts/generation/pack/burgsAndStates/generateConflicts.ts +++ b/src/scripts/generation/pack/burgsAndStates/generateConflicts.ts @@ -1,12 +1,22 @@ import * as d3 from "d3"; import {TIME} from "config/logging"; -import {list, trimVowels} from "utils/languageUtils"; -import {gauss, ra} from "utils/probabilityUtils"; +import {getAdjective, list, trimVowels} from "utils/languageUtils"; +import {gauss, P, ra, rw} from "utils/probabilityUtils"; +import {conflictTypes} from "./config"; -export function generateConflicts(states: IState[]) { +const {Names} = window; + +export function generateConflicts(states: IState[], cultures: TCultures): IConflict[] { TIME && console.time("generateConflicts"); + const historicalWars = generateHistoricalConflicts(states, cultures); + const ongoingWars = generateOngoingConflicts(states); + TIME && console.timeEnd("generateConflicts"); + return [...historicalWars, ...ongoingWars].sort((a, b) => a.start - b.start); +} + +function generateOngoingConflicts(states: IState[]): IConflict[] { const statesMap = new Map(states.map(state => [state.i, state])); const wars: IConflict[] = []; @@ -37,7 +47,6 @@ export function generateConflicts(states: IState[]) { wars.push(war); } - TIME && console.timeEnd("generateConflicts"); return wars; function simulateWar(attacker: IState, defender: IState): IConflict { @@ -134,7 +143,7 @@ export function generateConflicts(states: IState[]) { const name = `${attacker.name}-${trimVowels(defender.name)}ian War`; const parties = {attackers: attackers.map(({i}) => i), defenders: defenders.map(({i}) => i)}; const start = options.year - gauss(2, 2, 0, 5); - return {type: "conflict", name, start, parties, description: history.join(". ")}; + return {name, start, parties, description: history.join(". ")}; } function getStatePower(state: IState) { @@ -156,3 +165,31 @@ export function generateConflicts(states: IState[]) { return "minor"; } } + +function generateHistoricalConflicts(states: IState[], cultures: TCultures): IConflict[] { + const statesMap = new Map(states.map(state => [state.i, state])); + const isConflict = (conflict: IConflict | null): conflict is IConflict => conflict !== null; + const getNameBase = (cultureId: number) => cultures[cultureId].base; + return states.map(generateConflicts).flat(); + + function generateConflicts(state: IState): IConflict[] { + const conflicts = state.neighbors + .map((neighbor, index) => { + if (index && P(0.8)) return null; + const enemy = statesMap.get(neighbor); + if (!enemy) return null; + + const properName = P(0.8) ? enemy.name : Names.getBaseShort(getNameBase(enemy.culture)); + const name = getAdjective(properName) + " " + rw(conflictTypes); + const start = gauss(options.year - 100, 150, 1, options.year - 6); + const end = start + gauss(4, 5, 1, options.year - start - 1); + const parties = {attackers: [state.i], defenders: [enemy.i]}; + + const conflict: IConflict = {name, start, end, parties}; + return conflict; + }) + .filter(isConflict); + + return conflicts; + } +} diff --git a/src/scripts/generation/pack/burgsAndStates/specifyStates.ts b/src/scripts/generation/pack/burgsAndStates/specifyStates.ts index cebb55db..ba9be9ee 100644 --- a/src/scripts/generation/pack/burgsAndStates/specifyStates.ts +++ b/src/scripts/generation/pack/burgsAndStates/specifyStates.ts @@ -16,7 +16,7 @@ export function specifyStates( diplomacy: TDiplomacy, cultures: TCultures, burgs: TBurgs -): TStates { +): {states: TStates; conflicts: IConflict[]} { TIME && console.time("specifyStates"); const colors = defineStateColors(statistics); @@ -56,10 +56,8 @@ export function specifyStates( }; }); - const wars = generateConflicts(states); // mutates states - console.log(wars); - console.log(states); + const conflicts = generateConflicts(states, cultures); // mutates states TIME && console.timeEnd("specifyStates"); - return [NEUTRALS, ...states]; + return {states: [NEUTRALS, ...states], conflicts}; } diff --git a/src/scripts/generation/pack/pack.ts b/src/scripts/generation/pack/pack.ts index 85af9c85..f5be5c3c 100644 --- a/src/scripts/generation/pack/pack.ts +++ b/src/scripts/generation/pack/pack.ts @@ -18,7 +18,7 @@ import {generateReligions} from "./religions/generateReligions"; const {LAND_COAST, WATER_COAST, DEEPER_WATER} = DISTANCE_FIELD; const {Biomes} = window; -export function createPack(grid: IGrid): IPack { +export function createPack(grid: IGrid): {pack: IPack; conflicts: IConflict[]} { const {temp, prec} = grid.cells; const {vertices, cells} = repackGrid(grid); @@ -97,7 +97,7 @@ export function createPack(grid: IGrid): IPack { pop: population }); - const {burgIds, stateIds, burgs, states} = generateBurgsAndStates( + const {burgIds, stateIds, burgs, states, conflicts} = generateBurgsAndStates( cultures, mergedFeatures, temp, @@ -199,7 +199,7 @@ export function createPack(grid: IGrid): IPack { religions }; - return pack; + return {pack, conflicts}; } // repack grid cells: discart deep water cells, add land cells along the coast diff --git a/src/types/events.d.ts b/src/types/events.d.ts index 25ef3a08..814ba4af 100644 --- a/src/types/events.d.ts +++ b/src/types/events.d.ts @@ -1,13 +1,15 @@ +interface IEvents { + conflicts: IConflict[]; +} + interface IEvent { - type: string; name: string; start: number; end?: number; // undefined for ongoing events - description: string; + description?: string; } interface IConflict extends IEvent { - type: "conflict"; parties: { attackers: number[]; defenders: number[]; diff --git a/src/types/globals.d.ts b/src/types/globals.d.ts index c1c18074..15f81616 100644 --- a/src/types/globals.d.ts +++ b/src/types/globals.d.ts @@ -1,11 +1,13 @@ declare let grid: IGrid; declare let pack: IPack; +declare let notes: INote[]; +declare let events: IEvents; + declare let seed: string; declare let mapId: number; declare let mapHistory: IMapHistoryEntry[]; -declare let notes: INote[]; declare let customization: number; declare let rulers: Rulers;