Files
Battle-for-Tismo/tests/famine_test.js

82 lines
3.0 KiB
JavaScript

import { TestCase } from "./framework/test_case.js";
import { smallState, cityOf } from "./framework/helpers.js";
import { key } from "../shared/hex.js";
import { FAMINE, NEWS_FAMINE } from "../shared/data.js";
// A region in famine: its food store has run dry and the day's need went unmet.
function starve(state, city) {
state._resourceShortages = new Map([[city.id, { food: 1 }]]);
}
export class FamineTest extends TestCase {
test_famine_begins_when_food_runs_out() {
const state = smallState();
const city = cityOf(state, 0);
this.assertFalse(state.isFamine(city), "a fed region is not in famine");
starve(state, city);
state._tickFamine();
this.assertTrue(state.isFamine(city), "running out of food starts a famine");
}
test_famine_kills_one_percent_a_day() {
const state = smallState();
const city = cityOf(state, 0);
const before = state.regionPopulation(city);
this.assertGreater(before, 0, "the region has people");
starve(state, city);
state._tickFamine();
const after = state.regionPopulation(city);
this.assertApprox(after, before * (1 - FAMINE.dailyMortality), before * 0.01);
}
test_famine_is_announced_once_per_occurrence() {
const state = smallState();
const city = cityOf(state, 0);
starve(state, city);
state._tickFamine();
state._tickFamine();
let news = state.news.filter((entry) => entry.type === NEWS_FAMINE);
this.assertEqual(news.length, 1, "a lasting famine is announced only once");
this.assertEqual(news[0].region, city.name, "the region is named");
this.assertEqual(news[0].civ, city.civ, "so is its nation");
// Food comes back: the famine ends silently...
state._resourceShortages = new Map();
state._tickFamine();
this.assertFalse(state.isFamine(city), "food ends the famine");
// ...and a later famine is fresh news.
starve(state, city);
state._tickFamine();
news = state.news.filter((entry) => entry.type === NEWS_FAMINE);
this.assertEqual(news.length, 2, "a new famine is announced afresh");
}
test_the_snapshot_ships_the_famine() {
const state = smallState();
const city = cityOf(state, 0);
starve(state, city);
state._tickFamine();
const snapshot = state.snapshot(0);
const stats = snapshot.cityStats.find((entry) => entry.id === city.id);
this.assertTrue(stats.famine, "the famine is shipped to the client");
}
test_a_drained_food_store_starts_a_famine() {
const state = smallState();
const city = cityOf(state, 0);
// The region's people far outnumber what its land can feed, so the day's
// harvest and every reachable store fall short of the need.
for (const coords of state.regionTiles(city)) {
const k = key(coords.x, coords.y);
state.tilePopulation.set(k, (state.tilePopulation.get(k) || 0) * 1000);
}
state._tickResources();
this.assertTrue(state.isFamine(city), "the resource tick starts the famine");
this.assertGreater(
state.news.filter((entry) => entry.type === NEWS_FAMINE).length,
0,
"the world is told"
);
}
}