diff --git a/js/hellsim.js b/js/hellsim.js
index 6ae1a58..7fde10f 100644
--- a/js/hellsim.js
+++ b/js/hellsim.js
@@ -85,6 +85,7 @@ function InitStats(params) {
gunGems: 0,
gateGems: 0,
compactorGems: 0,
+ curiousGems: 0,
patrolKills: 0,
droneKills: 0,
totalPreFightThreat: 0,
@@ -194,7 +195,8 @@ function SimResults() {
", Forge: " + (stats.forgeGems / hours).toFixed(2) +
", Gate Turrets: " + (stats.gateGems / hours).toFixed(2) +
(params.soul_compactor ? ", Compactor: " + (stats.compactorGems / hours).toFixed(2) : "") +
- ", Total: " + ((stats.patrolGems + stats.surveyorGems + stats.gunGems + stats.forgeGems + stats.gateGems + stats.compactorGems) / hours).toFixed(2) +
+ (params.curious ? ", Curious: " + (stats.curiousGems / hours).toFixed(2) : "") +
+ ", Total: " + ((stats.patrolGems + stats.surveyorGems + stats.gunGems + stats.forgeGems + stats.gateGems + stats.compactorGems + stats.curiousGems) / hours).toFixed(2) +
"\n");
LogResult(stats, "Encounters: " + stats.patrolEncounters +
", per hour: " + (stats.patrolEncounters / hours).toFixed(1) +
@@ -817,6 +819,8 @@ function ConvertSave(save) {
$('#banana')[0].checked = save.race['banana'] ? true : false;
$('#rage')[0].checked = save.city['ptrait'] && save.city.ptrait.includes('rage') ? true : false;
$('#elliptical')[0].checked = save.city['ptrait'] && save.city.ptrait.includes('elliptical') ? true : false;
+ $('#flare')[0].checked = save.city['ptrait'] && save.city.ptrait.includes('flare') ? true : false;
+ $('#ancient_ruins')[0].checked = save.race['ancient_ruins'] ? true : false;
$('#rejuvenated')[0].checked = save.race['rejuvenated'] ? true : false;
let technophobe_l = save.stats.achieve['technophobe'] && save.stats.achieve.technophobe.l;
let technophobe_additional = 0;
@@ -830,6 +834,7 @@ function ConvertSave(save) {
$('#bureaucratic_efficiency')[0].checked = save['genes'] && save.genes['governor'] && save.genes.governor >= 3 ? true : false;
$('#aquatic')[0].checked = (save.race.species == "sharkin" || save.race.species == "octigoran");
+ $('#aggressive')[0].value = save.race['aggressive'] || 0;
$('#apexPredator')[0].value = save.race['apex_predator'] || 0;
$('#astrologer')[0].value = save.race['astrologer'] || 0;
$('#armored')[0].value = save.race['armored'] || 0;
@@ -842,6 +847,7 @@ function ConvertSave(save) {
$('#chameleon')[0].value = save.race['chameleon'] || 0;
$('#chicken')[0].value = save.race['chicken'] || 0;
$('#claws')[0].value = save.race['claws'] || 0;
+ $('#curious')[0].value = save.race['curious'] || 0;
$('#diverse')[0].value = save.race['diverse'] || 0;
$('#elemental')[0].value = save.race['elemental'] || 0;
$('#elusive')[0].value = save.race['elusive'] || 0;
@@ -864,6 +870,7 @@ function ConvertSave(save) {
$('#rhinoRage')[0].value = save.race['rage'] || 0;
$('#regenerative')[0].value = save.race['regenerative'] || 0;
$('#revive')[0].value = save.race['revive'] || 0;
+ $('#rogue')[0].value = save.race['rogue'] || 0;
$('#scales')[0].value = save.race['scales'] || 0;
$('#slaver')[0].value = save.race['slaver'] || 0;
$('#slow')[0].value = save.race['slow'] || 0;
diff --git a/js/worker.js b/js/worker.js
index 08768da..5eef1d6 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -748,16 +748,45 @@ function Events(params, sim, stats) {
"inspiration",
"motivation",
"surge",
- "terrorist",
- "ruins"
+ "terrorist"
];
if (!(params.kindling || params.smoldering || params.evil || params.aquatic)) {
events.push("fire");
}
+ if (params.flare) {
+ events.push("flare");
+ }
+ /* TODO: Witch crusade? */
+ if (params.ancient_ruins) {
+ events.push("ruins");
+ }
if (params.slaver) {
events.push("slave1", "slave2", "slave3");
}
+ if (params.government == "republic") {
+ events.push("protest");
+ }
+ if (params.governor == "media") {
+ events.push("scandal");
+ }
+ /* TODO: maybe?
+ if (params.miners) {
+ events.push("mine_collapse");
+ }
+ */
+ if (params.rogue) {
+ events.push("klepto");
+ }
+ if (params.chicken) {
+ events.push("chicken_feast");
+ }
+ if (params.aggressive) {
+ events.push("brawl");
+ }
+ if (params.curious) {
+ events.push("m_curious");
+ }
/* Remove the last event that occurred from the list so that the same event can't happen twice in a row */
let lastIdx = events.indexOf(sim.lastEvent);
@@ -794,6 +823,10 @@ function Events(params, sim, stats) {
LogResult(stats, TimeStr(sim) + " - Terrorist attack: " + wounded + " wounded, " + killed + " killed.\n");
}
}
+ } else if (event == "m_curious") {
+ if (Rand(0, 25) == 0) {
+ stats.curiousGems++;
+ }
} /* else, irrelevant event */
sim.lastEvent = event;
From c21215a2e5c8273a21cb261d1594522a60c4e148 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Sat, 31 May 2025 14:42:38 -0700
Subject: [PATCH 54/65] Implementing current sort-of-broken revive trait
behavior
---
js/worker.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/js/worker.js b/js/worker.js
index 5eef1d6..a7afd80 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -487,7 +487,10 @@ function BloodWar(params, sim, stats) {
if (params.revive) {
let reviveDivisor = TraitSelect(params.revive, 4, 4, 4, 3, 2, 2, 2);
let reviveMax = soldiersKilled / reviveDivisor + 0.25;
- let revived = Math.round(Math.random() * reviveMax);
+ /* Yes, the argument is not an integer. This is wacky in-game due to refactoring.
+ It's a pretty devastating nerf in practice. See:
+ https://github.com/pmotschmann/Evolve/issues/1479 */
+ let revived = Rand(0, reviveMax);
sim.soldiers += revived;
stats.soldiersRevived += revived;
}
From e264ee2ae23c73980f8b0c721891600a3054172c Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Sat, 31 May 2025 14:57:51 -0700
Subject: [PATCH 55/65] Terror attack wasn't wounding the right number
---
js/worker.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/worker.js b/js/worker.js
index a7afd80..e7fbfa9 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -813,7 +813,7 @@ function Events(params, sim, stats) {
/* Terrorist attack or enemy raid. Equivalent for our purposes here */
if (params.terrorists) {
let killed = Rand(0, sim.wounded);
- let wounded = Rand(sim.wounded, sim.soldiers);
+ let wounded = Rand(0, sim.soldiers - sim.wounded);
sim.soldiers -= killed;
stats.soldiersKilled += killed;
From b7ca7578c9a28ac447cc46a9b12fa6e4165d161a Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Sat, 31 May 2025 15:00:33 -0700
Subject: [PATCH 56/65] Instincts help against terror attack
---
js/worker.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/js/worker.js b/js/worker.js
index e7fbfa9..3d3ba8a 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -815,6 +815,11 @@ function Events(params, sim, stats) {
let killed = Rand(0, sim.wounded);
let wounded = Rand(0, sim.soldiers - sim.wounded);
+ if (params.instincts) {
+ killed = Math.round(killed / 2);
+ wounded = Math.round(wounded / 2);
+ }
+
sim.soldiers -= killed;
stats.soldiersKilled += killed;
sim.wounded += wounded;
From efa0cc18a2ae8726157b77d78f5bb9d76f667269 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Sat, 31 May 2025 15:53:03 -0700
Subject: [PATCH 57/65] Training update -- allow multiple per tick, save
fraction, UI respects hyper/slow rank
---
js/hellsim.js | 26 +++++++++---------------
js/worker.js | 56 ++++++++++++++++++++++++++++-----------------------
2 files changed, 40 insertions(+), 42 deletions(-)
diff --git a/js/hellsim.js b/js/hellsim.js
index 7fde10f..044c940 100644
--- a/js/hellsim.js
+++ b/js/hellsim.js
@@ -486,7 +486,7 @@ function HandleSimStopped(stats) {
}
*/
function UpdateUIStrings(e) {
- ratingStr = "";
+ let ratingStr = "";
if (gParams.cautious) {
ratingStr += "~ ";
}
@@ -509,17 +509,13 @@ function UpdateUIStrings(e) {
}
$('#fortressRating').html(ratingStr);
- /* Get the training time, then round up to next tick and convert to seconds */
- trainingTime = e.data.trainingTime;
- trainingTime = Math.ceil(trainingTime) / 4;
- if (gParams.hyper) {
- trainingTime *= 0.95;
- }
- if (gParams.slow) {
- trainingTime *= 1.1;
- }
- let trainingRate = 3600 / trainingTime;
- let trainingStr = trainingTime.toFixed(2) + "sec " + trainingRate.toFixed(1);
+ /* Get the training rate in progress (%) per tick, convert to soldiers per hour */
+ let trainingRate = e.data.trainingRate;
+ let tickLength = e.data.tickLength; /* milliseconds */
+
+ let soldierPerHour = (trainingRate / 100) * (1000 / tickLength) * 3600;
+ let trainingTime = (tickLength / 1000) * (100 / trainingRate);
+ let trainingStr = trainingTime.toFixed(2) + "sec " + soldierPerHour.toFixed(1);
var mercRate;
switch (gParams.hireMercs) {
case 'script':
@@ -576,11 +572,7 @@ function UpdateUIStrings(e) {
}
function OnChange() {
- var patrolRating;
- var patrolRatingDroids;
- var fortressRating;
- var trainingTime;
-
+
GetParams();
/* If cpuThreads is invalid, set it to default based on user hardware.
diff --git a/js/worker.js b/js/worker.js
index 3d3ba8a..f7847cc 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -18,7 +18,8 @@ var gStop = false;
fortressRating - Fortress combat rating
patrolRating - Normal patrol combat rating
patrolRatingDroids - Droid-augmented patrol combat rating
- trainingTime - Soldier training time in ticks per soldier
+ tickLength - Length of a tick in milliseconds
+ trainingRate - Training progress (%) per tick
forgeSoldiers - Number of soldiers required to run the Soul Forge
'progress' - Update for progress bar
increment - Progress increment as a percentage of the sim
@@ -47,13 +48,7 @@ onmessage = function(e) {
}
function SimStart(id, simId, params, stats) {
- var tickLength = 250;
- if (params.hyper) {
- tickLength *= TraitSelect(params.hyper, 0.99, 0.98, 0.97, 0.95, 0.94, 0.93, 0.92);
- }
- if (params.slow) {
- tickLength *= TraitSelect(params.slow, 1.14, 1.13, 1.12, 1.1, 1.08, 1.06, 1.05);
- }
+ let tickLength = TickLength(params);
var sim = {
id: id,
simId: simId,
@@ -70,7 +65,7 @@ function SimStart(id, simId, params, stats) {
patrolRatingDroids: 0,
wounded: 0,
trainingProgress: 0,
- trainingTime: 0,
+ trainingRate: 0,
surveyors: params.surveyors,
carRepair: 0,
siegeOdds: 999,
@@ -100,7 +95,7 @@ function SimStart(id, simId, params, stats) {
/* Calculate patrol rating and training rate ahead of time for efficiency */
sim.patrolRating = ArmyRating(params, false, params.patrolSize);
sim.patrolRatingDroids = ArmyRating(params, false, params.patrolSize + DroidSize(params));
- sim.trainingTime = TrainingTime(params);
+ sim.trainingRate = TrainingRate(params);
LogResult(stats, " -- Sim " + sim.simId.toString().padStart(Math.floor(Math.log10(params.sims)) + 1, 0) + " --\n");
@@ -123,13 +118,15 @@ function ProvideInfo (params) {
var fortressRating;
var patrolRating;
var patrolRatingDroids;
- var trainingTime;
+ var tickLength;
+ var trainingRate;
var forgeSoldiers;
fortressRating = FortressRating(params, false);
patrolRating = ArmyRating(params, false, params.patrolSize);
patrolRatingDroids = ArmyRating(params, false, params.patrolSize + DroidSize(params));
- trainingTime = TrainingTime(params);
+ tickLength = TickLength(params);
+ trainingRate = TrainingRate(params);
forgeSoldiers = ForgeSoldiers(params);
self.postMessage({
@@ -137,7 +134,8 @@ function ProvideInfo (params) {
fortressRating: fortressRating,
patrolRating: patrolRating,
patrolRatingDroids: patrolRatingDroids,
- trainingTime: trainingTime,
+ tickLength: tickLength,
+ trainingRate: trainingRate,
forgeSoldiers: forgeSoldiers
});
}
@@ -855,15 +853,14 @@ function TrainSoldiers(params, sim, stats) {
return;
}
- sim.trainingProgress += 100 / sim.trainingTime;
+ sim.trainingProgress += sim.trainingRate;
if (sim.trainingProgress >= 100) {
- sim.soldiers++;
- stats.soldiersTrained++;
- sim.trainingProgress = 0;
- if (sim.hellSoldiers < sim.maxHellSoldiers) {
- sim.hellSoldiers++;
- }
+ let trained = Math.floor(sim.trainingProgress / 100);
+ sim.soldiers += trained;
+ stats.soldiersTrained += trained;
+ sim.trainingProgress -= trained * 100;
+ sim.hellSoldiers = Math.min(sim.hellSoldiers + trained, sim.maxHellSoldiers);
}
}
@@ -1119,8 +1116,19 @@ function PatrolCasualties(params, sim, stats, demons, ambush) {
return dead;
}
-/* Returns soldier training time in ticks, not rounded */
-function TrainingTime(params) {
+function TickLength(params) {
+ let tickLength = 250;
+ if (params.hyper) {
+ tickLength *= TraitSelect(params.hyper, 0.99, 0.98, 0.97, 0.95, 0.94, 0.93, 0.92);
+ }
+ if (params.slow) {
+ tickLength *= TraitSelect(params.slow, 1.14, 1.13, 1.12, 1.1, 1.08, 1.06, 1.05);
+ }
+ return tickLength;
+}
+
+/* Returns soldier training rate in progress points (%) per tick */
+function TrainingRate(params) {
var bootCampBonus;
bootCampBonus = params.vrTraining == true ? 0.08 : 0.05;
@@ -1155,9 +1163,7 @@ function TrainingTime(params) {
/* Convert to progress per tick (as does the game) */
rate *= 0.25;
- /* Convert to ticks per soldier */
- rate /= 100.0;
- return 1.0/rate;
+ return rate;
}
function TrainingBonus(value, params) {
From f272e2cc715ebe774c67edfe4a3a38c349e9e38d Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 15:51:24 -0700
Subject: [PATCH 58/65] High pop updates
---
js/hellsim.js | 26 +++++++++++++++++++++++++-
js/worker.js | 25 ++++++++++++++++++-------
2 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/js/hellsim.js b/js/hellsim.js
index 044c940..084dae1 100644
--- a/js/hellsim.js
+++ b/js/hellsim.js
@@ -959,11 +959,35 @@ function ConvertSave(save) {
defenders = 0;
garrison = save.civic.garrison.max;
}
+ let popFactor = 1;
+ if (save.race['high_pop']) {
+ switch(save.race.high_pop) {
+ case 0.1:
+ case 0.25:
+ popFactor = 2;
+ break;
+ case 0.5:
+ popFactor = 3;
+ break;
+ case 1:
+ popFactor = 4;
+ break;
+ case 2:
+ popFactor = 5;
+ break;
+ case 3:
+ popFactor = 6;
+ break;
+ case 4:
+ popFactor = 7;
+ break;
+ }
+ }
$('#patrols')[0].value = patrols;
$('#patrolSize')[0].value = patrolSize;
$('#defenders')[0].value = defenders;
$('#garrison')[0].value = garrison;
- $('#surveyors')[0].value = save.portal.carport ? save.portal.carport.count : 0;
+ $('#surveyors')[0].value = save.portal.carport ? popFactor * save.portal.carport.count : 0;
$('#repairDroids')[0].value = save.portal.repair_droid ? save.portal.repair_droid.count : 0;
$('#turrets')[0].value = save.portal.turret ? save.portal.turret.on : 0;
$('#beacons')[0].value = save.portal.attractor ? save.portal.attractor.on : 0;
diff --git a/js/worker.js b/js/worker.js
index f7847cc..70e56fc 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -179,10 +179,13 @@ function SimRun(sim, params, stats) {
/* Random events, which could mean a demon surge influx */
Events(params, sim, stats);
- /* 1/4 chance to reduce merc counter */
+ /* 1/3 chance to reduce merc counter -- we assume Signing Bonus was researched. */
if (sim.mercCounter > 0) {
- if (Rand(0,3) == 0) {
- sim.mercCounter--;
+ let rolls = PopFactor(params);
+ for (let i = 0; i < rolls && sim.mercCounter > 0; i++) {
+ if (Rand(0,3) == 0) {
+ sim.mercCounter--;
+ }
}
}
}
@@ -612,9 +615,11 @@ function BloodWar(params, sim, stats) {
if (params.shieldGen) {
divisor += 250;
}
- let danger = sim.threat / divisor;
- let exposure = Math.min(10, sim.surveyors);
- let risk = 10 - Rand(0, exposure+1);
+ let popfactor = PopFactor(params);
+ let danger = popfactor * (sim.threat / divisor);
+ let max_risk = popfactor * 10;
+ let exposure = Math.min(max_risk, sim.surveyors);
+ let risk = max_risk - Rand(0, exposure+1);
if (danger > risk) {
let cap = Math.round(danger);
@@ -1012,6 +1017,9 @@ function HealSoldiers(params, sim, stats) {
healCredits += Math.floor(3 * Fathom(params, params.mantis_thralls));
}
}
+ if (params.highPop) {
+ healCredits *= TraitSelect(params.HighPop, 1.2, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5);
+ }
if (params.governor == "sports") {
healCredits *= 1.5;
}
@@ -1043,8 +1051,11 @@ function RepairSurveyors(params, sim, stats) {
let repair = 180;
if (params.repairDroids > 0) {
repair *= 0.95 ** params.repairDroids;
- repair = Math.round(repair);
}
+ if (params.highPop) {
+ repair /= TraitSelect(params.HighPop, 1.2, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5);
+ }
+ repair = Math.round(repair);
sim.carRepair++;
if (sim.carRepair >= repair) {
From b96ea963ef21b0fc499c68775aab0d6797342731 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 15:53:04 -0700
Subject: [PATCH 59/65] Fix Lamentis healing bonus
---
js/worker.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/worker.js b/js/worker.js
index 70e56fc..d4555d6 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -993,7 +993,7 @@ function HealSoldiers(params, sim, stats) {
healCredits = params.bootCamps;
}
if (params.rejuvenated && params.lamentis) {
- hc += params.lamentis;
+ healCredits += params.lamentis;
}
if (params.astrology == "cancer") {
healCredits = Math.max(0, healCredits + Math.round((params.astroWish ? 8 : 5) * AstroMod(params)));
From ebb40b0b11748e51e8718099ebe3cabe05b57e16 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 15:55:15 -0700
Subject: [PATCH 60/65] Fix repair droid bonus to surveyors
---
js/worker.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/worker.js b/js/worker.js
index d4555d6..ea15e3c 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -1050,7 +1050,7 @@ function RepairSurveyors(params, sim, stats) {
}
let repair = 180;
if (params.repairDroids > 0) {
- repair *= 0.95 ** params.repairDroids;
+ repair *= 0.92 ** params.repairDroids;
}
if (params.highPop) {
repair /= TraitSelect(params.HighPop, 1.2, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5);
From 49dce9761935323ada589f51b9980b1c0ade41e5 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 16:28:21 -0700
Subject: [PATCH 61/65] New death stats
---
js/hellsim.js | 4 ++++
js/worker.js | 20 +++++++++++++++-----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/js/hellsim.js b/js/hellsim.js
index 084dae1..0e65bc4 100644
--- a/js/hellsim.js
+++ b/js/hellsim.js
@@ -104,6 +104,8 @@ function InitStats(params) {
totalWounded: 0,
maxWounded: 0,
ambushDeaths: 0,
+ woundedDeaths: 0,
+ noDroidDeaths: 0,
minReserves: params.garrison + params.defenders,
surges: 0,
sieges: 0,
@@ -221,6 +223,8 @@ function SimResults() {
LogResult(stats,
", per bloodwar: " + (stats.soldiersKilled / stats.bloodWars).toFixed(3) +
", in ambushes: " + (stats.ambushDeaths / stats.soldiersKilled * 100).toFixed(1) + "%" +
+ ", in wounded patrols: " + (stats.woundedDeaths / stats.soldiersKilled * 100).toFixed(1) + "%" +
+ ", with no droid: " + (stats.noDroidDeaths / stats.soldiersKilled * 100).toFixed(1) + "%" +
"\n");
if (params.hireMercs != "off") {
LogResult(stats,
diff --git a/js/worker.js b/js/worker.js
index ea15e3c..09568f6 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -399,20 +399,24 @@ function BloodWar(params, sim, stats) {
/* Encounter */
stats.patrolEncounters++;
+ let droid = false;
+ if (droids > 0) {
+ droid = true;
+ droids--;
+ }
+
var patrolRating;
/* If no wounded, use alread-calculated patrol rating to save time */
if (wounded == 0) {
- if (droids > 0) {
+ if (droid) {
patrolRating = sim.patrolRatingDroids;
- droids--;
} else {
patrolRating = sim.patrolRating;
}
} else {
let patrolSize = params.patrolSize;
- if (droids > 0) {
+ if (droid) {
patrolSize += DroidSize(params);
- droids--;
}
patrolRating = ArmyRating(params, sim, patrolSize, wounded);
}
@@ -455,7 +459,13 @@ function BloodWar(params, sim, stats) {
let kills = patrolRating;
if (kills < demons) {
/* Suffer casualties if the patrol didn't kill all of the demons */
- soldiersKilled += PatrolCasualties(params, sim, stats, (demons - kills), false);
+ let dead = PatrolCasualties(params, sim, stats, (demons - kills), false);
+ soldiersKilled += dead;
+ if (wounded > 0) {
+ stats.woundedDeaths += dead;
+ } else if (!droid) {
+ stats.noDroidDeaths += dead;
+ }
} else {
kills = demons;
}
From 17e962e450c9f3e1761947ba8a4558b84e423d73 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 16:49:24 -0700
Subject: [PATCH 62/65] Marginal encounter rate
---
js/hellsim.js | 2 ++
js/worker.js | 3 +++
2 files changed, 5 insertions(+)
diff --git a/js/hellsim.js b/js/hellsim.js
index 0e65bc4..9bb7803 100644
--- a/js/hellsim.js
+++ b/js/hellsim.js
@@ -97,6 +97,7 @@ function InitStats(params) {
bloodWars: 0,
patrolEncounters: 0,
skippedEncounters: 0,
+ marginalEncounters: 0,
ambushes: 0,
soldiersTrained: 0,
soldiersKilled: 0,
@@ -203,6 +204,7 @@ function SimResults() {
LogResult(stats, "Encounters: " + stats.patrolEncounters +
", per hour: " + (stats.patrolEncounters / hours).toFixed(1) +
", per bloodwar: " + (stats.patrolEncounters / stats.bloodWars).toFixed(3) +
+ ", marginal: " + (stats.marginalEncounters / stats.bloodWars * 100).toFixed(2) + "%" +
", skipped: " + (stats.skippedEncounters / (stats.skippedEncounters + stats.patrolEncounters) * 100).toFixed(2) + "%" +
"\n");
LogResult(stats, "Patrol kills per gem: " + (stats.patrolKills / stats.patrolGems).toFixed(2) +
diff --git a/js/worker.js b/js/worker.js
index 09568f6..8132fcf 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -398,6 +398,9 @@ function BloodWar(params, sim, stats) {
if (Rand(0, sim.threat) >= Rand(0, 999)) {
/* Encounter */
stats.patrolEncounters++;
+ if (i + 1 == sim.patrols) {
+ stats.marginalEncounters++;
+ }
let droid = false;
if (droids > 0) {
From 5a2f323bb42269ae91082371f0a5883b751c0a9e Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 17:40:18 -0700
Subject: [PATCH 63/65] Re-add army rating rounding where appropriate (not
forge)
---
js/worker.js | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/js/worker.js b/js/worker.js
index 8132fcf..f9fa054 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -93,8 +93,8 @@ function SimStart(id, simId, params, stats) {
sim.maxHellSoldiers += forgeSoldiers;
}
/* Calculate patrol rating and training rate ahead of time for efficiency */
- sim.patrolRating = ArmyRating(params, false, params.patrolSize);
- sim.patrolRatingDroids = ArmyRating(params, false, params.patrolSize + DroidSize(params));
+ sim.patrolRating = Math.round(ArmyRating(params, false, params.patrolSize));
+ sim.patrolRatingDroids = Math.round(ArmyRating(params, false, params.patrolSize + DroidSize(params)));
sim.trainingRate = TrainingRate(params);
LogResult(stats, " -- Sim " + sim.simId.toString().padStart(Math.floor(Math.log10(params.sims)) + 1, 0) + " --\n");
@@ -123,8 +123,8 @@ function ProvideInfo (params) {
var forgeSoldiers;
fortressRating = FortressRating(params, false);
- patrolRating = ArmyRating(params, false, params.patrolSize);
- patrolRatingDroids = ArmyRating(params, false, params.patrolSize + DroidSize(params));
+ patrolRating = Math.round(ArmyRating(params, false, params.patrolSize));
+ patrolRatingDroids = Math.round(ArmyRating(params, false, params.patrolSize + DroidSize(params)));
tickLength = TickLength(params);
trainingRate = TrainingRate(params);
forgeSoldiers = ForgeSoldiers(params);
@@ -371,8 +371,8 @@ function BloodWar(params, sim, stats) {
let needPity = true;
/* Update patrol rating if cautious/tusked, for random weather */
if (params.cautious || params.tusk) {
- sim.patrolRating = ArmyRating(params, sim, params.patrolSize);
- sim.patrolRatingDroids = ArmyRating(params, sim, params.patrolSize + DroidSize(params));
+ sim.patrolRating = Math.round(ArmyRating(params, sim, params.patrolSize));
+ sim.patrolRatingDroids = Math.round(ArmyRating(params, sim, params.patrolSize + DroidSize(params)));
}
let patrolWounds = 0;
let extraWounds = 0;
@@ -421,7 +421,7 @@ function BloodWar(params, sim, stats) {
if (droid) {
patrolSize += DroidSize(params);
}
- patrolRating = ArmyRating(params, sim, patrolSize, wounded);
+ patrolRating = Math.round(ArmyRating(params, sim, patrolSize, wounded));
}
let minDemons = Math.floor(sim.threat / 50);
@@ -1487,7 +1487,7 @@ function FortressRating(params, sim) {
break;
}
- return ArmyRating(params, sim, defenders, wounded) + params.turrets * turretRating;
+ return Math.round(ArmyRating(params, sim, defenders, wounded)) + params.turrets * turretRating;
}
function ForgeSoldiers(params) {
From cb6bd6dffd543922649246c8e03f40c3e7ade363 Mon Sep 17 00:00:00 2001
From: maryrivlet <107000523+maryrivlet@users.noreply.github.com>
Date: Wed, 4 Jun 2025 17:49:14 -0700
Subject: [PATCH 64/65] Update version text
---
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.html b/index.html
index acac6f4..86538e9 100644
--- a/index.html
+++ b/index.html
@@ -20,7 +20,7 @@
Evolve Hell Simulator
-
+