refactor: refactor religions expand

This commit is contained in:
Azgaar 2022-09-01 00:22:46 +03:00
parent 5361565cd7
commit b9ff6a652c
13 changed files with 55 additions and 40 deletions

View file

@ -1639,7 +1639,7 @@
</td>
<td>Religions number</td>
<td>
<input id="religionsInput" data-stored="religions" type="range" min="0" max="50" step="1" value="15" />
<input id="religionsInput" data-stored="religions" type="range" min="0" max="50" step="1" />
</td>
<td>
<output id="religionsOutput" data-stored="religions" value="auto"></output>

View file

@ -1119,7 +1119,7 @@ function adjustProvinces(affectedProvinces) {
// reassign province ownership to province center owner
prevOwner.provinces = prevOwner.provinces.filter(province => province !== provinceId);
province.state = stateId;
province.color = getMixedColor(states[stateId].color);
province.color = brighter(getMixedColor(states[stateId].color, 0.2), 0.3);
states[stateId].provinces.push(provinceId);
return;
}
@ -1163,7 +1163,7 @@ function adjustProvinces(affectedProvinces) {
const formOptions = ["Zone", "Area", "Territory", "Province"];
const formName = burgCell && oldProvince.formName ? oldProvince.formName : ra(formOptions);
const color = getMixedColor(states[stateId].color);
const color = brighter(getMixedColor(states[stateId].color, 0.2), 0.3);
const kinship = nameByBurg ? 0.8 : 0.4;
const type = BurgsAndStates.getType(center, burg?.port);

View file

@ -780,7 +780,7 @@ window.BurgsAndStates = (function () {
const sameColored = pack.states.filter(s => s.color === c);
sameColored.forEach((s, d) => {
if (!d) return;
s.color = getMixedColor(s.color);
s.color = brighter(getMixedColor(s.color, 0.2), 0.3);
});
});
@ -1209,7 +1209,7 @@ window.BurgsAndStates = (function () {
const formName = rw(form);
form[formName] += 10;
const fullName = name + " " + formName;
const color = getMixedColor(s.color);
const color = brighter(getMixedColor(s.color, 0.2), 0.3);
const kinship = nameByBurg ? 0.8 : 0.4;
const type = getType(center, burg.port);
const coa = COA.generate(stateBurgs[i].coa, kinship, null, type);
@ -1317,7 +1317,7 @@ window.BurgsAndStates = (function () {
// generate "wild" province name
const cultureId = cells.culture[center];
const f = pack.features[cells.f[center]];
const color = getMixedColor(s.color);
const color = brighter(getMixedColor(s.color, 0.2), 0.3);
const provCells = stateNoProvince.filter(i => cells.province[i] === province);
const singleIsle = provCells.length === f.cells && !provCells.find(i => cells.f[i] !== f.i);

View file

@ -566,7 +566,7 @@ export function randomizeOptions() {
manorsInput.value = 1000;
manorsOutput.value = "auto";
}
if (randomize || !locked("religions")) religionsInput.value = religionsOutput.value = gauss(5, 2, 2, 10);
if (randomize || !locked("religions")) religionsInput.value = religionsOutput.value = gauss(6, 3, 2, 10);
if (randomize || !locked("power")) powerInput.value = powerOutput.value = gauss(4, 2, 0, 10, 2);
if (randomize || !locked("neutral")) neutralInput.value = neutralOutput.value = rn(1 + Math.random(), 1);
if (randomize || !locked("cultures")) culturesInput.value = culturesOutput.value = gauss(12, 3, 5, 30);

View file

@ -4,14 +4,16 @@ import {openDialog} from "dialogs";
import {tip} from "scripts/tooltips";
import {handleMapClick} from "./onclick";
import {onMouseMove} from "./onhover";
// @ts-expect-error js module
import {clearLegend, dragLegendBox} from "modules/legend";
export function setDefaultEventHandlers() {
window.Zoom.setZoomBehavior();
viewbox.style("cursor", "default").on(".drag", null).on("click", handleMapClick);
//.on("touchmove mousemove", onMouseMove);
viewbox
.style("cursor", "default")
.on(".drag", null)
.on("click", handleMapClick)
.on("touchmove mousemove", onMouseMove);
scaleBar.on("mousemove", () => tip("Click to open Units Editor")).on("click", () => openDialog("unitsEditor"));

View file

@ -1,9 +1,6 @@
import * as d3 from "d3";
import {layerIsOn} from "layers";
// @ts-expect-error js module
import {clearLegend, dragLegendBox} from "modules/legend";
// @ts-expect-error js module
import {updateCellInfo} from "modules/ui/cell-info";
import {debounce} from "utils/functionUtils";
import {findCell, findGridCell, isLand} from "utils/graphUtils";
@ -78,7 +75,7 @@ const getHoveredElement = (tagName: string, group: string, subgroup: string, isL
if (layerIsOn("togglePopulation")) return "populationLayer";
if (layerIsOn("toggleTemp")) return "temperatureLayer";
if (layerIsOn("toggleBiomes") && biome[cellId]) return "biomesLayer";
if (layerIsOn("toggleReligions") && religion[cellId]) return "religionsLayer";
if (religion[cellId]) return "religionsLayer"; // layerIsOn("toggleReligions") &&
if (layerIsOn("toggleProvinces") || (layerIsOn("toggleStates") && state[cellId])) return "statesLayer";
if (layerIsOn("toggleCultures") && culture[cellId]) return "culturesLayer";
if (layerIsOn("toggleHeight")) return "heightLayer";

View file

@ -26,6 +26,7 @@ import {createGrid} from "./grid/grid";
import {createPack} from "./pack/pack";
import {getInputValue, setInputValue} from "utils/nodeUtils";
import {calculateMapCoordinates} from "modules/coordinates";
import {drawPoint} from "utils/debugUtils";
const {Zoom, ThreeD} = window;
@ -72,6 +73,10 @@ async function generate(options?: IGenerationOptions) {
// renderLayer("states");
renderLayer("religions");
// pack.cells.route.forEach((route, index) => {
// if (route === 2) drawPoint(pack.cells.p[index], {color: "black"});
// });
WARN && console.warn(`TOTAL: ${rn((performance.now() - timeStart) / 1000, 2)}s`);
// showStatistics();
INFO && console.groupEnd();

View file

@ -103,7 +103,7 @@ export function generateRoutes(burgs: TBurgs, temp: Int8Array, cells: TCellsData
const segments = findPathSegments({isWater: true, cellRoutes, connections, start, exit});
for (const segment of segments) {
addConnections(segment, ROUTES.MAIN_ROAD);
addConnections(segment, ROUTES.SEA_ROUTE);
mainRoads.push({feature: Number(key), cells: segment});
}
});
@ -118,7 +118,7 @@ export function generateRoutes(burgs: TBurgs, temp: Int8Array, cells: TCellsData
const cellId = segment[i];
const nextCellId = segment[i + 1];
if (nextCellId) connections.set(`${cellId}-${nextCellId}`, true);
cellRoutes[cellId] = roadTypeId;
if (!cellRoutes[cellId]) cellRoutes[cellId] = roadTypeId;
}
}

View file

@ -188,11 +188,11 @@ export function createPack(grid: IGrid): IPack {
burg: burgIds,
state: stateIds,
route: cellRoutes,
religion: religionIds
// province
religion: religionIds,
province: new Uint16Array(cells.i.length)
},
features: mergedFeatures,
// rivers: rawRivers, // "name" | "basin" | "type"
rivers: rawRivers, // "name" | "basin" | "type"
cultures,
states,
burgs,

View file

@ -1,12 +1,12 @@
import FlatQueue from "flatqueue";
import {ROUTES} from "config/generation";
import {MIN_LAND_HEIGHT, ROUTES} from "config/generation";
import {getInputNumber} from "utils/nodeUtils";
import {gauss} from "utils/probabilityUtils";
import {isReligion} from "utils/typeUtils";
type TReligionData = Pick<IReligion, "i" | "type" | "center" | "culture" | "expansion" | "expansionism">;
type TCellsData = Pick<IPack["cells"], "i" | "c" | "biome" | "culture" | "state" | "route">;
type TCellsData = Pick<IPack["cells"], "i" | "c" | "h" | "biome" | "culture" | "state" | "route">;
export function expandReligions(religions: TReligionData[], cells: TCellsData) {
const religionIds = spreadFolkReligions(religions, cells);
@ -15,11 +15,9 @@ export function expandReligions(religions: TReligionData[], cells: TCellsData) {
const cost: number[] = [];
const neutralInput = getInputNumber("neutralInput");
const maxExpansionCost = (cells.i.length / 25) * gauss(1, 0.3, 0.2, 2, 2) * neutralInput;
const maxExpansionCost = (cells.i.length / 20) * gauss(1, 0.3, 0.2, 2, 2) * neutralInput;
const biomePassageCost = (cellId: number) => biomesData.cost[cells.biome[cellId]];
const isMainRoad = (cellId: number) => cells.route[cellId] === ROUTES.MAIN_ROAD;
const isSeaRoute = (cellId: number) => cells.route[cellId] === ROUTES.SEA_ROUTE;
for (const religion of religions) {
if (!isReligion(religion as IReligion) || (religion as IReligion).type === "Folk") continue;
@ -32,6 +30,11 @@ export function expandReligions(religions: TReligionData[], cells: TCellsData) {
const religionsMap = new Map<number, TReligionData>(religions.map(religion => [religion.i, religion]));
const isMainRoad = (cellId: number) => cells.route[cellId] === ROUTES.MAIN_ROAD;
const isTrail = (cellId: number) => cells.route[cellId] === ROUTES.TRAIL;
const isSeaRoute = (cellId: number) => cells.route[cellId] === ROUTES.SEA_ROUTE;
const isWater = (cellId: number) => cells.h[cellId] < MIN_LAND_HEIGHT;
while (queue.length) {
const priority = queue.peekValue()!;
const {cellId, religionId} = queue.pop()!;
@ -39,16 +42,14 @@ export function expandReligions(religions: TReligionData[], cells: TCellsData) {
const {culture, center, expansion, expansionism} = religionsMap.get(religionId)!;
cells.c[cellId].forEach(neibCellId => {
// if (neibCellId === center && religionIds[neibCellId]) return; // do not overwrite center cells
if (expansion === "culture" && culture !== cells.culture[neibCellId]) return;
if (expansion === "state" && cells.state[center] !== cells.state[neibCellId]) return;
const cultureCost = culture !== cells.culture[neibCellId] ? 50 : 0;
const stateCost = cells.state[center] !== cells.state[neibCellId] ? 50 : 0;
const passageCost = isMainRoad(neibCellId) ? 1 : biomePassageCost(neibCellId); // [1, 5000]
const waterCost = isSeaRoute(neibCellId) ? 50 : 1000;
const cultureCost = culture !== cells.culture[neibCellId] ? 10 : 0;
const stateCost = cells.state[center] !== cells.state[neibCellId] ? 10 : 0;
const passageCost = getPassageCost(neibCellId);
const cellCost = Math.max(cultureCost + stateCost + passageCost + waterCost, 0);
const cellCost = cultureCost + stateCost + passageCost;
const totalCost = priority + 10 + cellCost / expansionism;
if (totalCost > maxExpansionCost) return;
@ -62,6 +63,13 @@ export function expandReligions(religions: TReligionData[], cells: TCellsData) {
}
return religionIds;
function getPassageCost(cellId: number) {
if (isWater(cellId)) return isSeaRoute(cellId) ? 50 : 500;
if (isMainRoad(cellId)) return 1;
const biomeCost = biomePassageCost(cellId); // [1, 5000]
return isTrail(cellId) ? biomeCost / 1.5 : biomeCost;
}
}
// folk religions initially get all cells of their culture

View file

@ -30,7 +30,7 @@ export function generateReligions({
cultures,
states,
burgs,
pick(cells, "i", "c", "biome", "culture", "burg", "state", "route")
pick(cells, "i", "c", "h", "biome", "culture", "burg", "state", "route")
);
folkReligions.forEach(({center}) => drawPoint(cells.p[center], {radius: 3, color: "blue"}));

View file

@ -1,4 +1,4 @@
import {brighter, getMixedColor} from "utils/colorUtils";
import {brighter, darker, getMixedColor} from "utils/colorUtils";
import {each, gauss, rand} from "utils/probabilityUtils";
import {isCulture} from "utils/typeUtils";
import {expandReligions} from "./expandReligions";
@ -7,19 +7,20 @@ import {generateReligionName} from "./generateReligionName";
const expansionismMap = {
Folk: () => 0,
Organized: () => rand(3, 8),
Cult: () => gauss(1.1, 0.5, 0, 5),
Heresy: () => gauss(1.2, 0.5, 0, 5)
Organized: () => gauss(5, 3, 0, 10, 1),
Cult: () => gauss(0.5, 0.5, 0, 5, 1),
Heresy: () => gauss(1, 0.5, 0, 5, 1)
};
type TReligionData = Pick<IReligion, "type" | "form" | "culture" | "center">;
type TCellsData = Pick<IPack["cells"], "i" | "c" | "h" | "biome" | "culture" | "burg" | "state" | "route">;
export function specifyReligions(
religionsData: TReligionData[],
cultures: TCultures,
states: TStates,
burgs: TBurgs,
cells: Pick<IPack["cells"], "i" | "c" | "biome" | "culture" | "burg" | "state" | "route">
cells: TCellsData
): {religions: TReligions; religionIds: Uint16Array} {
const rawReligions = religionsData.map(({type, form, culture: cultureId, center}, index) => {
const supreme = getDeityName(cultures, cultureId);
@ -56,8 +57,10 @@ export function specifyReligions(
const culture = cultures[cultureId];
if (!isCulture(culture)) throw new Error(`Culture ${cultureId} is not a valid culture`);
if (type === "Folk") return brighter(culture.color, 0.2);
return getMixedColor(culture.color, 0.2, 0);
if (type === "Folk") return culture.color;
if (type === "Heresy") return darker(getMixedColor(culture.color, 0.35), 0.3);
if (type === "Cult") return darker(getMixedColor(culture.color, 0.5), 0.8);
return brighter(getMixedColor(culture.color, 0.25), 0.3);
}
function combineReligionsData(): TReligions {

View file

@ -46,12 +46,12 @@ export function getRandomColor(): Hex {
}
// mix a color with a random color. TODO: refactor without interpolation
export function getMixedColor(color: Hex | CssUrl, mixation = 0.2, bright = 0.3) {
export function getMixedColor(color: Hex | CssUrl, mixation: number) {
const color1 = color.startsWith("#") ? color : getRandomColor();
const color2 = getRandomColor();
const mixedColor = d3.interpolate(color1, color2)(mixation);
return d3.color(mixedColor)!.brighter(bright).formatHex() as Hex;
return d3.color(mixedColor)!.formatHex() as Hex;
}
export function darker(color: Hex | CssUrl, amount = 1) {