mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-04-04 14:37:24 +02:00
Adapt generator
This commit is contained in:
parent
85f52e81a6
commit
6ced96796c
3 changed files with 53 additions and 481 deletions
20
package-lock.json
generated
20
package-lock.json
generated
|
|
@ -14,7 +14,8 @@
|
||||||
"armoria": "file:../armoria/dist",
|
"armoria": "file:../armoria/dist",
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
"delaunator": "^5.0.1",
|
"delaunator": "^5.0.1",
|
||||||
"polylabel": "^2.0.1"
|
"polylabel": "^2.0.1",
|
||||||
|
"symlink-dir": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.3.13",
|
"@biomejs/biome": "2.3.13",
|
||||||
|
|
@ -26,7 +27,6 @@
|
||||||
"@vitest/browser": "^4.0.18",
|
"@vitest/browser": "^4.0.18",
|
||||||
"@vitest/browser-playwright": "^4.0.18",
|
"@vitest/browser-playwright": "^4.0.18",
|
||||||
"playwright": "^1.57.0",
|
"playwright": "^1.57.0",
|
||||||
"symlink-dir": "^9.0.0",
|
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^7.3.1",
|
"vite": "^7.3.1",
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.0.18"
|
||||||
|
|
@ -51,14 +51,11 @@
|
||||||
"puppeteer-core": "24.11.2"
|
"puppeteer-core": "24.11.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^7.0.1",
|
|
||||||
"@sveltejs/adapter-static": "^3.0.10",
|
|
||||||
"@sveltejs/adapter-vercel": "^6.3.3",
|
"@sveltejs/adapter-vercel": "^6.3.3",
|
||||||
"@sveltejs/kit": "^2.22.5",
|
"@sveltejs/kit": "^2.22.5",
|
||||||
"@sveltejs/package": "^2.5.7",
|
"@sveltejs/package": "^2.5.7",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
"armoria-core": "file:../armoria-core",
|
|
||||||
"eslint": "^9.31.0",
|
"eslint": "^9.31.0",
|
||||||
"eslint-config-prettier": "^10.1.5",
|
"eslint-config-prettier": "^10.1.5",
|
||||||
"eslint-plugin-svelte": "^3.10.1",
|
"eslint-plugin-svelte": "^3.10.1",
|
||||||
|
|
@ -75,6 +72,10 @@
|
||||||
"typescript-eslint": "^8.36.0",
|
"typescript-eslint": "^8.36.0",
|
||||||
"vite": "^5.0.3",
|
"vite": "^5.0.3",
|
||||||
"workbox-precaching": "^7.3.0"
|
"workbox-precaching": "^7.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@sveltejs/kit": "^2.22.5",
|
||||||
|
"svelte": "^4.2.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@biomejs/biome": {
|
"node_modules/@biomejs/biome": {
|
||||||
|
|
@ -1571,7 +1572,6 @@
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@zkochan/rimraf/-/rimraf-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@zkochan/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
"integrity": "sha512-GBf4ua7ogWTr7fATnzk/JLowZDBnBJMm8RkMaC/KcvxZ9gxbMWix0/jImd815LmqKyIHZ7h7lADRddGMdGBuCA==",
|
"integrity": "sha512-GBf4ua7ogWTr7fATnzk/JLowZDBnBJMm8RkMaC/KcvxZ9gxbMWix0/jImd815LmqKyIHZ7h7lADRddGMdGBuCA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.12"
|
"node": ">=18.12"
|
||||||
|
|
@ -1601,7 +1601,6 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz",
|
||||||
"integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==",
|
"integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-windows": "^1.0.0"
|
"is-windows": "^1.0.0"
|
||||||
|
|
@ -2130,7 +2129,6 @@
|
||||||
"version": "11.3.0",
|
"version": "11.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
||||||
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
|
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
|
|
@ -2160,7 +2158,6 @@
|
||||||
"version": "4.2.11",
|
"version": "4.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
|
|
@ -2188,7 +2185,6 @@
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
||||||
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
|
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
|
|
@ -2198,7 +2194,6 @@
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
|
|
@ -2396,7 +2391,6 @@
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/rename-overwrite/-/rename-overwrite-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/rename-overwrite/-/rename-overwrite-6.0.3.tgz",
|
||||||
"integrity": "sha512-Daqe51STnrCUq/t4dbzCtfNBLElrqVpCtuWK0MuPrzUi6K/13E98y3E8/kzuMZt6IEmghMnF41J0AidrFqjZUA==",
|
"integrity": "sha512-Daqe51STnrCUq/t4dbzCtfNBLElrqVpCtuWK0MuPrzUi6K/13E98y3E8/kzuMZt6IEmghMnF41J0AidrFqjZUA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zkochan/rimraf": "^3.0.2",
|
"@zkochan/rimraf": "^3.0.2",
|
||||||
|
|
@ -2519,7 +2513,6 @@
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/symlink-dir/-/symlink-dir-9.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/symlink-dir/-/symlink-dir-9.0.0.tgz",
|
||||||
"integrity": "sha512-3i39G70eXo9POjx9RnYAgymfUO3AFrezABaJq0Sh+muMCR3Lx7B9KQR2uWMY+yc1QCwhEelVCGS6N+sR3aKCZg==",
|
"integrity": "sha512-3i39G70eXo9POjx9RnYAgymfUO3AFrezABaJq0Sh+muMCR3Lx7B9KQR2uWMY+yc1QCwhEelVCGS6N+sR3aKCZg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-path-resolve": "^1.0.0",
|
"better-path-resolve": "^1.0.0",
|
||||||
|
|
@ -2617,7 +2610,6 @@
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@
|
||||||
"@vitest/browser": "^4.0.18",
|
"@vitest/browser": "^4.0.18",
|
||||||
"@vitest/browser-playwright": "^4.0.18",
|
"@vitest/browser-playwright": "^4.0.18",
|
||||||
"playwright": "^1.57.0",
|
"playwright": "^1.57.0",
|
||||||
"symlink-dir": "^9.0.0",
|
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^7.3.1",
|
"vite": "^7.3.1",
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.0.18"
|
||||||
|
|
@ -44,7 +43,8 @@
|
||||||
"armoria": "file:../armoria/dist",
|
"armoria": "file:../armoria/dist",
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
"delaunator": "^5.0.1",
|
"delaunator": "^5.0.1",
|
||||||
"polylabel": "^2.0.1"
|
"polylabel": "^2.0.1",
|
||||||
|
"symlink-dir": "^9.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=24.0.0"
|
"node": ">=24.0.0"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
import {
|
import { generateCOA, getTincture, shields, tinctures } from "armoria";
|
||||||
charges,
|
|
||||||
divisions,
|
|
||||||
lines,
|
|
||||||
ordinaries,
|
|
||||||
positions,
|
|
||||||
shields,
|
|
||||||
tinctures,
|
|
||||||
} from "armoria";
|
|
||||||
import { P, rw } from "../../utils";
|
import { P, rw } from "../../utils";
|
||||||
import { typeMapping } from "./typeMapping";
|
import { typeMapping } from "./typeMapping";
|
||||||
|
|
||||||
|
|
@ -61,271 +53,29 @@ class EmblemGeneratorModule {
|
||||||
kinship = 0;
|
kinship = 0;
|
||||||
dominion = 0;
|
dominion = 0;
|
||||||
}
|
}
|
||||||
|
return generateCOA(null, {
|
||||||
let usedPattern: string | null = null;
|
charge: () => {
|
||||||
const usedTinctures: string[] = [];
|
|
||||||
|
|
||||||
const t1 = P(kinship as number)
|
|
||||||
? parent!.t1
|
|
||||||
: this.getTincture("field", usedTinctures, null);
|
|
||||||
if (t1.includes("-")) usedPattern = t1;
|
|
||||||
const coa: Emblem = { t1 };
|
|
||||||
|
|
||||||
const addCharge = P(usedPattern ? 0.5 : 0.93); // 80% for charge
|
|
||||||
const linedOrdinary =
|
|
||||||
(addCharge && P(0.3)) || P(0.5)
|
|
||||||
? parent?.ordinaries && P(kinship as number)
|
|
||||||
? parent.ordinaries[0].ordinary
|
|
||||||
: rw(ordinaries.lined)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const ordinary =
|
|
||||||
(!addCharge && P(0.65)) || P(0.3)
|
|
||||||
? linedOrdinary
|
|
||||||
? linedOrdinary
|
|
||||||
: rw(ordinaries.straight)
|
|
||||||
: null; // 36% for ordinary
|
|
||||||
|
|
||||||
const rareDivided = [
|
|
||||||
"chief",
|
|
||||||
"terrace",
|
|
||||||
"chevron",
|
|
||||||
"quarter",
|
|
||||||
"flaunches",
|
|
||||||
].includes(ordinary!);
|
|
||||||
|
|
||||||
const divisioned = (() => {
|
|
||||||
if (rareDivided) return P(0.03);
|
|
||||||
if (addCharge && ordinary) return P(0.03);
|
|
||||||
if (addCharge) return P(0.3);
|
|
||||||
if (ordinary) return P(0.7);
|
|
||||||
return P(0.995);
|
|
||||||
})();
|
|
||||||
|
|
||||||
const division = (() => {
|
|
||||||
if (divisioned) {
|
|
||||||
if (parent?.division && P((kinship as number) - 0.1))
|
|
||||||
return parent.division.division;
|
|
||||||
return rw(divisions.variants);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (division) {
|
|
||||||
const t = this.getTincture(
|
|
||||||
"division",
|
|
||||||
usedTinctures,
|
|
||||||
P(0.98) ? coa.t1 : null,
|
|
||||||
);
|
|
||||||
coa.division = { division, t };
|
|
||||||
if (divisions[division])
|
|
||||||
coa.division.line =
|
|
||||||
usedPattern || (ordinary && P(0.7))
|
|
||||||
? "straight"
|
|
||||||
: rw(divisions.data[division].line);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ordinary) {
|
|
||||||
coa.ordinaries = [
|
|
||||||
{ ordinary, t: this.getTincture("charge", usedTinctures, coa.t1) },
|
|
||||||
];
|
|
||||||
if (linedOrdinary)
|
|
||||||
coa.ordinaries[0].line =
|
|
||||||
usedPattern || (division && P(0.7)) ? "straight" : rw(lines.variants);
|
|
||||||
if (
|
|
||||||
division &&
|
|
||||||
!addCharge &&
|
|
||||||
!usedPattern &&
|
|
||||||
P(0.5) &&
|
|
||||||
ordinary !== "bordure" &&
|
|
||||||
ordinary !== "orle"
|
|
||||||
) {
|
|
||||||
if (P(0.8)) coa.ordinaries[0].divided = "counter";
|
|
||||||
// 40%
|
|
||||||
else if (P(0.6)) coa.ordinaries[0].divided = "field";
|
|
||||||
// 6%
|
|
||||||
else coa.ordinaries[0].divided = "division"; // 4%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addCharge) {
|
|
||||||
const charge = (() => {
|
|
||||||
if (parent?.charges && P((kinship as number) - 0.1))
|
if (parent?.charges && P((kinship as number) - 0.1))
|
||||||
return parent.charges[0].charge;
|
return parent.charges[0].charge;
|
||||||
if (type && type !== "Generic" && P(0.3)) return rw(typeMapping[type]);
|
if (type && type !== "Generic" && P(0.3)) return rw(typeMapping[type]);
|
||||||
return this.selectCharge(
|
},
|
||||||
ordinary || divisioned ? charges.types : charges.single,
|
division: () => {
|
||||||
);
|
if (parent?.division && P((kinship as number) - 0.1))
|
||||||
})();
|
return parent.division.division;
|
||||||
const chargeDataEntry = charges.data[charge] || {};
|
},
|
||||||
|
ordinary: () => {
|
||||||
let p: string;
|
if (parent?.ordinaries && P(kinship as number))
|
||||||
let t: string;
|
return parent.ordinaries[0].ordinary;
|
||||||
|
},
|
||||||
const ordinaryData = ordinaries.data[ordinary!];
|
tincture: () => {
|
||||||
const tOrdinary = coa.ordinaries ? coa.ordinaries[0].t : null;
|
if (P(kinship as number)) return parent!.t1;
|
||||||
|
},
|
||||||
if (ordinaryData?.positionsOn && P(0.8)) {
|
finalize: (coa: Emblem, config: Record<string, any>) => {
|
||||||
// place charge over ordinary (use tincture of field type)
|
|
||||||
p = rw(ordinaryData.positionsOn);
|
|
||||||
t =
|
|
||||||
!usedPattern && P(0.3)
|
|
||||||
? coa.t1
|
|
||||||
: this.getTincture("charge", [], tOrdinary);
|
|
||||||
} else if (ordinaryData?.positionsOff && P(0.95)) {
|
|
||||||
// place charge out of ordinary (use tincture of ordinary type)
|
|
||||||
p = rw(ordinaryData.positionsOff);
|
|
||||||
t =
|
|
||||||
!usedPattern && P(0.3)
|
|
||||||
? tOrdinary!
|
|
||||||
: this.getTincture("charge", usedTinctures, coa.t1);
|
|
||||||
} else if (divisions.data[division]?.positions) {
|
|
||||||
// place charge in fields made by division
|
|
||||||
p = rw(divisions.data[division].positions);
|
|
||||||
t = this.getTincture(
|
|
||||||
"charge",
|
|
||||||
tOrdinary ? usedTinctures.concat(tOrdinary) : usedTinctures,
|
|
||||||
coa.t1,
|
|
||||||
);
|
|
||||||
} else if (chargeDataEntry.positions) {
|
|
||||||
// place charge-suitable position
|
|
||||||
p = rw(chargeDataEntry.positions);
|
|
||||||
t = this.getTincture("charge", usedTinctures, coa.t1);
|
|
||||||
} else {
|
|
||||||
// place in standard position (use new tincture)
|
|
||||||
p = usedPattern
|
|
||||||
? "e"
|
|
||||||
: charges.conventional[charge]
|
|
||||||
? rw(positions.conventional)
|
|
||||||
: rw(positions.complex);
|
|
||||||
t = this.getTincture(
|
|
||||||
"charge",
|
|
||||||
usedTinctures.concat(tOrdinary!),
|
|
||||||
coa.t1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
chargeDataEntry.natural &&
|
|
||||||
chargeDataEntry.natural !== t &&
|
|
||||||
chargeDataEntry.natural !== tOrdinary
|
|
||||||
)
|
|
||||||
t = chargeDataEntry.natural;
|
|
||||||
|
|
||||||
const item: EmblemCharge = { charge: charge, t, p };
|
|
||||||
const colors = chargeDataEntry.colors || 1;
|
|
||||||
if (colors > 1)
|
|
||||||
item.t2 = P(0.25)
|
|
||||||
? this.getTincture("charge", usedTinctures, coa.t1)
|
|
||||||
: t;
|
|
||||||
if (colors > 2 && item.t2)
|
|
||||||
item.t3 = P(0.5)
|
|
||||||
? this.getTincture("charge", usedTinctures, coa.t1)
|
|
||||||
: t;
|
|
||||||
coa.charges = [item];
|
|
||||||
|
|
||||||
if (p === "ABCDEFGHIJKL" && P(0.95)) {
|
|
||||||
// add central charge if charge is in bordure
|
|
||||||
coa.charges[0].charge = rw(charges.conventional);
|
|
||||||
const chargeNew = this.selectCharge(charges.single);
|
|
||||||
const tNew = this.getTincture("charge", usedTinctures, coa.t1);
|
|
||||||
coa.charges.push({ charge: chargeNew, t: tNew, p: "e" });
|
|
||||||
} else if (P(0.8) && charge === "inescutcheon") {
|
|
||||||
// add charge to inescutcheon
|
|
||||||
const chargeNew = this.selectCharge(charges.types);
|
|
||||||
const t2 = this.getTincture("charge", [], t);
|
|
||||||
coa.charges.push({ charge: chargeNew, t: t2, p, size: 0.5 });
|
|
||||||
} else if (division && !ordinary) {
|
|
||||||
const allowCounter =
|
|
||||||
!usedPattern &&
|
|
||||||
(!coa.division?.line || coa.division.line === "straight");
|
|
||||||
|
|
||||||
// dimidiation: second charge at division basic positions
|
|
||||||
if (
|
|
||||||
P(0.3) &&
|
|
||||||
["perPale", "perFess"].includes(division) &&
|
|
||||||
coa.division?.line === "straight"
|
|
||||||
) {
|
|
||||||
coa.charges[0].divided = "field";
|
|
||||||
if (P(0.95)) {
|
|
||||||
const p2 =
|
|
||||||
p === "e" || P(0.5)
|
|
||||||
? "e"
|
|
||||||
: rw(divisions.data[division].positions);
|
|
||||||
const chargeNew = this.selectCharge(charges.single);
|
|
||||||
const tNew = this.getTincture(
|
|
||||||
"charge",
|
|
||||||
usedTinctures,
|
|
||||||
coa.division!.t,
|
|
||||||
);
|
|
||||||
coa.charges.push({
|
|
||||||
charge: chargeNew,
|
|
||||||
t: tNew,
|
|
||||||
p: p2,
|
|
||||||
divided: "division",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (allowCounter && P(0.4)) coa.charges[0].divided = "counter";
|
|
||||||
// counterchanged, 40%
|
|
||||||
else if (
|
|
||||||
["perPale", "perFess", "perBend", "perBendSinister"].includes(
|
|
||||||
division,
|
|
||||||
) &&
|
|
||||||
P(0.8)
|
|
||||||
) {
|
|
||||||
// place 2 charges in division standard positions
|
|
||||||
const [p1, p2] =
|
|
||||||
division === "perPale"
|
|
||||||
? ["p", "q"]
|
|
||||||
: division === "perFess"
|
|
||||||
? ["k", "n"]
|
|
||||||
: division === "perBend"
|
|
||||||
? ["l", "m"]
|
|
||||||
: ["j", "o"]; // perBendSinister
|
|
||||||
coa.charges[0].p = p1;
|
|
||||||
|
|
||||||
const chargeNew = this.selectCharge(charges.single);
|
|
||||||
const tNew = this.getTincture(
|
|
||||||
"charge",
|
|
||||||
usedTinctures,
|
|
||||||
coa.division!.t,
|
|
||||||
);
|
|
||||||
coa.charges.push({ charge: chargeNew, t: tNew, p: p2 });
|
|
||||||
} else if (["perCross", "perSaltire"].includes(division) && P(0.5)) {
|
|
||||||
// place 4 charges in division standard positions
|
|
||||||
const [p1, p2, p3, p4] =
|
|
||||||
division === "perCross"
|
|
||||||
? ["j", "l", "m", "o"]
|
|
||||||
: ["b", "d", "f", "h"];
|
|
||||||
coa.charges[0].p = p1;
|
|
||||||
|
|
||||||
const c2 = this.selectCharge(charges.single);
|
|
||||||
const t2 = this.getTincture("charge", [], coa.division!.t);
|
|
||||||
|
|
||||||
const c3 = this.selectCharge(charges.single);
|
|
||||||
const t3 = this.getTincture("charge", [], coa.division!.t);
|
|
||||||
|
|
||||||
const c4 = this.selectCharge(charges.single);
|
|
||||||
const t4 = this.getTincture("charge", [], coa.t1);
|
|
||||||
coa.charges.push(
|
|
||||||
{ charge: c2, t: t2, p: p2 },
|
|
||||||
{ charge: c3, t: t3, p: p3 },
|
|
||||||
{ charge: c4, t: t4, p: p4 },
|
|
||||||
);
|
|
||||||
} else if (allowCounter && p.length > 1)
|
|
||||||
coa.charges[0].divided = "counter"; // counterchanged, 40%
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const c of coa.charges) {
|
|
||||||
this.defineChargeAttributes(ordinary, division, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dominions have canton with parent coa
|
// dominions have canton with parent coa
|
||||||
if (P(dominion as number) && parent?.charges) {
|
if (P(dominion as number) && parent?.charges) {
|
||||||
const invert = this.isSameType(parent.t1, coa.t1);
|
const invert = this.isSameType(parent.t1, coa.t1);
|
||||||
const t = invert
|
const t = invert
|
||||||
? this.getTincture("division", usedTinctures, coa.t1)
|
? getTincture(config, "division", config.usedTinctures, coa.t1)
|
||||||
: parent.t1;
|
: parent.t1;
|
||||||
const canton: EmblemOrdinary = { ordinary: "canton", t };
|
const canton: EmblemOrdinary = { ordinary: "canton", t };
|
||||||
|
|
||||||
|
|
@ -344,7 +94,7 @@ class EmblemGeneratorModule {
|
||||||
|
|
||||||
let t2 = invert ? parent.t1 : parent.charges[0].t;
|
let t2 = invert ? parent.t1 : parent.charges[0].t;
|
||||||
if (this.isSameType(t, t2))
|
if (this.isSameType(t, t2))
|
||||||
t2 = this.getTincture("charge", usedTinctures, t);
|
t2 = getTincture(config, "charge", config.usedTinctures, t);
|
||||||
|
|
||||||
if (!coa.charges) coa.charges = [];
|
if (!coa.charges) coa.charges = [];
|
||||||
coa.charges.push({ charge, t: t2, p: "y", size: 0.5 });
|
coa.charges.push({ charge, t: t2, p: "y", size: 0.5 });
|
||||||
|
|
@ -355,71 +105,8 @@ class EmblemGeneratorModule {
|
||||||
coa.ordinaries = [canton];
|
coa.ordinaries = [canton];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return coa;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private selectCharge(set?: Record<string, number>): string {
|
|
||||||
const type = set ? rw(set) : rw(charges.types);
|
|
||||||
return type === "inescutcheon"
|
|
||||||
? "inescutcheon"
|
|
||||||
: rw(charges[type as keyof typeof charges] as Record<string, number>);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select tincture: element type (field, division, charge), used field tinctures, field type to follow RoT
|
|
||||||
private getTincture(
|
|
||||||
element: "field" | "division" | "charge",
|
|
||||||
fields: string[] = [],
|
|
||||||
RoT: string | null,
|
|
||||||
): string {
|
|
||||||
const base = RoT ? (RoT.includes("-") ? RoT.split("-")[1] : RoT) : null;
|
|
||||||
|
|
||||||
let type = rw(tinctures[element]); // metals, colours, stains, patterns
|
|
||||||
if (RoT && type !== "patterns")
|
|
||||||
type = this.getType(base!) === "metals" ? "colours" : "metals"; // follow RoT
|
|
||||||
if (type === "metals" && fields.includes("or") && fields.includes("argent"))
|
|
||||||
type = "colours"; // exclude metals overuse
|
|
||||||
let tincture = rw(
|
|
||||||
tinctures[type as keyof typeof tinctures] as Record<string, number>,
|
|
||||||
);
|
|
||||||
|
|
||||||
while (tincture === base || fields.includes(tincture)) {
|
|
||||||
tincture = rw(
|
|
||||||
tinctures[type as keyof typeof tinctures] as Record<string, number>,
|
|
||||||
);
|
|
||||||
} // follow RoT
|
|
||||||
|
|
||||||
if (type !== "patterns" && element !== "charge") fields.push(tincture); // add field tincture
|
|
||||||
|
|
||||||
if (type === "patterns") {
|
|
||||||
tincture = this.definePattern(tincture, element, fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tincture;
|
|
||||||
}
|
|
||||||
|
|
||||||
private defineChargeAttributes(
|
|
||||||
ordinary: string | null,
|
|
||||||
division: string | null,
|
|
||||||
c: EmblemCharge,
|
|
||||||
): void {
|
|
||||||
// define size
|
|
||||||
c.size = (c.size || 1) * this.getSize(c.p, ordinary, division);
|
|
||||||
|
|
||||||
// clean-up position
|
|
||||||
c.p = [...new Set(c.p)].join("");
|
|
||||||
|
|
||||||
// define orientation
|
|
||||||
if (P(0.02) && charges.data[c.charge]?.sinister) c.sinister = 1;
|
|
||||||
if (P(0.02) && charges.data[c.charge]?.reversed) c.reversed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getType(t: string): string | undefined {
|
|
||||||
const tinc = t.includes("-") ? t.split("-")[1] : t;
|
|
||||||
if (Object.keys(tinctures.metals).includes(tinc)) return "metals";
|
|
||||||
if (Object.keys(tinctures.colours).includes(tinc)) return "colours";
|
|
||||||
if (Object.keys(tinctures.stains).includes(tinc)) return "stains";
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private isSameType(t1: string, t2: string): boolean {
|
private isSameType(t1: string, t2: string): boolean {
|
||||||
|
|
@ -433,113 +120,6 @@ class EmblemGeneratorModule {
|
||||||
return "pattern";
|
return "pattern";
|
||||||
}
|
}
|
||||||
|
|
||||||
private definePattern(
|
|
||||||
pattern: string,
|
|
||||||
element: "field" | "division" | "charge",
|
|
||||||
usedTinctures: string[],
|
|
||||||
): string {
|
|
||||||
let t1: string | null = null;
|
|
||||||
let t2: string | null = null;
|
|
||||||
let size = "";
|
|
||||||
|
|
||||||
// Size selection - must use sequential P() calls to match original behavior
|
|
||||||
if (P(0.1)) size = "-small";
|
|
||||||
// biome-ignore lint/suspicious/noDuplicateElseIf: false positive
|
|
||||||
else if (P(0.1)) size = "-smaller";
|
|
||||||
else if (P(0.01)) size = "-big";
|
|
||||||
else if (P(0.005)) size = "-smallest";
|
|
||||||
|
|
||||||
// apply standard tinctures
|
|
||||||
if (P(0.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {
|
|
||||||
t1 = "azure";
|
|
||||||
t2 = "argent";
|
|
||||||
} else if (P(0.8) && pattern === "ermine") {
|
|
||||||
t1 = "argent";
|
|
||||||
t2 = "sable";
|
|
||||||
} else if (pattern === "pappellony") {
|
|
||||||
if (P(0.2)) {
|
|
||||||
t1 = "gules";
|
|
||||||
t2 = "or";
|
|
||||||
// biome-ignore lint/suspicious/noDuplicateElseIf: false positive
|
|
||||||
} else if (P(0.2)) {
|
|
||||||
t1 = "argent";
|
|
||||||
t2 = "sable";
|
|
||||||
// biome-ignore lint/suspicious/noDuplicateElseIf: false positive
|
|
||||||
} else if (P(0.2)) {
|
|
||||||
t1 = "azure";
|
|
||||||
t2 = "argent";
|
|
||||||
}
|
|
||||||
} else if (pattern === "masoned") {
|
|
||||||
if (P(0.3)) {
|
|
||||||
t1 = "gules";
|
|
||||||
t2 = "argent";
|
|
||||||
// biome-ignore lint/suspicious/noDuplicateElseIf: false positive
|
|
||||||
} else if (P(0.3)) {
|
|
||||||
t1 = "argent";
|
|
||||||
t2 = "sable";
|
|
||||||
} else if (P(0.1)) {
|
|
||||||
t1 = "or";
|
|
||||||
t2 = "sable";
|
|
||||||
}
|
|
||||||
} else if (pattern === "fretty") {
|
|
||||||
if (t2 === "sable" || P(0.35)) {
|
|
||||||
t1 = "argent";
|
|
||||||
t2 = "gules";
|
|
||||||
} else if (P(0.25)) {
|
|
||||||
t1 = "sable";
|
|
||||||
t2 = "or";
|
|
||||||
} else if (P(0.15)) {
|
|
||||||
t1 = "gules";
|
|
||||||
t2 = "argent";
|
|
||||||
}
|
|
||||||
} else if (pattern === "semy")
|
|
||||||
pattern = `${pattern}_of_${this.selectCharge(charges.semy)}`;
|
|
||||||
|
|
||||||
if (!t1 || !t2) {
|
|
||||||
const startWithMetal = P(0.7);
|
|
||||||
t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours);
|
|
||||||
t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals);
|
|
||||||
}
|
|
||||||
|
|
||||||
// division should not be the same tincture as base field
|
|
||||||
if (element === "division") {
|
|
||||||
if (usedTinctures.includes(t1)) t1 = this.replaceTincture(t1);
|
|
||||||
if (usedTinctures.includes(t2)) t2 = this.replaceTincture(t2);
|
|
||||||
}
|
|
||||||
|
|
||||||
usedTinctures.push(t1, t2);
|
|
||||||
return `${pattern}-${t1}-${t2}${size}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private replaceTincture(t: string): string {
|
|
||||||
const type = this.getType(t);
|
|
||||||
let n: string | null = null;
|
|
||||||
while (!n || n === t) {
|
|
||||||
n = rw(tinctures[type] as Record<string, number>);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getSize(
|
|
||||||
p: string,
|
|
||||||
o: string | null = null,
|
|
||||||
d: string | null = null,
|
|
||||||
): number {
|
|
||||||
if (p === "e" && (o === "bordure" || o === "orle")) return 1.1;
|
|
||||||
if (p === "e") return 1.5;
|
|
||||||
if (p === "jln" || p === "jlh") return 0.7;
|
|
||||||
if (p === "abcpqh" || p === "ez" || p === "be") return 0.5;
|
|
||||||
if (["a", "b", "c", "d", "f", "g", "h", "i", "bh", "df"].includes(p))
|
|
||||||
return 0.5;
|
|
||||||
if (["j", "l", "m", "o", "jlmo"].includes(p) && d === "perCross")
|
|
||||||
return 0.6;
|
|
||||||
if (p.length > 10) return 0.18; // >10 (bordure)
|
|
||||||
if (p.length > 7) return 0.3; // 8, 9, 10
|
|
||||||
if (p.length > 4) return 0.4; // 5, 6, 7
|
|
||||||
if (p.length > 2) return 0.5; // 3, 4
|
|
||||||
return 0.7; // 1, 2
|
|
||||||
}
|
|
||||||
|
|
||||||
getShield(culture: number, state?: number): string {
|
getShield(culture: number, state?: number): string {
|
||||||
const emblemShape = document.getElementById(
|
const emblemShape = document.getElementById(
|
||||||
"emblemShape",
|
"emblemShape",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue