mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 13:50:15 +00:00
35b7213c5c
## Description: Doesn't need a description :D https://github.com/user-attachments/assets/8de576fd-050b-4b35-8526-e4c88d1a9f25 https://github.com/user-attachments/assets/c99147a1-efdf-426b-96d1-e996e01f89aa ## Please complete the following: - [X] I have added screenshots for all UI updates - [X] I process any text displayed to the user through translateText() and I've added it to the en.json file - [X] I have added relevant tests to the test directory - [X] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: FloPinguin
161 lines
5.0 KiB
TypeScript
161 lines
5.0 KiB
TypeScript
import { NukeExecution } from "../../../src/core/execution/NukeExecution";
|
|
import {
|
|
Game,
|
|
Player,
|
|
PlayerInfo,
|
|
PlayerType,
|
|
UnitType,
|
|
} from "../../../src/core/game/Game";
|
|
import { setup } from "../../util/Setup";
|
|
import { TestConfig } from "../../util/TestConfig";
|
|
import { executeTicks } from "../../util/utils";
|
|
|
|
let game: Game;
|
|
let player: Player;
|
|
let otherPlayer: Player;
|
|
|
|
describe("NukeExecution", () => {
|
|
beforeEach(async () => {
|
|
game = await setup(
|
|
"big_plains",
|
|
{
|
|
infiniteGold: true,
|
|
instantBuild: true,
|
|
},
|
|
[
|
|
new PlayerInfo("player", PlayerType.Human, "client_id1", "player_id"),
|
|
new PlayerInfo("other", PlayerType.Human, "client_id2", "other_id"),
|
|
],
|
|
);
|
|
|
|
(game.config() as TestConfig).nukeMagnitudes = vi.fn(() => ({
|
|
inner: 10,
|
|
outer: 10,
|
|
}));
|
|
(game.config() as TestConfig).nukeAllianceBreakThreshold = vi.fn(() => 5);
|
|
|
|
while (game.inSpawnPhase()) {
|
|
game.executeNextTick();
|
|
}
|
|
|
|
player = game.player("player_id");
|
|
otherPlayer = game.player("other_id");
|
|
|
|
player.conquer(game.ref(1, 1));
|
|
});
|
|
|
|
test("nuke should destroy buildings and redraw out of range buildings", async () => {
|
|
// Build a city at (1,1)
|
|
player.buildUnit(UnitType.City, game.ref(1, 1), {});
|
|
// Build a missile silo in range
|
|
player.buildUnit(UnitType.MissileSilo, game.ref(1, 10), {});
|
|
// Build a SAM out of range
|
|
const sam = player.buildUnit(UnitType.SAMLauncher, game.ref(1, 11), {});
|
|
sam.touch = vi.fn();
|
|
// Build a Defense post out of range AND out of redraw range
|
|
const defensePost = player.buildUnit(
|
|
UnitType.DefensePost,
|
|
game.ref(1, 27),
|
|
{},
|
|
);
|
|
defensePost.touch = vi.fn();
|
|
// Add a nuke execution targeting the city
|
|
const nukeExec = new NukeExecution(
|
|
UnitType.AtomBomb,
|
|
player,
|
|
game.ref(1, 1),
|
|
game.ref(1, 2),
|
|
);
|
|
game.addExecution(nukeExec);
|
|
// Run enough ticks for the nuke to detonate
|
|
executeTicks(game, 10);
|
|
// The city and silo should be destroyed
|
|
expect(player.units(UnitType.City)).toHaveLength(0);
|
|
expect(player.units(UnitType.MissileSilo)).toHaveLength(0);
|
|
expect(player.units(UnitType.SAMLauncher)).toHaveLength(1);
|
|
expect(sam.touch).toHaveBeenCalled();
|
|
expect(defensePost.touch).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test("nuke should only be targetable near src and dst", async () => {
|
|
player.buildUnit(UnitType.MissileSilo, game.ref(1, 1), {});
|
|
const nukeExec = new NukeExecution(
|
|
UnitType.AtomBomb,
|
|
player,
|
|
game.ref(199, 199),
|
|
game.ref(1, 1),
|
|
);
|
|
game.addExecution(nukeExec);
|
|
// targetable distance is 400
|
|
|
|
//near launch should be targetable (distance src < 400)
|
|
executeTicks(game, 2);
|
|
expect(nukeExec.getNuke()!.isTargetable()).toBeTruthy();
|
|
|
|
//mid air should not be targetable (distance src > 400, distance target > 400)
|
|
executeTicks(game, 38);
|
|
expect(nukeExec.getNuke()!.isTargetable()).toBeFalsy();
|
|
|
|
//near target should be targetable (distance target < 400)
|
|
executeTicks(game, 35);
|
|
expect(nukeExec.getNuke()!.isTargetable()).toBeTruthy();
|
|
});
|
|
|
|
test("nuke should break alliances on launch", async () => {
|
|
const req = player.createAllianceRequest(otherPlayer);
|
|
req!.accept();
|
|
|
|
player.conquer(game.ref(1, 1));
|
|
player.buildUnit(UnitType.MissileSilo, game.ref(1, 1), {});
|
|
|
|
for (let x = 90; x < 99; x++) {
|
|
for (let y = 90; y < 99; y++) {
|
|
otherPlayer.conquer(game.ref(x, y));
|
|
}
|
|
}
|
|
|
|
// Add a nuke targeting just outside the other player's territory.
|
|
game.addExecution(
|
|
new NukeExecution(UnitType.AtomBomb, player, game.ref(85, 85), null),
|
|
);
|
|
|
|
game.executeNextTick(); // init
|
|
game.executeNextTick(); // exec
|
|
|
|
expect(player.isTraitor()).toBe(true);
|
|
expect(player.isAlliedWith(otherPlayer)).toBe(false);
|
|
});
|
|
|
|
test("nuke should break alliance when destroying ally's building even with few tiles", async () => {
|
|
const req = player.createAllianceRequest(otherPlayer);
|
|
req!.accept();
|
|
|
|
expect(player.isAlliedWith(otherPlayer)).toBe(true);
|
|
|
|
player.conquer(game.ref(1, 1));
|
|
player.buildUnit(UnitType.MissileSilo, game.ref(1, 1), {});
|
|
|
|
// Give the other player just a few tiles (below the threshold of 5)
|
|
// and build a port on one of them
|
|
otherPlayer.conquer(game.ref(50, 50));
|
|
otherPlayer.conquer(game.ref(51, 50));
|
|
otherPlayer.conquer(game.ref(50, 51));
|
|
otherPlayer.buildUnit(UnitType.Port, game.ref(50, 50), {});
|
|
|
|
expect(otherPlayer.units(UnitType.Port)).toHaveLength(1);
|
|
|
|
// Nuke targeting the ally's port - this should break alliance
|
|
// even though the tile count is below threshold
|
|
game.addExecution(
|
|
new NukeExecution(UnitType.AtomBomb, player, game.ref(50, 50), null),
|
|
);
|
|
|
|
game.executeNextTick(); // init
|
|
game.executeNextTick(); // exec
|
|
|
|
// Alliance should be broken because we're destroying ally's building
|
|
expect(player.isTraitor()).toBe(true);
|
|
expect(player.isAlliedWith(otherPlayer)).toBe(false);
|
|
});
|
|
});
|