Files
Battle-for-Tismo/tests/resource_efficiency_test.js
T
adrien 71dad18e8d Let central banks work their reserves and cleared the landlocked famines
Central banks now redeem the national money foreign banks hold, sell reserves to defend a weak rate, and cover part of strategic imports from reserves. Five repeatable technologies raise each commodity's output per unit of energy. Hostile troops on a road or sea lane sever trade, power and unit supply. Middlemen buy food to resell to neighbours at a markup, and starving regions buy before those topping up their buffers, which clears the landlocked famines. The economic map's trade graph gains a colour legend.
2026-09-22 15:28:11 +02:00

115 lines
4.3 KiB
JavaScript

import { TestCase } from "./framework/test_case.js";
import { smallState } from "./framework/helpers.js";
import { key } from "../shared/hex.js";
import {
RESOURCE_IDS,
RESOURCE_EFFICIENCY_EFFECT,
TECHNOLOGIES,
} from "../shared/data.js";
import { producerEnergyPerDay } from "../shared/resources.js";
// Puts a resource building on the first free land tile of `civ`.
function placeProducer(state, id, civ = 0) {
for (const coords of state._territoryByCiv.get(civ) || []) {
if (state.cityAt(coords)) continue;
if (!state._isLand(coords)) continue;
const k = key(coords.x, coords.y);
if (state.tileImprovements.has(k)) continue;
state.tileImprovements.set(k, id);
state.tileImprovementOwner.set(k, civ);
state.tileImprovementHp.set(k, 1000);
state._ensureResourceStock(k);
state._ensureBuildingAgent(k);
return { coords, k };
}
return null;
}
// Studies one level of a repeatable technology for a nation.
function research(state, civ, id) {
const index = state.technologies.findIndex((tech) => tech.id === id);
state.researched.get(civ).add(index);
const counts = state.repeatCounts.get(civ);
counts.set(id, (counts.get(id) || 0) + 1);
state._touchModifiers();
}
export class ResourceEfficiencyDataTest extends TestCase {
test_there_is_exactly_one_efficiency_technology_per_resource() {
for (const resource of RESOURCE_IDS) {
const stat = RESOURCE_EFFICIENCY_EFFECT[resource];
const matching = TECHNOLOGIES.filter(
(tech) => (tech.effects || []).some((e) => e.stat === stat)
);
this.assertSize(matching, 1, `one technology raises ${resource} output per input`);
this.assertTrue(matching[0].repeatable, `${resource} efficiency is repeatable`);
}
}
}
export class ResourceEfficiencyModelTest extends TestCase {
test_efficiency_is_zero_until_the_technology_is_researched() {
const state = smallState();
this.assertApprox(state.resourceEfficiency(0, "steel"), 0);
research(state, 0, "advanced_metallurgy");
this.assertApprox(state.resourceEfficiency(0, "steel"), 0.05);
research(state, 0, "advanced_metallurgy");
this.assertApprox(state.resourceEfficiency(0, "steel"), 0.10, 1e-9);
this.assertApprox(state.resourceEfficiency(1, "steel"), 0, 1e-9, "research is national");
}
test_steel_efficiency_cuts_the_mill_s_energy_draw() {
const state = smallState();
const placed = placeProducer(state, "steel_mill");
const components = state._resourceLandComponents();
const componentId = components.get(placed.k);
const draw = () => state._buildEnergyLedger(components).get(componentId).converters
.find((entry) => entry.k === placed.k).amount;
const before = draw();
this.assertGreater(before, 0);
research(state, 0, "advanced_metallurgy");
const after = draw();
this.assertApprox(before / after, 1.05, 1e-6, "the same steel costs 5% less power");
}
test_energy_efficiency_cuts_the_plant_s_fuel() {
const state = smallState();
const placed = placeProducer(state, "coal_power_plant");
const components = state._resourceLandComponents();
const componentId = components.get(placed.k);
const fuel = () => state._buildEnergyLedger(components).get(componentId).fuelEnergy;
const before = fuel();
this.assertGreater(before, 0);
research(state, 0, "efficient_generation");
const after = fuel();
this.assertApprox(before / after, 1.05, 1e-6, "the same power burns 5% less fuel");
}
test_every_efficiency_technology_reads_back_on_its_own_resource() {
const state = smallState();
const byResource = {
energy: "efficient_generation",
steel: "advanced_metallurgy",
food: "precision_agriculture",
luxury: "automated_extraction",
hightech: "advanced_lithography",
};
for (const [resource, tech] of Object.entries(byResource)) {
research(state, 0, tech);
this.assertApprox(state.resourceEfficiency(0, resource), 0.05, 1e-9, resource);
}
}
test_food_efficiency_cuts_the_harvest_s_energy() {
const state = smallState();
this.assertApprox(
state._foodHarvestEnergy(0, 1000), producerEnergyPerDay("food", 1000)
);
research(state, 0, "precision_agriculture");
this.assertApprox(
state._foodHarvestEnergy(0, 1000), producerEnergyPerDay("food", 1000) / 1.05, 1e-6,
"better farming grows the same food for less power"
);
}
}