@@ -474,9 +473,17 @@ export class SinglePlayerModal extends LitElement {
private handleGameModeSelection(value: GameMode) {
this.gameMode = value;
+ if (value === GameMode.FFA) {
+ this.teamGameType = TeamGameType.Standard;
+ }
+ // Clear disabled units when switching to other modes
+ this.disabledUnits = [];
+ }
+ private handleTeamGameTypeSelection(value: TeamGameType) {
+ this.teamGameType = value;
// Enforce Nuke Wars restrictions
- if (value === GameMode.NukeWars) {
+ if (value === TeamGameType.NukeWars) {
// Force 2 teams for Nuke Wars
this.teamCount = 2;
// Force Baikal map
@@ -484,12 +491,6 @@ export class SinglePlayerModal extends LitElement {
this.selectedMap = GameMapType.Baikal;
this.useRandomMap = false;
}
-
- // Disable all units except missiles and SAMs
- this.disabledUnits = [...this.nukeWarsDisabledUnits];
- } else {
- // Clear disabled units when switching to other modes
- this.disabledUnits = [];
}
}
@@ -517,7 +518,8 @@ export class SinglePlayerModal extends LitElement {
}
// Enforce Nuke Wars availability only on Baikal for single player as well
if (
- this.gameMode === GameMode.NukeWars &&
+ this.gameMode === GameMode.Team &&
+ this.teamGameType === TeamGameType.NukeWars &&
this.selectedMap !== GameMapType.Baikal
) {
alert(
@@ -579,6 +581,7 @@ export class SinglePlayerModal extends LitElement {
: GameMapSize.Normal,
gameType: GameType.Singleplayer,
gameMode: this.gameMode,
+ teamGameType: this.gameMode === GameMode.Team ? this.teamGameType : undefined,
playerTeams: this.teamCount,
difficulty: this.selectedDifficulty,
disableNPCs: this.disableNPCs,
diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts
index f697ce382..28ddb7a7c 100644
--- a/src/client/graphics/GameRenderer.ts
+++ b/src/client/graphics/GameRenderer.ts
@@ -1,6 +1,6 @@
import { EventBus } from "../../core/EventBus";
import { GameView } from "../../core/game/GameView";
-import { UserSettings } from "../../core/game/UserSettings";
+import { GameMode, TeamGameType } from "../../core/game/Game";
import { GameStartingModal } from "../GameStartingModal";
import { RefreshGraphicsEvent as RedrawGraphicsEvent } from "../InputHandler";
import { TransformHandler } from "./TransformHandler";
@@ -248,7 +248,11 @@ export function createRenderer(
playerPanel,
),
new SpawnTimer(game, transformHandler),
- new NukeWarsTopBanner(game),
+ // Conditionally add NukeWarsTopBanner if it's a Nuke Wars game
+ ...(game.config().gameConfig().gameMode === GameMode.Team &&
+ game.config().gameConfig().teamGameType === TeamGameType.NukeWars
+ ? [new NukeWarsTopBanner(game)]
+ : []),
leaderboard,
gameLeftSidebar,
unitDisplay,
diff --git a/src/client/graphics/layers/NukeWarsTopBanner.ts b/src/client/graphics/layers/NukeWarsTopBanner.ts
index 61484a339..4266ed7c5 100644
--- a/src/client/graphics/layers/NukeWarsTopBanner.ts
+++ b/src/client/graphics/layers/NukeWarsTopBanner.ts
@@ -1,4 +1,4 @@
-import { GameMapType, GameMode } from "../../../core/game/Game";
+import { GameMapType, GameMode, TeamGameType } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
import { Layer } from "./Layer";
@@ -19,7 +19,7 @@ export class NukeWarsTopBanner implements Layer {
renderLayer(context: CanvasRenderingContext2D) {
const config = this.game.config().gameConfig();
- if (config.gameMode !== GameMode.NukeWars) return;
+ if (!(config.gameMode === GameMode.Team && config.teamGameType === TeamGameType.NukeWars)) return;
if (config.gameMap !== GameMapType.Baikal) return;
const canvasWidth = context.canvas.width;
const padding = 12;
diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts
index 4110bc2c1..7490b36f0 100644
--- a/src/core/Schemas.ts
+++ b/src/core/Schemas.ts
@@ -15,6 +15,7 @@ import {
GameMode,
GameType,
Quads,
+ TeamGameType,
Trios,
UnitType,
} from "./game/Game";
@@ -157,6 +158,7 @@ export const GameConfigSchema = z.object({
donateTroops: z.boolean(), // Configures donations to humans only
gameType: z.enum(GameType),
gameMode: z.enum(GameMode),
+ teamGameType: z.enum(TeamGameType).optional(),
gameMapSize: z.enum(GameMapSize),
disableNPCs: z.boolean(),
bots: z.number().int().min(0).max(400),
diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts
index 352be5fb5..2495f5050 100644
--- a/src/core/configuration/DefaultConfig.ts
+++ b/src/core/configuration/DefaultConfig.ts
@@ -18,6 +18,7 @@ import {
Trios,
UnitInfo,
UnitType,
+ TeamGameType,
} from "../game/Game";
import { TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
@@ -316,13 +317,22 @@ export class DefaultConfig implements Config {
spawnNPCs(): boolean {
return !this._gameConfig.disableNPCs;
- }
-
isUnitDisabled(unitType: UnitType): boolean {
- // Nuke Wars: only MIRV is blocked explicitly. Keep any server-configured
- // disabledUnits in the check as well.
- if (this._gameConfig.gameMode === GameMode.NukeWars) {
- if (unitType === UnitType.MIRV) return true;
+ if (this._gameConfig.gameMode === GameMode.Team && this._gameConfig.teamGameType === TeamGameType.NukeWars) {
+ const allowedUnits = [
+ UnitType.City,
+ UnitType.Port,
+ UnitType.Factory,
+ UnitType.MissileSilo,
+ UnitType.SAMLauncher,
+ UnitType.DefensePost,
+ UnitType.Warship,
+ UnitType.TradeShip,
+ UnitType.TransportShip,
+ UnitType.AtomBomb,
+ UnitType.HydrogenBomb,
+ ];
+ return !allowedUnits.includes(unitType);
}
return this._gameConfig.disabledUnits?.includes(unitType) ?? false;
@@ -619,7 +629,7 @@ export class DefaultConfig implements Config {
numPreparationPhaseTurns(): number {
// Preparation phase duration (Nuke Wars uses a 3 minute prep phase)
- if (this._gameConfig.gameMode === GameMode.NukeWars) {
+ if (this._gameConfig.gameMode === GameMode.Team && this._gameConfig.teamGameType === TeamGameType.NukeWars) {
return 180 * 10; // 180 seconds * 10 ticks/sec
}
return 0;
diff --git a/src/core/execution/MoveWarshipExecution.ts b/src/core/execution/MoveWarshipExecution.ts
index 8327b0ad5..aa8594c07 100644
--- a/src/core/execution/MoveWarshipExecution.ts
+++ b/src/core/execution/MoveWarshipExecution.ts
@@ -4,6 +4,7 @@ import {
GameMapType,
GameMode,
Player,
+ TeamGameType,
UnitType,
} from "../game/Game";
import { TileRef } from "../game/GameMap";
@@ -34,7 +35,8 @@ export class MoveWarshipExecution implements Execution {
// In Nuke Wars on Baikal, prevent assigning patrols that cross the midpoint.
const gc = mg.config().gameConfig();
if (
- gc.gameMode === GameMode.NukeWars &&
+ gc.gameMode === GameMode.Team &&
+ gc.teamGameType === TeamGameType.NukeWars &&
gc.gameMap === GameMapType.Baikal
) {
const mapWidth = mg.width();
diff --git a/src/core/execution/SpawnExecution.ts b/src/core/execution/SpawnExecution.ts
index a5bbfee71..3517d18f1 100644
--- a/src/core/execution/SpawnExecution.ts
+++ b/src/core/execution/SpawnExecution.ts
@@ -6,6 +6,7 @@ import {
Player,
PlayerInfo,
PlayerType,
+ TeamGameType,
} from "../game/Game";
import { TileRef } from "../game/GameMap";
import { BotExecution } from "./BotExecution";
@@ -49,7 +50,8 @@ export class SpawnExecution implements Execution {
let spawnTile = this.tile;
const gc = this.mg.config().gameConfig();
if (
- gc.gameMode === GameMode.NukeWars &&
+ gc.gameMode === GameMode.Team &&
+ gc.teamGameType === TeamGameType.NukeWars &&
gc.gameMap === GameMapType.Baikal
) {
const mapWidth = this.mg.width();
diff --git a/src/core/execution/TransportShipExecution.ts b/src/core/execution/TransportShipExecution.ts
index e166a8abb..cc3718071 100644
--- a/src/core/execution/TransportShipExecution.ts
+++ b/src/core/execution/TransportShipExecution.ts
@@ -7,6 +7,7 @@ import {
Player,
PlayerID,
TerraNullius,
+ TeamGameType,
Unit,
UnitType,
} from "../game/Game";
@@ -108,7 +109,8 @@ export class TransportShipExecution implements Execution {
// In Nuke Wars on Baikal, prevent transport ships from entering enemy territory
const gc = this.mg.config().gameConfig();
if (
- gc.gameMode === GameMode.NukeWars &&
+ gc.gameMode === GameMode.Team &&
+ gc.teamGameType === TeamGameType.NukeWars &&
gc.gameMap === GameMapType.Baikal &&
this.dst !== null
) {
diff --git a/src/core/execution/WinCheckExecution.ts b/src/core/execution/WinCheckExecution.ts
index cabc32ddd..99727a9f3 100644
--- a/src/core/execution/WinCheckExecution.ts
+++ b/src/core/execution/WinCheckExecution.ts
@@ -6,6 +6,7 @@ import {
GameMode,
Player,
Team,
+ TeamGameType,
} from "../game/Game";
export class WinEvent implements GameEvent {
@@ -32,10 +33,13 @@ export class WinCheckExecution implements Execution {
const gameMode = this.mg.config().gameConfig().gameMode;
if (gameMode === GameMode.FFA) {
this.checkWinnerFFA();
- } else if (gameMode === GameMode.NukeWars) {
- this.checkWinnerNukeWars();
- } else {
- this.checkWinnerTeam();
+ } else if (gameMode === GameMode.Team) {
+ const teamGameType = this.mg.config().gameConfig().teamGameType;
+ if (teamGameType === TeamGameType.NukeWars) {
+ this.checkWinnerNukeWars();
+ } else {
+ this.checkWinnerTeam();
+ }
}
}
diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts
index e43d6b22a..7ad5563c5 100644
--- a/src/core/game/Game.ts
+++ b/src/core/game/Game.ts
@@ -149,8 +149,13 @@ export const isGameType = (value: unknown): value is GameType =>
export enum GameMode {
FFA = "Free For All",
Team = "Team",
+}
+
+export enum TeamGameType {
+ Standard = "Standard",
NukeWars = "Nuke Wars",
}
+
export const isGameMode = (value: unknown): value is GameMode =>
isEnumValue(GameMode, value);
diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts
index 08487471a..abbf5e8a4 100644
--- a/src/core/game/GameImpl.ts
+++ b/src/core/game/GameImpl.ts
@@ -30,6 +30,7 @@ import {
Unit,
UnitInfo,
UnitType,
+ TeamGameType,
} from "./Game";
import { GameMap, TileRef, TileUpdate } from "./GameMap";
import { GameUpdate, GameUpdateType } from "./GameUpdates";
@@ -98,8 +99,7 @@ export class GameImpl implements Game {
this.unitGrid = new UnitGrid(this._map);
// Treat Team and NukeWars as team-based games (Nuke Wars is 2-team only)
if (
- _config.gameConfig().gameMode === GameMode.Team ||
- _config.gameConfig().gameMode === GameMode.NukeWars
+ _config.gameConfig().gameMode === GameMode.Team
) {
this.populateTeams();
}
@@ -109,7 +109,7 @@ export class GameImpl implements Game {
private populateTeams() {
let numPlayerTeams = this._config.playerTeams();
// Force 2 teams for NukeWars
- if (this._config.gameConfig().gameMode === GameMode.NukeWars) {
+ if (this._config.gameConfig().gameMode === GameMode.Team && this._config.gameConfig().teamGameType === TeamGameType.NukeWars) {
numPlayerTeams = 2;
}
if (typeof numPlayerTeams !== "number") {
@@ -681,10 +681,7 @@ export class GameImpl implements Game {
teams(): Team[] {
if (this._config.gameConfig().gameMode !== GameMode.Team) {
- // Treat NukeWars as a team-based mode (2 teams)
- if (this._config.gameConfig().gameMode !== GameMode.NukeWars) {
- return [];
- }
+ return [];
}
return [this.botTeam, ...this.playerTeams];
}
diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts
index 71d1998b2..238f3fba2 100644
--- a/src/core/game/PlayerImpl.ts
+++ b/src/core/game/PlayerImpl.ts
@@ -33,6 +33,7 @@ import {
PlayerType,
Relation,
Team,
+ TeamGameType,
TerraNullius,
Tick,
Unit,
@@ -905,7 +906,8 @@ export class PlayerImpl implements Player {
private isInTeamSpawnZone(tile: TileRef): boolean {
const gameMode = this.mg.config().gameConfig().gameMode;
- if (gameMode !== GameMode.NukeWars) {
+ const teamGameType = this.mg.config().gameConfig().teamGameType;
+ if (!(gameMode === GameMode.Team && teamGameType === TeamGameType.NukeWars)) {
return true;
}
@@ -936,7 +938,8 @@ export class PlayerImpl implements Player {
// Nuke Wars restrictions on Baikal map
const gc = this.mg.config().gameConfig();
if (
- gc.gameMode === GameMode.NukeWars &&
+ gc.gameMode === GameMode.Team &&
+ gc.teamGameType === TeamGameType.NukeWars &&
gc.gameMap === GameMapType.Baikal
) {
// Ships cannot enter enemy team spawn zones
@@ -985,7 +988,7 @@ export class PlayerImpl implements Player {
// In Nuke Wars, AtomBomb and HydrogenBomb cannot be launched during the
// preparation phase, but are allowed afterwards. Other build restrictions
// (like team spawn zones) are handled above.
- if (gc.gameMode === GameMode.NukeWars && this.mg.inPreparationPhase()) {
+ if (gc.gameMode === GameMode.Team && gc.teamGameType === TeamGameType.NukeWars && this.mg.inPreparationPhase()) {
this.mg.displayMessage(
"Nuclear weapons cannot be launched during the preparation phase",
MessageType.ATTACK_FAILED,
@@ -1097,7 +1100,7 @@ export class PlayerImpl implements Player {
const owner = this.mg.owner(tile);
const gc = this.mg.config().gameConfig();
// In NukeWars prep phase, allow building in team territory
- if (gc.gameMode === GameMode.NukeWars && this.mg.inPreparationPhase()) {
+ if (gc.gameMode === GameMode.Team && gc.teamGameType === TeamGameType.NukeWars && this.mg.inPreparationPhase()) {
if (!owner.isPlayer() || !this.isOnSameTeam(owner as Player)) {
return [];
}
@@ -1243,7 +1246,8 @@ export class PlayerImpl implements Player {
// side deterministically by smallID parity (odd = left, even = right).
const gameCfg = this.mg.config().gameConfig();
if (
- gameCfg.gameMode === GameMode.NukeWars &&
+ gameCfg.gameMode === GameMode.Team &&
+ gameCfg.teamGameType === TeamGameType.NukeWars &&
gameCfg.gameMap === GameMapType.Baikal &&
this.mg.inSpawnPhase()
) {
diff --git a/src/core/game/TransportShipUtils.ts b/src/core/game/TransportShipUtils.ts
index 862f533e5..84b8c5304 100644
--- a/src/core/game/TransportShipUtils.ts
+++ b/src/core/game/TransportShipUtils.ts
@@ -1,6 +1,6 @@
import { PathFindResultType } from "../pathfinding/AStar";
import { MiniAStar } from "../pathfinding/MiniAStar";
-import { Game, GameMapType, GameMode, Player, UnitType } from "./Game";
+import { Game, GameMapType, GameMode, Player, TeamGameType, UnitType } from "./Game";
import { andFN, GameMap, manhattanDistFN, TileRef } from "./GameMap";
export function canBuildTransportShip(
@@ -22,19 +22,19 @@ export function canBuildTransportShip(
const other = game.owner(tile);
// During NukeWars, don't block transport ships between team members
const gc = game.config().gameConfig();
- if (gc.gameMode !== GameMode.NukeWars) {
+ if (!(gc.gameMode === GameMode.Team && gc.teamGameType === TeamGameType.NukeWars)) {
if (other === player) {
return false;
}
if (other.isPlayer() && player.isFriendly(other)) {
return false;
}
- } else {
- // In NukeWars, only block sending to enemy teams
- if (other.isPlayer() && player.isOnSameTeam(other as Player)) {
- return false;
+ // In NukeWars, only block sending to enemy teams
+ } else if (gc.gameMode === GameMode.Team && gc.teamGameType === TeamGameType.NukeWars) {
+ if (other.isPlayer() && player.isOnSameTeam(other as Player)) {
+ return false;
+ }
}
- }
if (game.isOceanShore(dst)) {
let myPlayerBordersOcean = false;
@@ -85,7 +85,8 @@ export function canBuildTransportShip(
// Block lake deployments into enemy team territory in Nuke Wars
const gc = game.config().gameConfig();
if (
- gc.gameMode === GameMode.NukeWars &&
+ gc.gameMode === GameMode.Team &&
+ gc.teamGameType === TeamGameType.NukeWars &&
gc.gameMap === GameMapType.Baikal
) {
const tileOwner = game.owner(t);
diff --git a/tests/core/executions/NukeWarsRestrictions.test.ts b/tests/core/executions/NukeWarsRestrictions.test.ts
deleted file mode 100644
index b1f9867e0..000000000
--- a/tests/core/executions/NukeWarsRestrictions.test.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-import { Game, GameMode, UnitType } from "../../../src/core/game/Game";
-import { PlayerImpl } from "../../../src/core/game/PlayerImpl";
-
-describe("NukeWars Unit Restrictions", () => {
- let mg: jest.Mocked
;
-
- beforeEach(() => {
- mg = {
- config: jest.fn().mockReturnValue({
- gameConfig: jest.fn().mockReturnValue({
- gameMode: GameMode.NukeWars,
- maxTimerValue: 5,
- }),
- isUnitDisabled: jest.fn().mockImplementation((unitType: UnitType) => {
- const allowedUnits = [
- UnitType.MissileSilo,
- UnitType.SAMLauncher,
- UnitType.AtomBomb,
- UnitType.HydrogenBomb,
- ];
- return !allowedUnits.includes(unitType);
- }),
- }),
- width: jest.fn().mockReturnValue(100),
- x: jest.fn(),
- teams: jest.fn().mockReturnValue(["Team1", "Team2"]),
- inSpawnPhase: jest.fn().mockReturnValue(true),
- unitInfo: jest.fn().mockReturnValue({
- cost: jest.fn().mockReturnValue(0n),
- }),
- } as unknown as jest.Mocked;
- });
-
- describe("Unit type restrictions", () => {
- it.each([
- [UnitType.MissileSilo, true],
- [UnitType.SAMLauncher, true],
- [UnitType.AtomBomb, true],
- [UnitType.HydrogenBomb, true],
- [UnitType.MIRV, false],
- [UnitType.City, false],
- [UnitType.DefensePost, false],
- [UnitType.Port, false],
- [UnitType.TransportShip, false],
- [UnitType.Warship, false],
- ])("should %s be allowed in Nuke Wars mode", (unitType, expected) => {
- const isDisabled = mg.config().isUnitDisabled(unitType);
- expect(!isDisabled).toBe(expected);
- });
- });
-
- describe("Spawn zone restrictions", () => {
- let player: jest.Mocked;
-
- beforeEach(() => {
- player = {
- team: jest.fn().mockReturnValue("Team1"),
- isAlive: jest.fn().mockReturnValue(true),
- gold: jest.fn().mockReturnValue(1000n),
- canBuild: jest.fn().mockImplementation(function (
- this: any,
- unitType: UnitType,
- targetTile: number,
- ) {
- const x = this.mg.x(targetTile);
- const mapWidth = this.mg.width();
- const midpoint = Math.floor(mapWidth / 2);
- const onOwnSide = x < midpoint;
-
- if (this.mg.inSpawnPhase()) {
- return onOwnSide ? targetTile : false;
- }
-
- if (!onOwnSide) {
- return [UnitType.AtomBomb, UnitType.HydrogenBomb].includes(unitType)
- ? targetTile
- : false;
- }
-
- return this.mg.config().isUnitDisabled(unitType) ? false : targetTile;
- }),
- mg: mg,
- } as unknown as jest.Mocked;
- });
-
- describe("During spawn phase", () => {
- beforeEach(() => {
- mg.inSpawnPhase.mockReturnValue(true);
- });
-
- it("should allow building on own side", () => {
- mg.x.mockReturnValue(20); // Left side
- const canBuild = player.canBuild(UnitType.MissileSilo, 0);
- expect(canBuild).not.toBe(false);
- });
-
- it("should prevent building on enemy side", () => {
- mg.x.mockReturnValue(80); // Right side
- const canBuild = player.canBuild(UnitType.MissileSilo, 0);
- expect(canBuild).toBe(false);
- });
- });
-
- describe("After spawn phase", () => {
- beforeEach(() => {
- mg.inSpawnPhase.mockReturnValue(false);
- });
-
- it("should allow missiles to cross midpoint", () => {
- mg.x.mockReturnValue(80); // Right side
- const canBuild = player.canBuild(UnitType.AtomBomb, 0);
- expect(canBuild).not.toBe(false);
- });
-
- it("should prevent SAM launchers from crossing midpoint", () => {
- mg.x.mockReturnValue(80); // Right side
- const canBuild = player.canBuild(UnitType.SAMLauncher, 0);
- expect(canBuild).toBe(false);
- });
- });
- });
-});
diff --git a/tests/core/executions/NukeWarsWinCheck.test.ts b/tests/core/executions/NukeWarsWinCheck.test.ts
deleted file mode 100644
index 172979111..000000000
--- a/tests/core/executions/NukeWarsWinCheck.test.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { WinCheckExecution } from "../../../src/core/execution/WinCheckExecution";
-import {
- ColoredTeams,
- Game,
- GameMode,
- Player,
- Team,
-} from "../../../src/core/game/Game";
-
-describe("NukeWars Win Check", () => {
- let winCheck: WinCheckExecution;
- let mg: jest.Mocked;
-
- beforeEach(() => {
- winCheck = new WinCheckExecution();
- mg = {
- config: jest.fn().mockReturnValue({
- gameConfig: jest.fn().mockReturnValue({
- gameMode: GameMode.NukeWars,
- maxTimerValue: 5,
- }),
- numSpawnPhaseTurns: jest.fn().mockReturnValue(0),
- }),
- players: jest.fn(),
- numLandTiles: jest.fn(),
- numTilesWithFallout: jest.fn(),
- setWinner: jest.fn(),
- ticks: jest.fn().mockReturnValue(0),
- stats: jest.fn().mockReturnValue({
- stats: jest.fn(),
- }),
- } as unknown as jest.Mocked;
- });
-
- it("should declare winner when a team drops below 5% territory", () => {
- const team1Players = [
- {
- numTilesOwned: jest.fn().mockReturnValue(40),
- team: jest.fn().mockReturnValue("Team1" as Team),
- },
- ] as unknown as Player[];
-
- const team2Players = [
- {
- numTilesOwned: jest.fn().mockReturnValue(4), // < 5% territory
- team: jest.fn().mockReturnValue("Team2" as Team),
- },
- ] as unknown as Player[];
-
- mg.players.mockReturnValue([...team1Players, ...team2Players]);
- mg.numLandTiles.mockReturnValue(100);
- mg.numTilesWithFallout.mockReturnValue(0);
-
- winCheck.init(mg, 0);
- winCheck.checkWinnerNukeWars();
-
- // Team1 should win since Team2 is below 5%
- expect(mg.setWinner).toHaveBeenCalledWith("Team1", expect.anything());
- });
-
- it("should not declare bot team as winner", () => {
- const botTeamPlayers = [
- {
- numTilesOwned: jest.fn().mockReturnValue(90),
- team: jest.fn().mockReturnValue(ColoredTeams.Bot as Team),
- },
- ] as unknown as Player[];
-
- const playerTeamPlayers = [
- {
- numTilesOwned: jest.fn().mockReturnValue(4),
- team: jest.fn().mockReturnValue("Team1" as Team),
- },
- ] as unknown as Player[];
-
- mg.players.mockReturnValue([...botTeamPlayers, ...playerTeamPlayers]);
- mg.numLandTiles.mockReturnValue(100);
- mg.numTilesWithFallout.mockReturnValue(0);
-
- winCheck.init(mg, 0);
- winCheck.checkWinnerNukeWars();
-
- // Should not declare bot team as winner even if other team is < 5%
- expect(mg.setWinner).not.toHaveBeenCalledWith(
- ColoredTeams.Bot,
- expect.anything(),
- );
- });
-
- it("should declare winner with most territory when time runs out", () => {
- const team1Players = [
- {
- numTilesOwned: jest.fn().mockReturnValue(60),
- team: jest.fn().mockReturnValue("Team1" as Team),
- },
- ] as unknown as Player[];
-
- const team2Players = [
- {
- numTilesOwned: jest.fn().mockReturnValue(40),
- team: jest.fn().mockReturnValue("Team2" as Team),
- },
- ] as unknown as Player[];
-
- mg.players.mockReturnValue([...team1Players, ...team2Players]);
- mg.numLandTiles.mockReturnValue(100);
- mg.numTilesWithFallout.mockReturnValue(0);
- mg.ticks.mockReturnValue(5 * 60 * 10 + 1); // Just past time limit
-
- winCheck.init(mg, 0);
- winCheck.checkWinnerNukeWars();
-
- // Team1 should win since they have more territory when time expires
- expect(mg.setWinner).toHaveBeenCalledWith("Team1", expect.anything());
- });
-});