82 lines
3.0 KiB
JavaScript
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"
|
|
);
|
|
}
|
|
}
|