separation of script.js
This commit is contained in:
parent
bddec03d22
commit
5d09ad30d7
7 changed files with 1314 additions and 1307 deletions
116
utils.js
Normal file
116
utils.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
function clamp(v, min, max) {
|
||||
return Math.max(min, Math.min(max, v));
|
||||
}
|
||||
function bestBy(items, score) {
|
||||
let best = null;
|
||||
let bestScore = -Infinity;
|
||||
for (const item of items) {
|
||||
const value = score(item);
|
||||
if (value > bestScore) {
|
||||
best = item;
|
||||
bestScore = value;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
function smoothstep(t) {
|
||||
return t * t * (3 - 2 * t);
|
||||
}
|
||||
const traitFields = [
|
||||
["mobility", traits => traits.mobility, 0.02, 1, 1, 1],
|
||||
["resourceAttraction", traits => traits.resourceAttraction, 0.05, 1.2, 1, 1],
|
||||
["assimilation", traits => traits.assimilation, 0, 0.75, 1, 1],
|
||||
["ethnocentrism", traits => traits.ethnocentrism, 0, 1.2, 1, 1],
|
||||
["reproductionThreshold", traits => traits.reproductionThreshold, 12, 48, 16, 1 / 48],
|
||||
["sedentary", traits => traits.sedentary, 0, 1, 1, 1]
|
||||
];
|
||||
function mutateTraits(traits, rng, amount) {
|
||||
return Object.fromEntries(traitFields.map(([key, get, min, max, mutationScale]) => [
|
||||
key,
|
||||
clamp(get(traits) + rng.range(-amount * mutationScale, amount * mutationScale), min, max)
|
||||
]));
|
||||
}
|
||||
function blendTraits(a, b, t) {
|
||||
return Object.fromEntries(traitFields.map(([key, get]) => [key, lerp(get(a), get(b), t)]));
|
||||
}
|
||||
function emptyTraitSums() {
|
||||
return Object.fromEntries(traitFields.map(([key]) => [key, 0]));
|
||||
}
|
||||
function addTraits(sum, traits) {
|
||||
for (const [key, get, , , , sumScale] of traitFields) sum[key] += get(traits) * sumScale;
|
||||
}
|
||||
function averageTraits(sum, count) {
|
||||
return Object.fromEntries(traitFields.map(([key, , , , , sumScale]) => [key, sum[key] / count / sumScale]));
|
||||
}
|
||||
function compositionTotal(composition) {
|
||||
return [...composition.values()].reduce((sum, value) => sum + value, 0);
|
||||
}
|
||||
function addBirthsToComposition(composition, births, rng = null) {
|
||||
const entries = [...composition.entries()];
|
||||
const total = entries.reduce((sum, [, value]) => sum + value, 0);
|
||||
if (!total || births <= 0) return;
|
||||
|
||||
for (let n = 0; n < births; n++) {
|
||||
let r = (rng ? rng.next() : Math.random()) * total;
|
||||
for (const [id, count] of entries) {
|
||||
r -= count;
|
||||
if (r <= 0) {
|
||||
composition.set(id, (composition.get(id) || 0) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function removeFromComposition(composition, loss) {
|
||||
let remaining = loss;
|
||||
const total = compositionTotal(composition);
|
||||
if (!total) return;
|
||||
for (const [id, count] of [...composition]) {
|
||||
const removed = Math.min(count, Math.ceil(loss * (count / total)));
|
||||
composition.set(id, Math.max(0, count - removed));
|
||||
remaining -= removed;
|
||||
if (composition.get(id) <= 0) composition.delete(id);
|
||||
if (remaining <= 0) break;
|
||||
}
|
||||
}
|
||||
function dominantComposition(composition) {
|
||||
let bestId = null;
|
||||
let bestCount = 0;
|
||||
for (const [id, count] of composition) {
|
||||
if (count > bestCount) {
|
||||
bestId = id;
|
||||
bestCount = count;
|
||||
}
|
||||
}
|
||||
return bestId;
|
||||
}
|
||||
function traitDistance(a, b) {
|
||||
return traitFields.reduce((sum, [, get, , , , distanceScale]) => sum + Math.abs(get(a) - get(b)) * distanceScale, 0);
|
||||
}
|
||||
function hslToRgb(h, s, l) {
|
||||
const hue = (p, q, t) => {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||
if (t < 1 / 2) return q;
|
||||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
const p = 2 * l - q;
|
||||
return [
|
||||
Math.round(hue(p, q, h + 1 / 3) * 255),
|
||||
Math.round(hue(p, q, h) * 255),
|
||||
Math.round(hue(p, q, h - 1 / 3) * 255)
|
||||
];
|
||||
}
|
||||
function mix(a, b, t) {
|
||||
return [
|
||||
Math.round(lerp(a[0], b[0], t)),
|
||||
Math.round(lerp(a[1], b[1], t)),
|
||||
Math.round(lerp(a[2], b[2], t))
|
||||
];
|
||||
}
|
||||
function lerp(a, b, t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue