import { TestCase } from "./framework/test_case.js"; import { smallState } from "./framework/helpers.js"; import { STARTING_FORCES, STARTING_RESERVE_DAYS, } from "../shared/game_state/scenario.js"; import { STORABLE_RESOURCE_IDS } from "../shared/data.js"; function unitsWithProto(state, protoId) { const index = state.protoUnits.findIndex((unit) => unit.id === protoId); return state.units.filter((unit) => unit.proto === index); } function countAt(state, protoId, coords) { return unitsWithProto(state, protoId).filter( (unit) => unit.coords.x === coords.x && unit.coords.y === coords.y ).length; } export class ScenarioTest extends TestCase { test_every_city_opens_with_a_barracks_and_the_capital_an_airport() { const state = smallState(); state.applyStartingScenario(); const barracks = state.buildingIndexById("barracks"); const airport = state.buildingIndexById("airport"); for (const city of state.cities) { this.assertEqual(state.getCityBuildingLevel(city, barracks), 1, "the city barracks"); this.assertEqual( state.getCityBuildingLevel(city, airport), city.isCapital ? 1 : 0, `the airport in ${city.name}` ); } } test_every_city_opens_with_its_infantry_and_artillery() { const state = smallState(); state.applyStartingScenario(); for (const city of state.cities) { this.assertEqual( countAt(state, "modern_infantry", city.coords), STARTING_FORCES.infantryPerCity, `infantry in ${city.name}` ); this.assertEqual( countAt(state, "artillery", city.coords), STARTING_FORCES.artilleryPerCity, `artillery in ${city.name}` ); } } test_every_port_launches_its_flotilla_onto_the_water() { const state = smallState(); state.applyStartingScenario(); for (let civ = 0; civ < state.civilisations.length; civ++) { const ports = state.cities.filter( (city) => city.civ === civ && state.hasCityBuilding(city, "port") ).length; const launches = unitsWithProto(state, "launch").filter((unit) => unit.civ === civ); const battleships = unitsWithProto(state, "battleship").filter((unit) => unit.civ === civ); this.assertEqual(launches.length, STARTING_FORCES.launchesPerPort * ports, `launches of civ ${civ}`); this.assertEqual( battleships.length, STARTING_FORCES.battleshipsPerPort * ports, `battleships of civ ${civ}` ); for (const unit of launches.concat(battleships)) { const tile = state.tiles[`${unit.coords.x},${unit.coords.y}`]; this.assertEqual(tile && tile.terrainClass, "Sea", "the warship floats"); } } } test_the_capital_fields_the_air_force() { const state = smallState(); state.applyStartingScenario(); for (const city of state.cities) { if (!city.isCapital) continue; this.assertEqual( countAt(state, "jet_fighter", city.coords), STARTING_FORCES.fightersPerCapital, `fighters in ${city.name}` ); this.assertEqual( countAt(state, "bomber", city.coords), STARTING_FORCES.bombersPerCapital, `bombers in ${city.name}` ); } } test_each_region_opens_with_a_year_of_its_consumption() { const state = smallState(); state.applyStartingScenario(); for (const city of state.cities) { const consumption = state.getRegionResourceInfo(city).consumption; const stock = state.getCityResourceStock(city); for (const id of STORABLE_RESOURCE_IDS) { this.assertApprox( stock[id], (consumption[id] || 0) * STARTING_RESERVE_DAYS, 1e-6, `${id} in ${city.name}` ); } } } test_the_scenario_replaces_any_starting_units() { const state = smallState(); state.applyStartingScenario(); const once = state.units.length; state.applyStartingScenario(); this.assertEqual(state.units.length, once, "re-applying does not stack a second army"); } }