mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
refactor: specify burgs
This commit is contained in:
parent
aa6cefb683
commit
7f57c9af65
14 changed files with 151 additions and 45 deletions
|
|
@ -250,7 +250,11 @@ export function open({type, id, el}) {
|
|||
parent = province ? pack.provinces[province] : pack.states[el.state];
|
||||
}
|
||||
|
||||
const shield = el.coa.shield || COA.getShield(el.culture || parent?.culture || 0, el.state);
|
||||
const cultureId = el.culture || parent?.culture || 0;
|
||||
const cultureShield = cultures[cultureId].shield;
|
||||
const stateShield = states[el.state]?.coa?.shield;
|
||||
|
||||
const shield = el.coa.shield || COA.getPackShield(cultureShield, stateShield);
|
||||
el.coa = COA.generate(parent ? parent.coa : null, 0.3, 0.1, null);
|
||||
el.coa.shield = shield;
|
||||
emblemShapeSelector.disabled = false;
|
||||
|
|
|
|||
|
|
@ -1168,7 +1168,7 @@ function adjustProvinces(affectedProvinces) {
|
|||
const kinship = nameByBurg ? 0.8 : 0.4;
|
||||
const type = BurgsAndStates.getType(center, burg?.port);
|
||||
const coa = COA.generate(burg?.coa || states[stateId].coa, kinship, burg ? null : 0.9, type);
|
||||
coa.shield = COA.getShield(culture, stateId);
|
||||
coa.shield = COA.getPackShield(culture, stateId);
|
||||
|
||||
provinces.push({
|
||||
i: newProvinceId,
|
||||
|
|
@ -1270,7 +1270,7 @@ function addState() {
|
|||
// generate emblem
|
||||
const cultureType = pack.cultures[culture].type;
|
||||
const coa = COA.generate(burgs[burg].coa, 0.4, null, cultureType);
|
||||
coa.shield = COA.getShield(culture, null);
|
||||
coa.shield = COA.getPackShield(culture, null);
|
||||
|
||||
// update diplomacy and reverse relations
|
||||
const diplomacy = states.map(s => {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ window.BurgsAndStates = (function () {
|
|||
const type = cultures[b.culture].type;
|
||||
|
||||
const coa = COA.generate(null, null, null, type);
|
||||
coa.shield = COA.getShield(b.culture, null);
|
||||
coa.shield = COA.getPackShield(b.culture, null);
|
||||
states.push({
|
||||
i,
|
||||
color: colors[i - 1],
|
||||
|
|
@ -230,7 +230,7 @@ window.BurgsAndStates = (function () {
|
|||
b.type = getType(i, b.port);
|
||||
const type = b.capital && P(0.2) ? "Capital" : b.type === "Generic" ? "City" : b.type;
|
||||
b.coa = COA.generate(stateCOA, kinship, null, type);
|
||||
b.coa.shield = COA.getShield(b.culture, b.state);
|
||||
b.coa.shield = COA.getPackShield(b.culture, b.state);
|
||||
}
|
||||
|
||||
// de-assign port status if it's the only one on feature
|
||||
|
|
@ -1213,7 +1213,7 @@ window.BurgsAndStates = (function () {
|
|||
const kinship = nameByBurg ? 0.8 : 0.4;
|
||||
const type = getType(center, burg.port);
|
||||
const coa = COA.generate(stateBurgs[i].coa, kinship, null, type);
|
||||
coa.shield = COA.getShield(cultureId, s.i);
|
||||
coa.shield = COA.getPackShield(cultureId, s.i);
|
||||
provinces.push({i: province, state: s.i, center, burg, name, formName, fullName, color, coa});
|
||||
}
|
||||
});
|
||||
|
|
@ -1346,7 +1346,7 @@ window.BurgsAndStates = (function () {
|
|||
const kinship = dominion ? 0 : 0.4;
|
||||
const type = getType(center, burgs[burg]?.port);
|
||||
const coa = COA.generate(s.coa, kinship, dominion, type);
|
||||
coa.shield = COA.getShield(cultureId, s.i);
|
||||
coa.shield = COA.getPackShield(cultureId, s.i);
|
||||
|
||||
provinces.push({i: province, state: s.i, center, burg, name, formName, fullName, color, coa});
|
||||
s.provinces.push(province);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import {pack} from "d3";
|
||||
import {P, rw} from "utils/probabilityUtils";
|
||||
import {ERROR} from "config/logging";
|
||||
|
||||
window.COA = (function () {
|
||||
const tinctures = {
|
||||
|
|
@ -1039,17 +1039,25 @@ window.COA = (function () {
|
|||
return coa;
|
||||
};
|
||||
|
||||
const getShield = function (cultureId, stateId, cultures = pack.cultures, states = pack.states) {
|
||||
const getShield = function (cultureShield, stateShield) {
|
||||
const emblemShape = document.getElementById("emblemShape");
|
||||
const shapeGroup = emblemShape.selectedOptions[0]?.parentNode.label || "Diversiform";
|
||||
|
||||
if (shapeGroup !== "Diversiform") return emblemShape.value;
|
||||
|
||||
if (emblemShape.value === "state" && stateId && states[stateId].coa) return states[stateId].coa.shield;
|
||||
if (cultures[cultureId].shield) return cultures[cultureId].shield;
|
||||
ERROR && console.error("Shield shape is not defined on culture level", cultures[cultureId]);
|
||||
if (emblemShape.value === "state" && stateShield) return stateShield;
|
||||
|
||||
if (cultureShield) cultureShield;
|
||||
ERROR && console.error("Shield shape is not defined on culture level");
|
||||
return "heater";
|
||||
};
|
||||
|
||||
const getPackShield = function (cultureId, stateId) {
|
||||
const cultureShield = pack.cultres[cultureId]?.shield;
|
||||
const stateShield = pack.states[stateId]?.coa?.shield;
|
||||
return getShield(cultureShield, stateShield);
|
||||
};
|
||||
|
||||
const getRandomShield = function () {
|
||||
const type = rw(shields.types);
|
||||
return rw(shields[type]);
|
||||
|
|
@ -1058,5 +1066,5 @@ window.COA = (function () {
|
|||
const toString = coa => JSON.stringify(coa).replaceAll("#", "%23");
|
||||
const copy = coa => JSON.parse(JSON.stringify(coa));
|
||||
|
||||
return {generate, toString, copy, getShield, shields, getRandomShield};
|
||||
return {generate, toString, copy, getShield, getPackShield, shields, getRandomShield};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ function addBurg(point) {
|
|||
|
||||
// generate emblem
|
||||
const coa = COA.generate(pack.states[state].coa, 0.25, null, type);
|
||||
coa.shield = COA.getShield(culture, state);
|
||||
coa.shield = COA.getPackShield(culture, state);
|
||||
COArenderer.add("burg", i, coa, x, y);
|
||||
|
||||
pack.burgs.push({name, cell, x, y, state, i, culture, feature, capital: 0, port: 0, temple, population, coa, type});
|
||||
|
|
|
|||
|
|
@ -389,7 +389,8 @@ function changeEmblemShape(emblemShape) {
|
|||
|
||||
pack.states.forEach(state => {
|
||||
if (!state.i || state.removed || !state.coa || state.coa === "custom") return;
|
||||
const newShield = specificShape || COA.getShield(state.culture, null);
|
||||
|
||||
const newShield = specificShape || COA.getPackShield(state.culture, null);
|
||||
if (newShield === state.coa.shield) return;
|
||||
state.coa.shield = newShield;
|
||||
rerenderCOA("stateCOA" + state.i, state.coa);
|
||||
|
|
@ -398,7 +399,7 @@ function changeEmblemShape(emblemShape) {
|
|||
pack.provinces.forEach(province => {
|
||||
if (!province.i || province.removed || !province.coa || province.coa === "custom") return;
|
||||
const culture = pack.cells.culture[province.center];
|
||||
const newShield = specificShape || COA.getShield(culture, province.state);
|
||||
const newShield = specificShape || COA.getPackShield(culture, province.state);
|
||||
if (newShield === province.coa.shield) return;
|
||||
province.coa.shield = newShield;
|
||||
rerenderCOA("provinceCOA" + province.i, province.coa);
|
||||
|
|
@ -406,7 +407,7 @@ function changeEmblemShape(emblemShape) {
|
|||
|
||||
pack.burgs.forEach(burg => {
|
||||
if (!burg.i || burg.removed || !burg.coa || burg.coa === "custom") return;
|
||||
const newShield = specificShape || COA.getShield(burg.culture, burg.state);
|
||||
const newShield = specificShape || COA.getPackShield(burg.culture, burg.state);
|
||||
if (newShield === burg.coa.shield) return;
|
||||
burg.coa.shield = newShield;
|
||||
rerenderCOA("burgCOA" + burg.i, burg.coa);
|
||||
|
|
|
|||
|
|
@ -1049,7 +1049,11 @@ export function editProvinces() {
|
|||
const parent = burg ? pack.burgs[burg].coa : pack.states[state].coa;
|
||||
const type = BurgsAndStates.getType(center, parent.port);
|
||||
const coa = COA.generate(parent, kinship, P(0.1), type);
|
||||
coa.shield = COA.getShield(cultureId, state);
|
||||
|
||||
const cultureShield = cultures[cultureId].shield;
|
||||
const stateShield = states[state]?.coa?.shield;
|
||||
coa.shield = COA.getShield(cultureShield, stateShield);
|
||||
|
||||
COArenderer.add("province", province, coa, point[0], point[1]);
|
||||
|
||||
provinces.push({i: province, state, center, burg, name, formName, fullName, color, coa});
|
||||
|
|
|
|||
|
|
@ -375,7 +375,9 @@ function regenerateEmblems() {
|
|||
if (!state.i || state.removed) return;
|
||||
const cultureType = pack.cultures[state.culture].type;
|
||||
state.coa = COA.generate(null, null, null, cultureType);
|
||||
state.coa.shield = COA.getShield(state.culture, null);
|
||||
|
||||
const cultureShield = cultures[state.culture].shield;
|
||||
state.coa.shield = COA.getShield(cultureShield, null);
|
||||
});
|
||||
|
||||
pack.burgs.forEach(burg => {
|
||||
|
|
@ -387,7 +389,10 @@ function regenerateEmblems() {
|
|||
else if (burg.port) kinship -= 0.1;
|
||||
if (state && burg.culture !== state.culture) kinship -= 0.25;
|
||||
burg.coa = COA.generate(state ? state.coa : null, kinship, null, burg.type);
|
||||
burg.coa.shield = COA.getShield(burg.culture, state ? burg.state : 0);
|
||||
|
||||
const cultureShield = cultures[burg.culture].shield;
|
||||
const stateShield = states[burg.state]?.coa?.shield;
|
||||
burg.coa.shield = COA.getShield(cultureShield, stateShield);
|
||||
});
|
||||
|
||||
pack.provinces.forEach(province => {
|
||||
|
|
@ -409,7 +414,10 @@ function regenerateEmblems() {
|
|||
const culture = pack.cells.culture[province.center];
|
||||
const type = BurgsAndStates.getType(province.center, parent.port);
|
||||
province.coa = COA.generate(parent.coa, kinship, dominion, type);
|
||||
province.coa.shield = COA.getShield(culture, province.state);
|
||||
|
||||
const cultureShield = cultures[culture].shield;
|
||||
const stateShield = states[province.state]?.coa?.shield;
|
||||
province.coa.shield = COA.getShield(cultureShield, stateShield);
|
||||
});
|
||||
|
||||
if (layerIsOn("toggleEmblems")) drawEmblems(); // redrawEmblems
|
||||
|
|
|
|||
|
|
@ -21,11 +21,12 @@ export function createStates(capitals: TCapitals, cultures: TCultures) {
|
|||
const id = index + 1;
|
||||
const name = getStateName(cellId, capitalName, cultureId, cultures);
|
||||
const color = colors[index];
|
||||
const type = (cultures[cultureId] as ICulture).type;
|
||||
|
||||
const {type, shield: cultureShield} = cultures[cultureId] as ICulture;
|
||||
const expansionism = rn(Math.random() * powerInput + 1, 1);
|
||||
|
||||
const shield = COA.getShield(cultureId, null, cultures);
|
||||
const coa = {...COA.generate(null, null, null, type), shield};
|
||||
const shield = COA.getShield(cultureShield, null);
|
||||
const coa: ICoa = {...COA.generate(null, null, null, type), shield};
|
||||
|
||||
return {i: id, center: cellId, type, name, color, expansionism, capital: capitalId, culture: cultureId, coa};
|
||||
});
|
||||
|
|
@ -34,7 +35,7 @@ export function createStates(capitals: TCapitals, cultures: TCultures) {
|
|||
return [NEUTRALS, ...states];
|
||||
}
|
||||
|
||||
function getStateName(cellId: number, capitalName: string, cultureId: number, cultures: TCultures) {
|
||||
function getStateName(cellId: number, capitalName: string, cultureId: number, cultures: TCultures): string {
|
||||
const useCapitalName = capitalName.length < 9 && each(5)(cellId);
|
||||
const nameBase = cultures[cultureId].base;
|
||||
const basename: string = useCapitalName ? capitalName : Names.getBaseShort(nameBase);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ export function expandStates(
|
|||
}
|
||||
|
||||
TIME && console.timeEnd("expandStates");
|
||||
return stateIds;
|
||||
|
||||
return normalizeStates(stateIds, capitals, cells.c, cells.h);
|
||||
|
||||
function isNeutrals(state: Entry<TStates>): state is TNeutrals {
|
||||
return state.i === 0;
|
||||
|
|
@ -193,3 +194,34 @@ export function expandStates(
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeStates(stateIds: Uint16Array, capitals: TCapitals, neibCells: number[][], heights: Uint8Array) {
|
||||
TIME && console.time("normalizeStates");
|
||||
|
||||
const normalizedStateIds = Uint16Array.from(stateIds);
|
||||
const capitalCells = capitals.map(capital => capital.cell);
|
||||
|
||||
for (let cellId = 0; cellId > heights.length; cellId++) {
|
||||
if (heights[cellId] < MIN_LAND_HEIGHT) continue;
|
||||
|
||||
const neibs = neibCells[cellId].filter(neib => heights[neib] >= MIN_LAND_HEIGHT);
|
||||
|
||||
const adversaries = neibs.filter(neib => normalizedStateIds[neib] !== normalizedStateIds[cellId]);
|
||||
if (adversaries.length < 2) continue;
|
||||
|
||||
const buddies = neibs.filter(neib => normalizedStateIds[neib] === normalizedStateIds[cellId]);
|
||||
if (buddies.length > 2) continue;
|
||||
|
||||
const isCapital = capitalCells.includes(cellId);
|
||||
if (isCapital) continue;
|
||||
|
||||
const isAdjucentToCapital = neibs.some(neib => capitalCells.includes(neib));
|
||||
if (isAdjucentToCapital) continue;
|
||||
|
||||
// change cells's state
|
||||
if (adversaries.length > buddies.length) normalizedStateIds[cellId] = normalizedStateIds[adversaries[0]];
|
||||
}
|
||||
|
||||
TIME && console.timeEnd("normalizeStates");
|
||||
return normalizedStateIds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,18 +11,27 @@ import {specifyBurgs} from "./specifyBurgs";
|
|||
export function generateBurgsAndStates(
|
||||
cultures: TCultures,
|
||||
features: TPackFeatures,
|
||||
temp: Int8Array,
|
||||
vertices: IGraphVertices,
|
||||
cells: Pick<
|
||||
IPack["cells"],
|
||||
"v" | "c" | "p" | "i" | "g" | "h" | "f" | "t" | "haven" | "harbor" | "r" | "fl" | "biome" | "s" | "culture"
|
||||
>
|
||||
) {
|
||||
): {burgIds: Uint16Array; stateIds: Uint16Array; burgs: TBurgs; states: TStates} {
|
||||
const cellsNumber = cells.i.length;
|
||||
const burgIds = new Uint16Array(cellsNumber);
|
||||
|
||||
const scoredCellIds = getScoredCellIds();
|
||||
const statesNumber = getStatesNumber(scoredCellIds.length);
|
||||
if (statesNumber === 0) return {burgIds, burgs: [NO_BURG], states: [NEUTRALS]};
|
||||
if (statesNumber === 0) {
|
||||
return {
|
||||
burgIds: new Uint16Array(cellsNumber),
|
||||
stateIds: new Uint16Array(cellsNumber),
|
||||
burgs: [NO_BURG],
|
||||
states: [NEUTRALS]
|
||||
};
|
||||
}
|
||||
|
||||
const burgIds = new Uint16Array(cellsNumber);
|
||||
const capitals = createCapitals(statesNumber, scoredCellIds, burgIds, cultures, pick(cells, "p", "f", "culture"));
|
||||
const states = createStates(capitals, cultures);
|
||||
const towns = createTowns(burgIds, cultures, pick(cells, "p", "i", "f", "s", "culture"));
|
||||
|
|
@ -33,11 +42,21 @@ export function generateBurgsAndStates(
|
|||
features,
|
||||
pick(cells, "c", "h", "f", "t", "r", "fl", "s", "biome", "culture")
|
||||
);
|
||||
// normalizeStates();
|
||||
// burgs.filter(b => b.i && !b.removed).forEach(b => (b.state = stateIds[b.cell])); // assign state to burgs
|
||||
|
||||
const roadScores = new Uint16Array(cellsNumber); // TODO: define roads
|
||||
|
||||
const burgs = specifyBurgs(capitals, towns, roadScores);
|
||||
const burgs = specifyBurgs(
|
||||
capitals,
|
||||
towns,
|
||||
roadScores,
|
||||
stateIds,
|
||||
features,
|
||||
temp,
|
||||
vertices,
|
||||
cultures,
|
||||
states,
|
||||
pick(cells, "v", "p", "g", "h", "f", "haven", "harbor", "s", "biome", "fl", "r")
|
||||
);
|
||||
|
||||
return {burgIds, stateIds, burgs, states};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,28 +4,43 @@ import {getCommonEdgePoint} from "utils/lineUtils";
|
|||
import {rn} from "utils/numberUtils";
|
||||
import {gauss, P} from "utils/probabilityUtils";
|
||||
import {NO_BURG} from "./config";
|
||||
|
||||
import type {createCapitals} from "./createCapitals";
|
||||
import type {createStates} from "./createStates";
|
||||
import type {createTowns} from "./createTowns";
|
||||
|
||||
const {COA} = window;
|
||||
|
||||
type TCapitals = ReturnType<typeof createCapitals>;
|
||||
type TTowns = ReturnType<typeof createTowns>;
|
||||
type TStatesReturn = ReturnType<typeof createStates>;
|
||||
|
||||
export function specifyBurgs(capitals: TCapitals, towns: TTowns, roadScores: Uint16Array): TBurgs {
|
||||
export function specifyBurgs(
|
||||
capitals: TCapitals,
|
||||
towns: TTowns,
|
||||
roadScores: Uint16Array,
|
||||
stateIds: Uint16Array,
|
||||
features: TPackFeatures,
|
||||
temp: Int8Array,
|
||||
vertices: IGraphVertices,
|
||||
cultures: TCultures,
|
||||
states: TStatesReturn,
|
||||
cells: Pick<IPack["cells"], "v" | "p" | "g" | "h" | "f" | "haven" | "harbor" | "s" | "biome" | "fl" | "r">
|
||||
): TBurgs {
|
||||
TIME && console.time("specifyBurgs");
|
||||
|
||||
const burgs = [...capitals, ...towns].map(burgData => {
|
||||
const {cell, culture, capital, state} = burgData;
|
||||
const burgs: IBurg[] = [...capitals, ...towns].map(burgData => {
|
||||
const {cell, culture, capital} = burgData;
|
||||
const state = stateIds[cell];
|
||||
|
||||
const port = definePort(cell, capital);
|
||||
const population = definePopulation(cell, capital, port);
|
||||
const [x, y] = defineLocation(cell, port);
|
||||
|
||||
const type = defineType(cell, port, population);
|
||||
const coa = defineEmblem(state, culture, port, capital, type);
|
||||
const coa = defineEmblem(state, culture, port, capital, type, cultures, states);
|
||||
|
||||
return {...burgData, port, population, x, y, type, coa};
|
||||
return {...burgData, state, port, population, x, y, type, coa};
|
||||
});
|
||||
|
||||
TIME && console.timeEnd("specifyBurgs");
|
||||
|
|
@ -98,12 +113,22 @@ export function specifyBurgs(capitals: TCapitals, towns: TTowns, roadScores: Uin
|
|||
return "Generic";
|
||||
}
|
||||
|
||||
function defineEmblem(stateId: number, cultureId: number, port: number, capital: Logical, type: TCultureType) {
|
||||
function defineEmblem(
|
||||
stateId: number,
|
||||
cultureId: number,
|
||||
port: number,
|
||||
capital: Logical,
|
||||
type: TCultureType,
|
||||
cultures: TCultures,
|
||||
states: TStatesReturn
|
||||
) {
|
||||
const coaType = capital && P(0.2) ? "Capital" : type === "Generic" ? "City" : type;
|
||||
const cultureShield = cultures[cultureId].shield;
|
||||
const stateShield = ((states[stateId] as IState)?.coa as ICoa)?.shield;
|
||||
|
||||
if (stateId === 0) {
|
||||
const baseCoa = COA.generate(null, 0, null, coaType);
|
||||
const shield = COA.getShield(cultureId, stateId, cultures, states);
|
||||
const shield = COA.getShield(cultureShield, stateShield);
|
||||
return {...baseCoa, shield};
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +136,7 @@ export function specifyBurgs(capitals: TCapitals, towns: TTowns, roadScores: Uin
|
|||
const kinship = defineKinshipToStateEmblem();
|
||||
|
||||
const baseCoa = COA.generate(stateCOA, kinship, null, coaType);
|
||||
const shield = COA.getShield(cultureId, stateId, cultures, states);
|
||||
const shield = COA.getShield(cultureShield, stateShield);
|
||||
return {...baseCoa, shield};
|
||||
|
||||
function defineKinshipToStateEmblem() {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export function createPack(grid: IGrid): IPack {
|
|||
pop: population
|
||||
});
|
||||
|
||||
const {burgIds, stateIds, burgs, states} = generateBurgsAndStates(cultures, mergedFeatures, {
|
||||
const {burgIds, stateIds, burgs, states} = generateBurgsAndStates(cultures, mergedFeatures, temp, vertices, {
|
||||
...pick(cells, "v", "c", "p", "i", "g"),
|
||||
h: heights,
|
||||
f: featureIds,
|
||||
|
|
|
|||
12
src/types/pack/states.d.ts
vendored
12
src/types/pack/states.d.ts
vendored
|
|
@ -1,11 +1,15 @@
|
|||
interface IState {
|
||||
i: number;
|
||||
name: string;
|
||||
culture: number;
|
||||
center: number;
|
||||
color: Hex | CssUrls;
|
||||
type: TCultureType;
|
||||
culture: number;
|
||||
expansionism: number;
|
||||
fullName: string;
|
||||
removed?: boolean;
|
||||
capital: Logical;
|
||||
coa: ICoa | string;
|
||||
removed?: boolean;
|
||||
}
|
||||
|
||||
type TNeutrals = {
|
||||
|
|
@ -20,6 +24,6 @@ interface ICoa {
|
|||
division: {};
|
||||
ordinaries: {}[];
|
||||
charges: {}[];
|
||||
shield: "heater";
|
||||
t1: "purpure";
|
||||
shield: string;
|
||||
t1: string;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue