Food, steel, luxury and high-tech now share one flat month-long reserve. A region keeps bidding for the shortfall while its store is thin, so a war that empties a pantry refills it from the grid instead of starving; the harvest is served before the city load, unmet food bids the price up, the army's rations count as demand, and a converter that cannot cover its power bill idles instead of making a loss. The delivery graph walks sea lanes any distance, so its walks are cached across days behind a road/railway/work/territory stamp and only dropped by a wartime unit move. Units are indexed per tile, market access and node populations are memoised for the day, and the server can settle a fresh world before serving (--warmup, 150 days by default). Roadmap records the remaining follow-ups -- the politics/migration hot path and the luxury/high-tech price plateau -- and that freight's heavy energy draw is intended.
45 lines
1.7 KiB
JavaScript
45 lines
1.7 KiB
JavaScript
import { TestCase } from "./framework/test_case.js";
|
|
import { traverse } from "../shared/economy_graph.js";
|
|
|
|
// A small undirected graph: `edges` maps a node to `[neighbour, weight]` pairs.
|
|
function graph(edges) {
|
|
return (node) => (edges[node] || []).map(([next, weight]) => ({ node: next, cost: 1, weight }));
|
|
}
|
|
|
|
export class EconomyGraphTest extends TestCase {
|
|
test_sea_legs_do_not_count_against_the_cap() {
|
|
// 0->1->2 are sea legs (weight 0); 2->3 and 3->4 are land (weight 1).
|
|
const neighbours = graph({
|
|
0: [[1, 0]],
|
|
1: [[0, 0], [2, 0]],
|
|
2: [[1, 0], [3, 1]],
|
|
3: [[2, 1], [4, 1]],
|
|
4: [[3, 1]],
|
|
});
|
|
const reached = traverse(0, { neighbours, maxWeight: 1 });
|
|
const nodes = reached.map((entry) => entry.node);
|
|
this.assertTrue(nodes.includes(3), "a land leg within the cap is reached past any sea");
|
|
this.assertFalse(nodes.includes(4), "a second land leg exceeds the cap");
|
|
}
|
|
|
|
test_land_legs_still_count_against_the_cap() {
|
|
const neighbours = graph({
|
|
0: [[1, 1]],
|
|
1: [[0, 1], [2, 1]],
|
|
2: [[1, 1]],
|
|
});
|
|
const reached = traverse(0, { neighbours, maxWeight: 1 });
|
|
const nodes = reached.map((entry) => entry.node);
|
|
this.assertTrue(nodes.includes(1), "the first land leg is reached");
|
|
this.assertFalse(nodes.includes(2), "the second land leg exceeds the cap");
|
|
}
|
|
|
|
test_an_edge_without_a_weight_counts_as_one() {
|
|
const neighbours = graph({ 0: [[1, undefined]], 1: [[0, undefined], [2, undefined]], 2: [[1, undefined]] });
|
|
const reached = traverse(0, { neighbours, maxWeight: 1 });
|
|
const nodes = reached.map((entry) => entry.node);
|
|
this.assertTrue(nodes.includes(1));
|
|
this.assertFalse(nodes.includes(2), "the default weight is one step");
|
|
}
|
|
}
|