mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
refactor: fix burgId issue
This commit is contained in:
parent
ec6285a7a4
commit
bc98757b96
8 changed files with 62 additions and 41 deletions
|
|
@ -5,13 +5,28 @@ import {round} from "utils/stringUtils";
|
||||||
export function drawRoutes() {
|
export function drawRoutes() {
|
||||||
routes.selectAll("path").remove();
|
routes.selectAll("path").remove();
|
||||||
|
|
||||||
|
const {cells, burgs} = pack;
|
||||||
const lineGen = d3.line().curve(d3.curveBasis);
|
const lineGen = d3.line().curve(d3.curveBasis);
|
||||||
|
|
||||||
|
const getBurgCoords = (burgId: number): TPoint => {
|
||||||
|
if (!burgId) throw new Error("burgId must be positive");
|
||||||
|
const burg = burgs[burgId] as IBurg;
|
||||||
|
return [burg.x, burg.y];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPathPoints = (cellIds: number[]): TPoints =>
|
||||||
|
cellIds.map(cellId => {
|
||||||
|
const burgId = cells.burg[cellId];
|
||||||
|
if (burgId) return getBurgCoords(burgId);
|
||||||
|
|
||||||
|
return cells.p[cellId];
|
||||||
|
});
|
||||||
|
|
||||||
const routePaths: Dict<string[]> = {};
|
const routePaths: Dict<string[]> = {};
|
||||||
|
|
||||||
for (const {i, type, cells: routeCells} of pack.routes) {
|
for (const {i, type, cells: routeCells} of pack.routes) {
|
||||||
const points = routeCells.map(cellId => pack.cells.p[cellId]);
|
const points = getPathPoints(routeCells);
|
||||||
const path = round(lineGen(points)!);
|
const path = round(lineGen(points)!, 1);
|
||||||
|
|
||||||
if (!routePaths[type]) routePaths[type] = [];
|
if (!routePaths[type]) routePaths[type] = [];
|
||||||
routePaths[type].push(`<path id="${type}${i}" d="${path}"/>`);
|
routePaths[type].push(`<path id="${type}${i}" d="${path}"/>`);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ const {Names} = window;
|
||||||
export function createCapitals(
|
export function createCapitals(
|
||||||
statesNumber: number,
|
statesNumber: number,
|
||||||
scoredCellIds: UintArray,
|
scoredCellIds: UintArray,
|
||||||
burgIds: Uint16Array,
|
|
||||||
cultures: TCultures,
|
cultures: TCultures,
|
||||||
cells: Pick<IPack["cells"], "p" | "f" | "culture">
|
cells: Pick<IPack["cells"], "p" | "f" | "culture">
|
||||||
) {
|
) {
|
||||||
|
|
@ -15,20 +14,15 @@ export function createCapitals(
|
||||||
|
|
||||||
const capitalCells = placeCapitals(statesNumber, scoredCellIds, cells.p);
|
const capitalCells = placeCapitals(statesNumber, scoredCellIds, cells.p);
|
||||||
|
|
||||||
const capitals = capitalCells.map((cellId, index) => {
|
const capitals = capitalCells.map(cellId => {
|
||||||
const id = index + 1;
|
|
||||||
const cultureId = cells.culture[cellId];
|
const cultureId = cells.culture[cellId];
|
||||||
const nameBase = cultures[cultureId].base;
|
const nameBase = cultures[cultureId].base;
|
||||||
const name: string = Names.getBaseShort(nameBase);
|
const name: string = Names.getBaseShort(nameBase);
|
||||||
const featureId = cells.f[cellId];
|
const featureId = cells.f[cellId];
|
||||||
|
|
||||||
return {i: id, cell: cellId, culture: cultureId, name, feature: featureId, capital: 1 as Logical};
|
return {cell: cellId, culture: cultureId, name, feature: featureId, capital: 1 as Logical};
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const {cell, i} of capitals) {
|
|
||||||
burgIds[cell] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIME && console.timeEnd("createCapitals");
|
TIME && console.timeEnd("createCapitals");
|
||||||
return capitals;
|
return capitals;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export function createStates(capitals: TCapitals, cultures: TCultures) {
|
||||||
const powerInput = getInputNumber("powerInput");
|
const powerInput = getInputNumber("powerInput");
|
||||||
|
|
||||||
const states = capitals.map((capital, index) => {
|
const states = capitals.map((capital, index) => {
|
||||||
const {cell: cellId, culture: cultureId, name: capitalName, i: capitalId} = capital;
|
const {cell: cellId, culture: cultureId, name: capitalName} = capital;
|
||||||
const id = index + 1;
|
const id = index + 1;
|
||||||
const name = getStateName(cellId, capitalName, cultureId, cultures);
|
const name = getStateName(cellId, capitalName, cultureId, cultures);
|
||||||
const color = colors[index];
|
const color = colors[index];
|
||||||
|
|
@ -28,7 +28,7 @@ export function createStates(capitals: TCapitals, cultures: TCultures) {
|
||||||
const shield = COA.getShield(cultureShield, null);
|
const shield = COA.getShield(cultureShield, null);
|
||||||
const coa: ICoa = {...COA.generate(null, null, null, type), shield};
|
const coa: ICoa = {...COA.generate(null, null, null, type), shield};
|
||||||
|
|
||||||
return {i: id, name, type, center: cellId, color, expansionism, capital: capitalId, culture: cultureId, coa};
|
return {i: id, name, type, center: cellId, color, expansionism, capital: id, culture: cultureId, coa};
|
||||||
});
|
});
|
||||||
|
|
||||||
TIME && console.timeEnd("createStates");
|
TIME && console.timeEnd("createStates");
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {gauss} from "utils/probabilityUtils";
|
||||||
const {Names} = window;
|
const {Names} = window;
|
||||||
|
|
||||||
export function createTowns(
|
export function createTowns(
|
||||||
burgIds: Uint16Array,
|
capitalCells: Map<number, boolean>,
|
||||||
cultures: TCultures,
|
cultures: TCultures,
|
||||||
cells: Pick<IPack["cells"], "p" | "i" | "f" | "s" | "culture">
|
cells: Pick<IPack["cells"], "p" | "i" | "f" | "s" | "culture">
|
||||||
) {
|
) {
|
||||||
|
|
@ -19,7 +19,7 @@ export function createTowns(
|
||||||
const scores = new Int16Array(cells.s.map(randomizeScore));
|
const scores = new Int16Array(cells.s.map(randomizeScore));
|
||||||
|
|
||||||
// take populated cells without capitals
|
// take populated cells without capitals
|
||||||
const scoredCellIds = cells.i.filter(i => scores[i] > 0 && cells.culture[i] && !burgIds[i]);
|
const scoredCellIds = cells.i.filter(i => scores[i] > 0 && cells.culture[i] && !capitalCells.has(i));
|
||||||
scoredCellIds.sort((a, b) => scores[b] - scores[a]); // sort by randomized suitability score
|
scoredCellIds.sort((a, b) => scores[b] - scores[a]); // sort by randomized suitability score
|
||||||
|
|
||||||
const townsNumber = getTownsNumber();
|
const townsNumber = getTownsNumber();
|
||||||
|
|
@ -27,20 +27,15 @@ export function createTowns(
|
||||||
|
|
||||||
const townCells = placeTowns(townsNumber, scoredCellIds, cells.p);
|
const townCells = placeTowns(townsNumber, scoredCellIds, cells.p);
|
||||||
|
|
||||||
const towns = townCells.map((cellId, index) => {
|
const towns = townCells.map(cellId => {
|
||||||
const id = index + 1;
|
|
||||||
const cultureId = cells.culture[cellId];
|
const cultureId = cells.culture[cellId];
|
||||||
const namesbase = cultures[cultureId].base;
|
const namesbase = cultures[cultureId].base;
|
||||||
const name: string = Names.getBase(namesbase);
|
const name: string = Names.getBase(namesbase);
|
||||||
const featureId = cells.f[cellId];
|
const featureId = cells.f[cellId];
|
||||||
|
|
||||||
return {i: id, cell: cellId, culture: cultureId, name, feature: featureId, capital: 0 as Logical};
|
return {cell: cellId, culture: cultureId, name, feature: featureId, capital: 0 as Logical};
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const {cell, i} of towns) {
|
|
||||||
burgIds[cell] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIME && console.timeEnd("createTowns");
|
TIME && console.timeEnd("createTowns");
|
||||||
return towns;
|
return towns;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ type TStates = ReturnType<typeof createStates>;
|
||||||
|
|
||||||
// growth algorithm to assign cells to states
|
// growth algorithm to assign cells to states
|
||||||
export function expandStates(
|
export function expandStates(
|
||||||
capitals: TCapitals,
|
capitalCells: Map<number, boolean>,
|
||||||
states: TStates,
|
states: TStates,
|
||||||
features: TPackFeatures,
|
features: TPackFeatures,
|
||||||
cells: Pick<IPack["cells"], "c" | "h" | "f" | "t" | "r" | "fl" | "s" | "biome" | "culture">
|
cells: Pick<IPack["cells"], "c" | "h" | "f" | "t" | "r" | "fl" | "s" | "biome" | "culture">
|
||||||
|
|
@ -28,7 +28,10 @@ export function expandStates(
|
||||||
const neutralInput = getInputNumber("neutralInput");
|
const neutralInput = getInputNumber("neutralInput");
|
||||||
const maxExpansionCost = (cellsNumber / 2) * neutralInput * statesNeutral;
|
const maxExpansionCost = (cellsNumber / 2) * neutralInput * statesNeutral;
|
||||||
|
|
||||||
for (const {i: stateId, cell: cellId} of capitals) {
|
for (const state of states) {
|
||||||
|
if (state.i === 0) continue;
|
||||||
|
|
||||||
|
const {i: stateId, center: cellId} = state as IState;
|
||||||
stateIds[cellId] = stateId;
|
stateIds[cellId] = stateId;
|
||||||
cost[cellId] = 1;
|
cost[cellId] = 1;
|
||||||
queue.push({cellId, stateId}, 0);
|
queue.push({cellId, stateId}, 0);
|
||||||
|
|
@ -99,7 +102,7 @@ export function expandStates(
|
||||||
|
|
||||||
TIME && console.timeEnd("expandStates");
|
TIME && console.timeEnd("expandStates");
|
||||||
|
|
||||||
return normalizeStates(stateIds, capitals, cells.c, cells.h);
|
return normalizeStates(stateIds, capitalCells, cells.c, cells.h);
|
||||||
|
|
||||||
function isNeutrals(state: Entry<TStates>): state is TNeutrals {
|
function isNeutrals(state: Entry<TStates>): state is TNeutrals {
|
||||||
return state.i === 0;
|
return state.i === 0;
|
||||||
|
|
@ -195,11 +198,15 @@ export function expandStates(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeStates(stateIds: Uint16Array, capitals: TCapitals, neibCells: number[][], heights: Uint8Array) {
|
function normalizeStates(
|
||||||
|
stateIds: Uint16Array,
|
||||||
|
capitalCells: Map<number, boolean>,
|
||||||
|
neibCells: number[][],
|
||||||
|
heights: Uint8Array
|
||||||
|
) {
|
||||||
TIME && console.time("normalizeStates");
|
TIME && console.time("normalizeStates");
|
||||||
|
|
||||||
const normalizedStateIds = Uint16Array.from(stateIds);
|
const normalizedStateIds = Uint16Array.from(stateIds);
|
||||||
const capitalCells = capitals.map(capital => capital.cell);
|
|
||||||
|
|
||||||
for (let cellId = 0; cellId > heights.length; cellId++) {
|
for (let cellId = 0; cellId > heights.length; cellId++) {
|
||||||
if (heights[cellId] < MIN_LAND_HEIGHT) continue;
|
if (heights[cellId] < MIN_LAND_HEIGHT) continue;
|
||||||
|
|
@ -212,10 +219,10 @@ function normalizeStates(stateIds: Uint16Array, capitals: TCapitals, neibCells:
|
||||||
const buddies = neibs.filter(neib => normalizedStateIds[neib] === normalizedStateIds[cellId]);
|
const buddies = neibs.filter(neib => normalizedStateIds[neib] === normalizedStateIds[cellId]);
|
||||||
if (buddies.length > 2) continue;
|
if (buddies.length > 2) continue;
|
||||||
|
|
||||||
const isCapital = capitalCells.includes(cellId);
|
const isCapital = capitalCells.has(cellId);
|
||||||
if (isCapital) continue;
|
if (isCapital) continue;
|
||||||
|
|
||||||
const isAdjucentToCapital = neibs.some(neib => capitalCells.includes(neib));
|
const isAdjucentToCapital = neibs.some(neib => capitalCells.has(neib));
|
||||||
if (isAdjucentToCapital) continue;
|
if (isAdjucentToCapital) continue;
|
||||||
|
|
||||||
// change cells's state
|
// change cells's state
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,14 @@ export function generateBurgsAndStates(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const burgIds = new Uint16Array(cellsNumber);
|
const capitals = createCapitals(statesNumber, scoredCellIds, cultures, pick(cells, "p", "f", "culture"));
|
||||||
const capitals = createCapitals(statesNumber, scoredCellIds, burgIds, cultures, pick(cells, "p", "f", "culture"));
|
const capitalCells = new Map(capitals.map(({cell}) => [cell, true]));
|
||||||
|
|
||||||
const states = createStates(capitals, cultures);
|
const states = createStates(capitals, cultures);
|
||||||
const towns = createTowns(burgIds, cultures, pick(cells, "p", "i", "f", "s", "culture"));
|
const towns = createTowns(capitalCells, cultures, pick(cells, "p", "i", "f", "s", "culture"));
|
||||||
|
|
||||||
const stateIds = expandStates(
|
const stateIds = expandStates(
|
||||||
capitals,
|
capitalCells,
|
||||||
states,
|
states,
|
||||||
features,
|
features,
|
||||||
pick(cells, "c", "h", "f", "t", "r", "fl", "s", "biome", "culture")
|
pick(cells, "c", "h", "f", "t", "r", "fl", "s", "biome", "culture")
|
||||||
|
|
@ -57,6 +58,8 @@ export function generateBurgsAndStates(
|
||||||
pick(cells, "v", "p", "g", "h", "f", "haven", "harbor", "s", "biome", "fl", "r")
|
pick(cells, "v", "p", "g", "h", "f", "haven", "harbor", "s", "biome", "fl", "r")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const burgIds = assignBurgIds(burgs);
|
||||||
|
|
||||||
return {burgIds, stateIds, burgs, states};
|
return {burgIds, stateIds, burgs, states};
|
||||||
|
|
||||||
function getScoredCellIds() {
|
function getScoredCellIds() {
|
||||||
|
|
@ -85,4 +88,15 @@ export function generateBurgsAndStates(
|
||||||
|
|
||||||
return requestedStatesNumber;
|
return requestedStatesNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assignBurgIds(burgs: TBurgs) {
|
||||||
|
const burgIds = new Uint16Array(cellsNumber);
|
||||||
|
|
||||||
|
for (let i = 1; i < burgs.length; i++) {
|
||||||
|
const {cell} = burgs[i] as IBurg;
|
||||||
|
burgIds[cell] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return burgIds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export function specifyBurgs(
|
||||||
): TBurgs {
|
): TBurgs {
|
||||||
TIME && console.time("specifyBurgs");
|
TIME && console.time("specifyBurgs");
|
||||||
|
|
||||||
const burgs = [...capitals, ...towns].map(burgData => {
|
const burgs = [...capitals, ...towns].map((burgData, index) => {
|
||||||
const {cell, culture, capital} = burgData;
|
const {cell, culture, capital} = burgData;
|
||||||
const state = stateIds[cell];
|
const state = stateIds[cell];
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ export function specifyBurgs(
|
||||||
const type = defineType(cell, port, population);
|
const type = defineType(cell, port, population);
|
||||||
const coa: ICoa = defineEmblem(state, culture, port, capital, type, cultures, states);
|
const coa: ICoa = defineEmblem(state, culture, port, capital, type, cultures, states);
|
||||||
|
|
||||||
const burg: IBurg = {...burgData, state, port, population, x, y, type, coa};
|
const burg: IBurg = {i: index + 1, ...burgData, state, port, population, x, y, type, coa};
|
||||||
return burg;
|
return burg;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
import {ERROR} from "../config/logging";
|
|
||||||
import {rn} from "./numberUtils";
|
import {rn} from "./numberUtils";
|
||||||
|
|
||||||
// round numbers in string to d decimals
|
// round numbers in string to d decimals
|
||||||
export function round(str: string, d = 1) {
|
export function round(str: string, decimals = 1) {
|
||||||
if (!str) {
|
if (!str) throw new Error("Path is empty");
|
||||||
ERROR && console.error("Path is empty", str);
|
return str.replace(/[\d\.-][\d\.e-]*/g, n => String(rn(+n, decimals)));
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return str.replace(/[\d\.-][\d\.e-]*/g, n => String(rn(+n, d)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return string with 1st char capitalized
|
// return string with 1st char capitalized
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue