have Team be an enum instead of an object, this was causing equality problems.

This commit is contained in:
Evan
2025-04-05 21:36:38 -07:00
parent f620264ce3
commit c7356a7348
16 changed files with 72 additions and 93 deletions
+3 -3
View File
@@ -11,7 +11,7 @@ import {
import { createGameRecord } from "../core/Util";
import { ServerConfig } from "../core/configuration/Config";
import { getConfig } from "../core/configuration/ConfigLoader";
import { TeamName, UnitType } from "../core/game/Game";
import { Team, UnitType } from "../core/game/Game";
import {
ErrorUpdate,
GameUpdateType,
@@ -189,13 +189,13 @@ export class ClientGameRunner {
clientID: this.lobby.clientID,
},
];
let winner: ClientID | TeamName | null = null;
let winner: ClientID | Team | null = null;
if (update.winnerType == "player") {
winner = this.gameView
.playerBySmallID(update.winner as number)
.clientID();
} else {
winner = update.winner as TeamName;
winner = update.winner as Team;
}
const record = createGameRecord(
+2 -2
View File
@@ -6,7 +6,7 @@ import {
GameType,
PlayerID,
PlayerType,
TeamName,
Team,
Tick,
UnitType,
} from "../core/game/Game";
@@ -128,7 +128,7 @@ export class SendSetTargetTroopRatioEvent implements GameEvent {
export class SendWinnerEvent implements GameEvent {
constructor(
public readonly winner: ClientID | TeamName,
public readonly winner: ClientID | Team,
public readonly allPlayersStats: AllPlayersStats,
public readonly winnerType: "player" | "team",
) {}
+3 -3
View File
@@ -1,5 +1,5 @@
import { blue, red } from "../../../core/configuration/Colors";
import { GameMode, TeamName } from "../../../core/game/Game";
import { GameMode, Team } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
@@ -28,12 +28,12 @@ export class SpawnTimer implements Layer {
const numBlueTiles = this.game
.players()
.filter((p) => p.teamName() == TeamName.Blue)
.filter((p) => p.team() == Team.Blue)
.reduce((acc, p) => acc + p.numTilesOwned(), 0);
const numRedTiles = this.game
.players()
.filter((p) => p.teamName() == TeamName.Red)
.filter((p) => p.team() == Team.Red)
.reduce((acc, p) => acc + p.numTilesOwned(), 0);
this.ratio = numBlueTiles / (numBlueTiles + numRedTiles);
+3 -7
View File
@@ -1,7 +1,7 @@
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { EventBus } from "../../../core/EventBus";
import { TeamName } from "../../../core/game/Game";
import { Team } from "../../../core/game/Game";
import { GameUpdateType } from "../../../core/game/GameUpdates";
import { GameView, PlayerView } from "../../../core/game/GameView";
import { PseudoRandom } from "../../../core/PseudoRandom";
@@ -226,13 +226,9 @@ export class WinModal extends LitElement implements Layer {
this.game.updatesSinceLastTick()[GameUpdateType.Win].forEach((wu) => {
if (wu.winnerType === "team") {
this.eventBus.emit(
new SendWinnerEvent(
wu.winner as TeamName,
wu.allPlayersStats,
"team",
),
new SendWinnerEvent(wu.winner as Team, wu.allPlayersStats, "team"),
);
if (wu.winner == this.game.myPlayer()?.teamName()) {
if (wu.winner == this.game.myPlayer()?.team()) {
this._title = "Your team won!";
this.won = true;
} else {
+3 -3
View File
@@ -6,7 +6,7 @@ import {
GameMode,
GameType,
PlayerType,
TeamName,
Team,
UnitType,
} from "./game/Game";
@@ -364,7 +364,7 @@ const ClientBaseMessageSchema = z.object({
export const ClientSendWinnerSchema = ClientBaseMessageSchema.extend({
type: z.literal("winner"),
winner: ID.or(z.nativeEnum(TeamName)).nullable(),
winner: ID.or(z.nativeEnum(Team)).nullable(),
allPlayersStats: AllPlayersStatsSchema,
winnerType: z.enum(["player", "team"]),
});
@@ -425,7 +425,7 @@ export const GameRecordSchema = z.object({
num_turns: z.number(),
turns: z.array(TurnSchema),
winner: z
.union([ID, z.nativeEnum(TeamName)])
.union([ID, z.nativeEnum(Team)])
.nullable()
.optional(),
winnerType: z.enum(["player", "team"]).nullable().optional(),
+2 -2
View File
@@ -1,7 +1,7 @@
import DOMPurify from "dompurify";
import { customAlphabet } from "nanoid";
import twemoji from "twemoji";
import { Cell, Game, Player, TeamName, Unit } from "./game/Game";
import { Cell, Game, Player, Team, Unit } from "./game/Game";
import { andFN, GameMap, manhattanDistFN, TileRef } from "./game/GameMap";
import {
AllPlayersStats,
@@ -253,7 +253,7 @@ export function createGameRecord(
turns: Turn[],
start: number,
end: number,
winner: ClientID | TeamName | null,
winner: ClientID | Team | null,
winnerType: "player" | "team" | null,
allPlayersStats: AllPlayersStats,
): GameRecord {
+4 -4
View File
@@ -1,7 +1,7 @@
import { Colord, colord } from "colord";
import { PseudoRandom } from "../PseudoRandom";
import { simpleHash } from "../Util";
import { PlayerType, TeamName, TerrainType } from "../game/Game";
import { PlayerType, Team, TerrainType } from "../game/Game";
import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import {
@@ -37,13 +37,13 @@ export const pastelTheme = new (class implements Theme {
private _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 });
territoryColor(player: PlayerView): Colord {
if (player.teamName() == TeamName.Bot) {
if (player.team() == Team.Bot) {
return botColor;
}
if (player.teamName() == TeamName.Red) {
if (player.team() == Team.Red) {
return red;
}
if (player.teamName() == TeamName.Blue) {
if (player.team() == Team.Blue) {
return blue;
}
if (player.info().playerType == PlayerType.Human) {
+4 -4
View File
@@ -1,7 +1,7 @@
import { Colord, colord } from "colord";
import { PseudoRandom } from "../PseudoRandom";
import { simpleHash } from "../Util";
import { PlayerType, TeamName, TerrainType } from "../game/Game";
import { PlayerType, Team, TerrainType } from "../game/Game";
import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import {
@@ -37,13 +37,13 @@ export const pastelThemeDark = new (class implements Theme {
private _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 });
territoryColor(player: PlayerView): Colord {
if (player.teamName() == TeamName.Bot) {
if (player.team() == Team.Bot) {
return botColor;
}
if (player.teamName() == TeamName.Red) {
if (player.team() == Team.Red) {
return red;
}
if (player.teamName() == TeamName.Blue) {
if (player.team() == Team.Blue) {
return blue;
}
if (player.info().playerType == PlayerType.Human) {
+4 -11
View File
@@ -1,12 +1,5 @@
import { GameEvent } from "../EventBus";
import {
Execution,
Game,
GameMode,
Player,
Team,
TeamName,
} from "../game/Game";
import { Execution, Game, GameMode, Player, Team } from "../game/Game";
export class WinEvent implements GameEvent {
constructor(public readonly winner: Player) {}
@@ -73,9 +66,9 @@ export class WinCheckExecution implements Execution {
this.mg.numLandTiles() - this.mg.numTilesWithFallout();
const percentage = (max[1] / numTilesWithoutFallout) * 100;
if (percentage > this.mg.config().percentageTilesOwnedToWin()) {
if (max[0].name == TeamName.Bot) return;
this.mg.setWinner(max[0].name, this.mg.stats().stats());
console.log(`${max[0].name} has won the game`);
if (max[0] == Team.Bot) return;
this.mg.setWinner(max[0], this.mg.stats().stats());
console.log(`${max[0]} has won the game`);
this.active = false;
}
}
+2 -6
View File
@@ -37,7 +37,7 @@ export enum Difficulty {
Impossible = "Impossible",
}
export enum TeamName {
export enum Team {
Red = "Red",
Blue = "Blue",
Bot = "Bot",
@@ -75,10 +75,6 @@ export enum GameMode {
Team = "Team",
}
export interface Team {
name: TeamName;
}
export interface UnitInfo {
cost: (player: Player | PlayerView) => Gold;
// Determines if its owner changes when its tile is conquered.
@@ -443,7 +439,7 @@ export interface Game extends GameMap {
ticks(): Tick;
inSpawnPhase(): boolean;
executeNextTick(): GameUpdates;
setWinner(winner: Player | TeamName, allPlayersStats: AllPlayersStats): void;
setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void;
config(): Config;
// Units
+3 -7
View File
@@ -20,7 +20,6 @@ import {
PlayerInfo,
PlayerType,
Team,
TeamName,
TerrainType,
TerraNullius,
Unit,
@@ -76,11 +75,8 @@ export class GameImpl implements Game {
private _stats: StatsImpl = new StatsImpl();
private playerTeams: Team[] = [
{ name: TeamName.Red },
{ name: TeamName.Blue },
];
private botTeam: Team = { name: TeamName.Bot };
private playerTeams: Team[] = [Team.Red, Team.Blue];
private botTeam: Team = Team.Bot;
constructor(
private _humans: PlayerInfo[],
@@ -555,7 +551,7 @@ export class GameImpl implements Game {
});
}
setWinner(winner: Player | TeamName, allPlayersStats: AllPlayersStats): void {
setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void {
this.addUpdate({
type: GameUpdateType.Win,
winner: typeof winner === "string" ? winner : winner.smallID(),
+3 -3
View File
@@ -6,7 +6,7 @@ import {
NameViewData,
PlayerID,
PlayerType,
TeamName,
Team,
Tick,
UnitType,
} from "./Game";
@@ -92,7 +92,7 @@ export interface PlayerUpdate {
name: string;
displayName: string;
id: PlayerID;
teamName?: TeamName;
team?: Team;
smallID: number;
playerType: PlayerType;
isAlive: boolean;
@@ -161,7 +161,7 @@ export interface WinUpdate {
type: GameUpdateType.Win;
allPlayersStats: AllPlayersStats;
// Player id or team name.
winner: number | TeamName;
winner: number | Team;
winnerType: "player" | "team";
}
+4 -6
View File
@@ -15,7 +15,7 @@ import {
PlayerInfo,
PlayerProfile,
PlayerType,
TeamName,
Team,
TerrainType,
TerraNullius,
Tick,
@@ -177,8 +177,8 @@ export class PlayerView {
id(): PlayerID {
return this.data.id;
}
teamName(): TeamName {
return this.data.teamName;
team(): Team | null {
return this.data.team;
}
type(): PlayerType {
return this.data.playerType;
@@ -223,9 +223,7 @@ export class PlayerView {
}
isOnSameTeam(other: PlayerView): boolean {
return (
this.data.teamName != null && this.data.teamName == other.data.teamName
);
return this.data.team != null && this.data.team == other.data.team;
}
isFriendly(other: PlayerView): boolean {
+2 -2
View File
@@ -127,7 +127,7 @@ export class PlayerImpl implements Player {
name: this.name(),
displayName: this.displayName(),
id: this.id(),
teamName: this.team()?.name,
team: this.team(),
smallID: this.smallID(),
playerType: this.type(),
isAlive: this.isAlive(),
@@ -596,7 +596,7 @@ export class PlayerImpl implements Player {
if (this.team() == null || other.team() == null) {
return false;
}
return this._team.name == other.team().name;
return this._team == other.team();
}
isFriendly(other: Player): boolean {
+5 -5
View File
@@ -1,4 +1,4 @@
import { PlayerInfo, Team, TeamName } from "./Game";
import { PlayerInfo, Team } from "./Game";
export function assignTeams(
players: PlayerInfo[],
@@ -38,7 +38,7 @@ export function assignTeams(
for (const player of clanPlayers) {
if (redTeamCount < maxTeamSize) {
redTeamCount++;
result.set(player, { name: TeamName.Red });
result.set(player, Team.Red);
} else {
result.set(player, "kicked");
}
@@ -48,7 +48,7 @@ export function assignTeams(
for (const player of clanPlayers) {
if (blueTeamCount < maxTeamSize) {
blueTeamCount++;
result.set(player, { name: TeamName.Blue });
result.set(player, Team.Blue);
} else {
result.set(player, "kicked");
}
@@ -60,10 +60,10 @@ export function assignTeams(
for (const player of noClanPlayers) {
if (redTeamCount <= blueTeamCount) {
redTeamCount++;
result.set(player, { name: TeamName.Red });
result.set(player, Team.Red);
} else {
blueTeamCount++;
result.set(player, { name: TeamName.Blue });
result.set(player, Team.Blue);
}
}
+25 -25
View File
@@ -1,4 +1,4 @@
import { PlayerInfo, PlayerType, TeamName } from "../src/core/game/Game";
import { PlayerInfo, PlayerType, Team } from "../src/core/game/Game";
import { assignTeams } from "../src/core/game/TeamAssignment";
describe("assignTeams", () => {
@@ -25,10 +25,10 @@ describe("assignTeams", () => {
const result = assignTeams(players);
// Check that players are assigned alternately
expect(result.get(players[0])).toEqual({ name: TeamName.Red });
expect(result.get(players[1])).toEqual({ name: TeamName.Blue });
expect(result.get(players[2])).toEqual({ name: TeamName.Red });
expect(result.get(players[3])).toEqual({ name: TeamName.Blue });
expect(result.get(players[0])).toEqual(Team.Red);
expect(result.get(players[1])).toEqual(Team.Blue);
expect(result.get(players[2])).toEqual(Team.Red);
expect(result.get(players[3])).toEqual(Team.Blue);
});
it("should keep clan members together on the same team", () => {
@@ -42,10 +42,10 @@ describe("assignTeams", () => {
const result = assignTeams(players);
// Check that clan members are on the same team
expect(result.get(players[0])).toEqual({ name: TeamName.Red });
expect(result.get(players[1])).toEqual({ name: TeamName.Red });
expect(result.get(players[2])).toEqual({ name: TeamName.Blue });
expect(result.get(players[3])).toEqual({ name: TeamName.Blue });
expect(result.get(players[0])).toEqual(Team.Red);
expect(result.get(players[1])).toEqual(Team.Red);
expect(result.get(players[2])).toEqual(Team.Blue);
expect(result.get(players[3])).toEqual(Team.Blue);
});
it("should handle mixed clan and non-clan players", () => {
@@ -59,10 +59,10 @@ describe("assignTeams", () => {
const result = assignTeams(players);
// Check that clan members are together and non-clan players balance teams
expect(result.get(players[0])).toEqual({ name: TeamName.Red });
expect(result.get(players[1])).toEqual({ name: TeamName.Red });
expect(result.get(players[2])).toEqual({ name: TeamName.Blue });
expect(result.get(players[3])).toEqual({ name: TeamName.Blue });
expect(result.get(players[0])).toEqual(Team.Red);
expect(result.get(players[1])).toEqual(Team.Red);
expect(result.get(players[2])).toEqual(Team.Blue);
expect(result.get(players[3])).toEqual(Team.Blue);
});
it("should kick players when teams are full", () => {
@@ -78,14 +78,14 @@ describe("assignTeams", () => {
const result = assignTeams(players);
// Check that players are kicked when teams are full
expect(result.get(players[0])).toEqual({ name: TeamName.Red });
expect(result.get(players[1])).toEqual({ name: TeamName.Red });
expect(result.get(players[2])).toEqual({ name: TeamName.Red });
expect(result.get(players[0])).toEqual(Team.Red);
expect(result.get(players[1])).toEqual(Team.Red);
expect(result.get(players[2])).toEqual(Team.Red);
expect(result.get(players[3])).toEqual("kicked");
expect(result.get(players[4])).toEqual({ name: TeamName.Blue });
expect(result.get(players[5])).toEqual({ name: TeamName.Blue });
expect(result.get(players[4])).toEqual(Team.Blue);
expect(result.get(players[5])).toEqual(Team.Blue);
});
it("should handle empty player list", () => {
@@ -96,7 +96,7 @@ describe("assignTeams", () => {
it("should handle single player", () => {
const players = [createPlayer("1")];
const result = assignTeams(players);
expect(result.get(players[0])).toEqual({ name: TeamName.Red });
expect(result.get(players[0])).toEqual(Team.Red);
});
it("should handle multiple clans with different sizes", () => {
@@ -112,11 +112,11 @@ describe("assignTeams", () => {
const result = assignTeams(players);
// Check that larger clans are assigned first
expect(result.get(players[0])).toEqual({ name: TeamName.Red });
expect(result.get(players[1])).toEqual({ name: TeamName.Red });
expect(result.get(players[2])).toEqual({ name: TeamName.Red });
expect(result.get(players[3])).toEqual({ name: TeamName.Blue });
expect(result.get(players[4])).toEqual({ name: TeamName.Blue });
expect(result.get(players[5])).toEqual({ name: TeamName.Blue });
expect(result.get(players[0])).toEqual(Team.Red);
expect(result.get(players[1])).toEqual(Team.Red);
expect(result.get(players[2])).toEqual(Team.Red);
expect(result.get(players[3])).toEqual(Team.Blue);
expect(result.get(players[4])).toEqual(Team.Blue);
expect(result.get(players[5])).toEqual(Team.Blue);
});
});