This commit is contained in:
Scott Anderson
2025-04-12 02:40:47 -04:00
parent b38e6a845d
commit 5e9819a973
20 changed files with 161 additions and 145 deletions
+3 -4
View File
@@ -295,10 +295,9 @@ export class BuildMenu extends LitElement implements Layer {
if (this.game?.myPlayer() === null || this.playerActions === null) {
return false;
}
const unit = this.playerActions.buildableUnits.filter(
(u) => u.type === item.unitType,
);
if (!unit) {
const buildableUnits = this.playerActions?.buildableUnits ?? [];
const unit = buildableUnits.filter((u) => u.type === item.unitType);
if (unit.length === 0) {
return false;
}
return unit[0].canBuild;
+2 -2
View File
@@ -230,7 +230,7 @@ export class WinModal extends LitElement implements Layer {
this.eventBus.emit(
new SendWinnerEvent(wu.winner as Team, wu.allPlayersStats, "team"),
);
if (wu.winner == this.game.myPlayer()?.team()) {
if (wu.winner === this.game.myPlayer()?.team()) {
this._title = "Your team won!";
this.won = true;
} else {
@@ -248,7 +248,7 @@ export class WinModal extends LitElement implements Layer {
new SendWinnerEvent(winnerClient, wu.allPlayersStats, "player"),
);
}
if (winner == this.game.myPlayer()) {
if (winner === this.game.myPlayer()) {
this._title = "You Won!";
this.won = true;
} else {
+5 -5
View File
@@ -40,7 +40,7 @@ export async function createGameRunner(
(p) =>
new PlayerInfo(
p.flag,
p.clientID == clientID
p.clientID === clientID
? sanitize(p.username)
: fixProfaneUsername(sanitize(p.username)),
PlayerType.Human,
@@ -122,19 +122,19 @@ export class GameRunner {
return;
}
if (this.game.inSpawnPhase() && this.game.ticks() % 2 == 0) {
if (this.game.inSpawnPhase() && this.game.ticks() % 2 === 0) {
this.game
.players()
.filter(
(p) =>
p.type() == PlayerType.Human || p.type() == PlayerType.FakeHuman,
p.type() === PlayerType.Human || p.type() === PlayerType.FakeHuman,
)
.forEach(
(p) => (this.playerViewData[p.id()] = placeName(this.game, p)),
);
}
if (this.game.ticks() < 3 || this.game.ticks() % 30 == 0) {
if (this.game.ticks() < 3 || this.game.ticks() % 30 === 0) {
this.game.players().forEach((p) => {
this.playerViewData[p.id()] = placeName(this.game, p);
});
@@ -166,7 +166,7 @@ export class GameRunner {
buildableUnits: Object.values(UnitType).map((u) => {
return {
type: u,
canBuild: player.canBuild(u, tile) != false,
canBuild: player.canBuild(u, tile) !== false,
cost: this.game.config().unitInfo(u).cost(player),
} as BuildableUnit;
}),
+2 -2
View File
@@ -38,14 +38,14 @@ export class PseudoRandom {
}
randElement<T>(arr: T[]): T {
if (arr.length == 0) {
if (arr.length === 0) {
throw new Error("array must not be empty");
}
return arr[this.nextInt(0, arr.length)];
}
chance(odds: number): boolean {
return this.nextInt(0, odds) == 0;
return this.nextInt(0, odds) === 0;
}
shuffleArray(array: any[]) {
+5 -5
View File
@@ -93,7 +93,7 @@ export function closestShoreFromPlayer(
const shoreTiles = Array.from(player.borderTiles()).filter((t) =>
gm.isShore(t),
);
if (shoreTiles.length == 0) {
if (shoreTiles.length === 0) {
return null;
}
@@ -117,7 +117,7 @@ function closestShoreTN(
)
.filter((t) => gm.isShore(t))
.sort((a, b) => gm.manhattanDist(tile, a) - gm.manhattanDist(tile, b));
if (tn.length == 0) {
if (tn.length === 0) {
return null;
}
return tn[0];
@@ -274,12 +274,12 @@ export function createGameRecord(
};
for (const turn of turns) {
if (turn.intents.length != 0 || turn.hash != undefined) {
if (turn.intents.length !== 0 || turn.hash !== undefined) {
record.turns.push(turn);
for (const intent of turn.intents) {
if (intent.type == "spawn") {
if (intent.type === "spawn") {
for (const playerRecord of players) {
if (playerRecord.clientID == intent.clientID) {
if (playerRecord.clientID === intent.clientID) {
playerRecord.username = intent.name;
}
}
+31 -27
View File
@@ -25,7 +25,7 @@ import { pastelThemeDark } from "./PastelThemeDark";
export abstract class DefaultServerConfig implements ServerConfig {
region(): string {
if (this.env() == GameEnv.Dev) {
if (this.env() === GameEnv.Dev) {
return "dev";
}
return process.env.REGION ?? "undefined";
@@ -104,7 +104,7 @@ export abstract class DefaultServerConfig implements ServerConfig {
return Math.random() < 0.2 ? 60 : 35;
}
// world belongs with the ~2 mils, but these amounts never made sense so I assume the insanity is intended.
if (map == GameMapType.World) {
if (map === GameMapType.World) {
return Math.random() < 0.2 ? 150 : 60;
}
// default return for non specified map
@@ -229,7 +229,7 @@ export class DefaultConfig implements Config {
case UnitType.Warship:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold()
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: Math.min(
1_000_000,
@@ -253,7 +253,7 @@ export class DefaultConfig implements Config {
case UnitType.Port:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold()
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: Math.min(
1_000_000,
@@ -268,19 +268,21 @@ export class DefaultConfig implements Config {
case UnitType.AtomBomb:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold() ? 0 : 750_000,
p.type() === PlayerType.Human && this.infiniteGold() ? 0 : 750_000,
territoryBound: false,
};
case UnitType.HydrogenBomb:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold() ? 0 : 5_000_000,
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: 5_000_000,
territoryBound: false,
};
case UnitType.MIRV:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold()
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: 25_000_000,
territoryBound: false,
@@ -298,14 +300,16 @@ export class DefaultConfig implements Config {
case UnitType.MissileSilo:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold() ? 0 : 1_000_000,
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: 1_000_000,
territoryBound: true,
constructionDuration: this.instantBuild() ? 0 : 10 * 10,
};
case UnitType.DefensePost:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold()
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: Math.min(
250_000,
@@ -319,7 +323,7 @@ export class DefaultConfig implements Config {
case UnitType.SAMLauncher:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold()
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: Math.min(
1_500_000 * 3,
@@ -333,7 +337,7 @@ export class DefaultConfig implements Config {
case UnitType.City:
return {
cost: (p: Player) =>
p.type() == PlayerType.Human && this.infiniteGold()
p.type() === PlayerType.Human && this.infiniteGold()
? 0
: Math.min(
2_000_000,
@@ -379,7 +383,7 @@ export class DefaultConfig implements Config {
return 600 * 10; // 10 minutes.
}
percentageTilesOwnedToWin(): number {
if (this._gameConfig.gameMode == GameMode.Team) {
if (this._gameConfig.gameMode === GameMode.Team) {
return 95;
}
return 80;
@@ -388,7 +392,7 @@ export class DefaultConfig implements Config {
return 3;
}
numSpawnPhaseTurns(): number {
return this._gameConfig.gameType == GameType.Singleplayer ? 100 : 300;
return this._gameConfig.gameType === GameType.Singleplayer ? 100 : 300;
}
numBots(): number {
return this.bots();
@@ -433,7 +437,7 @@ export class DefaultConfig implements Config {
gm.config().defensePostRange(),
UnitType.DefensePost,
)) {
if (dp.unit.owner() == defender) {
if (dp.unit.owner() === defender) {
mag *= this.defensePostDefenseBonus();
speed *= this.defensePostDefenseBonus();
break;
@@ -449,14 +453,14 @@ export class DefaultConfig implements Config {
if (attacker.isPlayer() && defender.isPlayer()) {
if (
attacker.type() == PlayerType.Human &&
defender.type() == PlayerType.Bot
attacker.type() === PlayerType.Human &&
defender.type() === PlayerType.Bot
) {
mag *= 0.8;
}
if (
attacker.type() == PlayerType.FakeHuman &&
defender.type() == PlayerType.Bot
attacker.type() === PlayerType.FakeHuman &&
defender.type() === PlayerType.Bot
) {
mag *= 0.8;
}
@@ -489,7 +493,7 @@ export class DefaultConfig implements Config {
} else {
return {
attackerTroopLoss:
attacker.type() == PlayerType.Bot ? mag / 10 : mag / 5,
attacker.type() === PlayerType.Bot ? mag / 10 : mag / 5,
defenderTroopLoss: 0,
tilesPerTickUsed: within(
(2000 * Math.max(10, speed)) / attackTroops,
@@ -534,7 +538,7 @@ export class DefaultConfig implements Config {
}
attackAmount(attacker: Player, defender: Player | TerraNullius) {
if (attacker.type() == PlayerType.Bot) {
if (attacker.type() === PlayerType.Bot) {
return attacker.troops() / 20;
} else {
return attacker.troops() / 5;
@@ -542,10 +546,10 @@ export class DefaultConfig implements Config {
}
startManpower(playerInfo: PlayerInfo): number {
if (playerInfo.playerType == PlayerType.Bot) {
if (playerInfo.playerType === PlayerType.Bot) {
return 10_000;
}
if (playerInfo.playerType == PlayerType.FakeHuman) {
if (playerInfo.playerType === PlayerType.FakeHuman) {
switch (this._gameConfig.difficulty) {
case Difficulty.Easy:
return 2_500 * (playerInfo?.nation?.strength ?? 1);
@@ -562,16 +566,16 @@ export class DefaultConfig implements Config {
maxPopulation(player: Player | PlayerView): number {
const maxPop =
player.type() == PlayerType.Human && this.infiniteTroops()
player.type() === PlayerType.Human && this.infiniteTroops()
? 1_000_000_000
: 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) +
player.units(UnitType.City).length * this.cityPopulationIncrease();
if (player.type() == PlayerType.Bot) {
if (player.type() === PlayerType.Bot) {
return maxPop / 2;
}
if (player.type() == PlayerType.Human) {
if (player.type() === PlayerType.Human) {
return maxPop;
}
@@ -595,11 +599,11 @@ export class DefaultConfig implements Config {
const ratio = 1 - player.population() / max;
toAdd *= ratio;
if (player.type() == PlayerType.Bot) {
if (player.type() === PlayerType.Bot) {
toAdd *= 0.7;
}
if (player.type() == PlayerType.FakeHuman) {
if (player.type() === PlayerType.FakeHuman) {
switch (this._gameConfig.difficulty) {
case Difficulty.Easy:
toAdd *= 0.9;
+8 -6
View File
@@ -37,26 +37,28 @@ export const pastelTheme = new (class implements Theme {
private _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 });
territoryColor(player: PlayerView): Colord {
if (player.team() == Team.Bot) {
if (player.team() === Team.Bot) {
return botColor;
}
if (player.team() == Team.Red) {
if (player.team() === Team.Red) {
return red;
}
if (player.team() == Team.Blue) {
if (player.team() === Team.Blue) {
return blue;
}
if (player.info().playerType == PlayerType.Human) {
if (player.info().playerType === PlayerType.Human) {
return humanColors[simpleHash(player.id()) % humanColors.length];
}
if (player.info().playerType == PlayerType.Bot) {
if (player.info().playerType === PlayerType.Bot) {
return botColors[simpleHash(player.id()) % botColors.length];
}
return territoryColors[simpleHash(player.id()) % territoryColors.length];
}
textColor(player: PlayerView): string {
return player.info().playerType == PlayerType.Human ? "#000000" : "#4D4D4D";
return player.info().playerType === PlayerType.Human
? "#000000"
: "#4D4D4D";
}
specialBuildingColor(player: PlayerView): Colord {
+8 -6
View File
@@ -37,26 +37,28 @@ export const pastelThemeDark = new (class implements Theme {
private _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 });
territoryColor(player: PlayerView): Colord {
if (player.team() == Team.Bot) {
if (player.team() === Team.Bot) {
return botColor;
}
if (player.team() == Team.Red) {
if (player.team() === Team.Red) {
return red;
}
if (player.team() == Team.Blue) {
if (player.team() === Team.Blue) {
return blue;
}
if (player.info().playerType == PlayerType.Human) {
if (player.info().playerType === PlayerType.Human) {
return humanColors[simpleHash(player.id()) % humanColors.length];
}
if (player.info().playerType == PlayerType.Bot) {
if (player.info().playerType === PlayerType.Bot) {
return botColors[simpleHash(player.id()) % botColors.length];
}
return territoryColors[simpleHash(player.id()) % territoryColors.length];
}
textColor(player: PlayerView): string {
return player.info().playerType == PlayerType.Human ? "#ffffff" : "#e6e6e6";
return player.info().playerType === PlayerType.Human
? "#ffffff"
: "#e6e6e6";
}
specialBuildingColor(player: PlayerView): Colord {
+24 -21
View File
@@ -21,8 +21,8 @@ export class AttackExecution implements Execution {
private active: boolean = true;
private toConquer: PriorityQueue<TileContainer> =
new PriorityQueue<TileContainer>((a: TileContainer, b: TileContainer) => {
if (a.priority == b.priority) {
if (a.tick == b.tick) {
if (a.priority === b.priority) {
if (a.tick === b.tick) {
return 0;
// return this.random.nextInt(-1, 1)
}
@@ -68,7 +68,7 @@ export class AttackExecution implements Execution {
this.active = false;
return;
}
if (this._targetID != null && !mg.hasPlayer(this._targetID)) {
if (this._targetID !== null && !mg.hasPlayer(this._targetID)) {
console.warn(`target ${this._targetID} not found`);
this.active = false;
return;
@@ -76,22 +76,22 @@ export class AttackExecution implements Execution {
this._owner = mg.player(this._ownerID);
this.target =
this._targetID == this.mg.terraNullius().id()
this._targetID === this.mg.terraNullius().id()
? mg.terraNullius()
: mg.player(this._targetID);
if (this.target && this.target.isPlayer()) {
const targetPlayer = this.target as Player;
if (
targetPlayer.type() != PlayerType.Bot &&
this._owner.type() != PlayerType.Bot
targetPlayer.type() !== PlayerType.Bot &&
this._owner.type() !== PlayerType.Bot
) {
// Don't let bots embargo since they can't trade anyways.
targetPlayer.addEmbargo(this._owner.id());
}
}
if (this._owner == this.target) {
if (this._owner === this.target) {
console.error(`Player ${this._owner} cannot attack itself`);
this.active = false;
return;
@@ -108,7 +108,7 @@ export class AttackExecution implements Execution {
return;
}
if (this.startTroops == null) {
if (this.startTroops === null) {
this.startTroops = this.mg
.config()
.attackAmount(this._owner, this.target);
@@ -124,7 +124,7 @@ export class AttackExecution implements Execution {
);
for (const incoming of this._owner.incomingAttacks()) {
if (incoming.attacker() == this.target) {
if (incoming.attacker() === this.target) {
// Target has opposing attack, cancel them out
if (incoming.troops() > this.attack.troops()) {
incoming.setTroops(incoming.troops() - this.attack.troops());
@@ -139,9 +139,9 @@ export class AttackExecution implements Execution {
}
for (const outgoing of this._owner.outgoingAttacks()) {
if (
outgoing != this.attack &&
outgoing.target() == this.attack.target() &&
outgoing.sourceTile() == this.attack.sourceTile()
outgoing !== this.attack &&
outgoing.target() === this.attack.target() &&
outgoing.sourceTile() === this.attack.sourceTile()
) {
// Existing attack on same target, add troops
outgoing.setTroops(outgoing.troops() + this.attack.troops());
@@ -151,7 +151,7 @@ export class AttackExecution implements Execution {
}
}
if (this.sourceTile != null) {
if (this.sourceTile !== null) {
this.addNeighbors(this.sourceTile);
} else {
this.refreshToConquer();
@@ -217,7 +217,7 @@ export class AttackExecution implements Execution {
}
const alliance = this._owner.allianceWith(this.target as Player);
if (this.breakAlliance && alliance != null) {
if (this.breakAlliance && alliance !== null) {
this.breakAlliance = false;
this._owner.breakAlliance(alliance);
}
@@ -245,7 +245,7 @@ export class AttackExecution implements Execution {
return;
}
if (this.toConquer.size() == 0) {
if (this.toConquer.size() === 0) {
this.refreshToConquer();
this.retreat();
return;
@@ -257,8 +257,8 @@ export class AttackExecution implements Execution {
const onBorder =
this.mg
.neighbors(tileToConquer)
.filter((t) => this.mg.owner(t) == this._owner).length > 0;
if (this.mg.owner(tileToConquer) != this.target || !onBorder) {
.filter((t) => this.mg.owner(t) === this._owner).length > 0;
if (this.mg.owner(tileToConquer) !== this.target || !onBorder) {
continue;
}
this.addNeighbors(tileToConquer);
@@ -283,13 +283,16 @@ export class AttackExecution implements Execution {
private addNeighbors(tile: TileRef) {
for (const neighbor of this.mg.neighbors(tile)) {
if (this.mg.isWater(neighbor) || this.mg.owner(neighbor) != this.target) {
if (
this.mg.isWater(neighbor) ||
this.mg.owner(neighbor) !== this.target
) {
continue;
}
this.border.add(neighbor);
let numOwnedByMe = this.mg
.neighbors(neighbor)
.filter((t) => this.mg.owner(t) == this._owner).length;
.filter((t) => this.mg.owner(t) === this._owner).length;
const dist = 0;
if (numOwnedByMe > 2) {
numOwnedByMe = 10;
@@ -334,13 +337,13 @@ export class AttackExecution implements Execution {
for (const tile of this.target.tiles()) {
const borders = this.mg
.neighbors(tile)
.some((t) => this.mg.owner(t) == this._owner);
.some((t) => this.mg.owner(t) === this._owner);
if (borders) {
this._owner.conquer(tile);
} else {
for (const neighbor of this.mg.neighbors(tile)) {
const no = this.mg.owner(neighbor);
if (no.isPlayer() && no != this.target) {
if (no.isPlayer() && no !== this.target) {
this.mg.player(no.id()).conquer(tile);
break;
}
+4 -4
View File
@@ -36,7 +36,7 @@ export class BotExecution implements Execution {
return;
}
if (ticks % this.attackRate != 0) {
if (ticks % this.attackRate !== 0) {
return;
}
@@ -74,9 +74,9 @@ export class BotExecution implements Execution {
const border = Array.from(this.bot.borderTiles())
.flatMap((t) => this.mg.neighbors(t))
.filter((t) => this.mg.hasOwner(t) && this.mg.owner(t) != this.bot);
.filter((t) => this.mg.hasOwner(t) && this.mg.owner(t) !== this.bot);
if (border.length == 0) {
if (border.length === 0) {
return;
}
@@ -87,7 +87,7 @@ export class BotExecution implements Execution {
if (this.bot.isFriendly(owner)) {
return;
}
if (owner.type() == PlayerType.FakeHuman) {
if (owner.type() === PlayerType.FakeHuman) {
if (!this.random.chance(2)) {
return;
}
+1 -1
View File
@@ -27,7 +27,7 @@ export class BotSpawner {
}
const botName = this.randomBotName();
const spawn = this.spawnBot(botName);
if (spawn != null) {
if (spawn !== null) {
this.bots.push(spawn);
} else {
tries++;
+4 -4
View File
@@ -12,7 +12,7 @@ import { TileRef } from "../game/GameMap";
export class CityExecution implements Execution {
private player: Player;
private mg: Game;
private city: Unit;
private city: Unit | null = null;
private active: boolean = true;
constructor(
@@ -31,9 +31,9 @@ export class CityExecution implements Execution {
}
tick(ticks: number): void {
if (this.city == null) {
if (this.city === null) {
const spawnTile = this.player.canBuild(UnitType.City, this.tile);
if (spawnTile == false) {
if (spawnTile === false) {
consolex.warn("cannot build city");
this.active = false;
return;
@@ -45,7 +45,7 @@ export class CityExecution implements Execution {
return;
}
if (this.player != this.city.owner()) {
if (this.player !== this.city.owner()) {
this.player = this.city.owner();
}
}
+6 -6
View File
@@ -20,7 +20,7 @@ import { WarshipExecution } from "./WarshipExecution";
export class ConstructionExecution implements Execution {
private player: Player;
private construction: Unit;
private construction: Unit | null = null;
private active: boolean = true;
private mg: Game;
@@ -45,15 +45,15 @@ export class ConstructionExecution implements Execution {
}
tick(ticks: number): void {
if (this.construction == null) {
if (this.construction === null) {
const info = this.mg.unitInfo(this.constructionType);
if (info.constructionDuration == null) {
if (info.constructionDuration === undefined) {
this.completeConstruction();
this.active = false;
return;
}
const spawnTile = this.player.canBuild(this.constructionType, this.tile);
if (spawnTile == false) {
if (spawnTile === false) {
consolex.warn(`cannot build ${this.constructionType}`);
this.active = false;
return;
@@ -75,11 +75,11 @@ export class ConstructionExecution implements Execution {
return;
}
if (this.player != this.construction.owner()) {
if (this.player !== this.construction.owner()) {
this.player = this.construction.owner();
}
if (this.ticksUntilComplete == 0) {
if (this.ticksUntilComplete === 0) {
this.player = this.construction.owner();
this.construction.delete(false);
// refund the cost so player has the gold to build the unit
+4 -4
View File
@@ -12,7 +12,7 @@ import { TileRef } from "../game/GameMap";
export class DefensePostExecution implements Execution {
private player: Player;
private mg: Game;
private post: Unit;
private post: Unit | null = null;
private active: boolean = true;
constructor(
@@ -31,9 +31,9 @@ export class DefensePostExecution implements Execution {
}
tick(ticks: number): void {
if (this.post == null) {
if (this.post === null) {
const spawnTile = this.player.canBuild(UnitType.DefensePost, this.tile);
if (spawnTile == false) {
if (spawnTile === false) {
consolex.warn("cannot build Defense Post");
this.active = false;
return;
@@ -45,7 +45,7 @@ export class DefensePostExecution implements Execution {
return;
}
if (this.player != this.post.owner()) {
if (this.player !== this.post.owner()) {
this.player = this.post.owner();
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ export class DonateGoldExecution implements Execution {
this.sender = mg.player(this.senderID);
this.recipient = mg.player(this.recipientID);
if (this.gold == null) {
if (this.gold === null) {
this.gold = Math.round(this.sender.gold() / 3);
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ export class DonateTroopsExecution implements Execution {
this.sender = mg.player(this.senderID);
this.recipient = mg.player(this.recipientID);
if (this.troops == null) {
if (this.troops === null) {
this.troops = mg.config().defaultDonationAmount(this.sender);
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ export class EmbargoExecution implements Execution {
}
tick(_: number): void {
if (this.action == "start") this.player.addEmbargo(this.targetID);
if (this.action === "start") this.player.addEmbargo(this.targetID);
else this.player.stopEmbargo(this.targetID);
this.active = false;
+7 -5
View File
@@ -26,7 +26,7 @@ export class EmojiExecution implements Execution {
this.active = false;
return;
}
if (this.recipientID != AllPlayers && !mg.hasPlayer(this.recipientID)) {
if (this.recipientID !== AllPlayers && !mg.hasPlayer(this.recipientID)) {
console.warn(`EmojiExecution: recipient ${this.recipientID} not found`);
this.active = false;
return;
@@ -34,16 +34,18 @@ export class EmojiExecution implements Execution {
this.requestor = mg.player(this.senderID);
this.recipient =
this.recipientID == AllPlayers ? AllPlayers : mg.player(this.recipientID);
this.recipientID === AllPlayers
? AllPlayers
: mg.player(this.recipientID);
}
tick(ticks: number): void {
if (this.requestor.canSendEmoji(this.recipient)) {
this.requestor.sendEmoji(this.recipient, this.emoji);
if (
this.emoji == "🖕" &&
this.recipient != AllPlayers &&
this.recipient.type() == PlayerType.FakeHuman
this.emoji === "🖕" &&
this.recipient !== AllPlayers &&
this.recipient.type() === PlayerType.FakeHuman
) {
this.recipient.updateRelation(this.requestor, -100);
}
+36 -33
View File
@@ -61,7 +61,7 @@ export class FakeHumanExecution implements Execution {
private updateRelationsFromEmbargos() {
const player = this.player;
if (player === null) return;
const others = this.mg.players().filter((p) => p.id() != player.id());
const others = this.mg.players().filter((p) => p.id() !== player.id());
others.forEach((other: Player) => {
const embargoMalus = -20;
@@ -84,7 +84,7 @@ export class FakeHumanExecution implements Execution {
private handleEmbargoesToHostileNations() {
const player = this.player;
if (player === null) return;
const others = this.mg.players().filter((p) => p.id() != player.id());
const others = this.mg.players().filter((p) => p.id() !== player.id());
others.forEach((other: Player) => {
/* When player is hostile starts embargo. Do not stop until neutral again */
@@ -104,9 +104,9 @@ export class FakeHumanExecution implements Execution {
tick(ticks: number) {
if (this.mg.inSpawnPhase()) {
if (ticks % this.random.nextInt(5, 30) == 0) {
if (ticks % this.random.nextInt(5, 30) === 0) {
const rl = this.randomLand();
if (rl == null) {
if (rl === null) {
consolex.warn(`cannot spawn ${this.playerInfo.name}`);
return;
}
@@ -114,10 +114,10 @@ export class FakeHumanExecution implements Execution {
}
return;
}
if (this.player == null) {
if (this.player === null) {
this.player =
this.mg.players().find((p) => p.id() == this.playerInfo.id) ?? null;
if (this.player == null) {
this.mg.players().find((p) => p.id() === this.playerInfo.id) ?? null;
if (this.player === null) {
return;
}
}
@@ -131,7 +131,7 @@ export class FakeHumanExecution implements Execution {
return;
}
if (ticks % this.random.nextInt(40, 80) != 0) {
if (ticks % this.random.nextInt(40, 80) !== 0) {
return;
}
@@ -152,10 +152,10 @@ export class FakeHumanExecution implements Execution {
.flatMap((t) => this.mg.neighbors(t))
.filter(
(t) =>
this.mg.isLand(t) && this.mg.ownerID(t) != this.player?.smallID(),
this.mg.isLand(t) && this.mg.ownerID(t) !== this.player?.smallID(),
);
if (enemyborder.length == 0) {
if (enemyborder.length === 0) {
if (this.random.chance(10)) {
this.sendBoatRandomly();
}
@@ -219,10 +219,13 @@ export class FakeHumanExecution implements Execution {
return false;
}
const difficulty = this.mg.config().gameConfig().difficulty;
if (difficulty == Difficulty.Hard || difficulty == Difficulty.Impossible) {
if (
difficulty === Difficulty.Hard ||
difficulty === Difficulty.Impossible
) {
return false;
}
if (other.type() != PlayerType.Human) {
if (other.type() !== PlayerType.Human) {
return false;
}
// Only discourage attacks on Humans who are not traitors on easy or medium difficulty.
@@ -240,28 +243,28 @@ export class FakeHumanExecution implements Execution {
const target =
player
.allies()
.filter((ally) => player.relation(ally) == Relation.Friendly)
.filter((ally) => player.relation(ally) === Relation.Friendly)
.filter((ally) => ally.targets().length > 0)
.map((ally) => ({ ally: ally, t: ally.targets()[0] }))[0] ?? null;
if (
target != null &&
target.t != player &&
target !== null &&
target.t !== player &&
!player.isAlliedWith(target.t)
) {
player.updateRelation(target.ally, -20);
this.enemy = target.t;
this.lastEnemyUpdateTick = this.mg.ticks();
if (target.ally.type() == PlayerType.Human) {
if (target.ally.type() === PlayerType.Human) {
this.mg.addExecution(
new EmojiExecution(player.id(), target.ally.id(), "👍"),
);
}
}
if (this.enemy == null) {
if (this.enemy === null) {
const mostHated = player.allRelationsSorted()[0] ?? null;
if (mostHated != null && mostHated.relation == Relation.Hostile) {
if (mostHated !== null && mostHated.relation === Relation.Hostile) {
this.enemy = mostHated.player;
this.lastEnemyUpdateTick = this.mg.ticks();
}
@@ -286,7 +289,7 @@ export class FakeHumanExecution implements Execution {
private maybeSendEmoji() {
if (this.player === null) throw new Error("not initialized");
if (this.enemy === null) return;
if (this.enemy.type() != PlayerType.Human) return;
if (this.enemy.type() !== PlayerType.Human) return;
const lastSent = this.lastEmojiSent.get(this.enemy) ?? -300;
if (this.mg.ticks() - lastSent <= 300) return;
this.lastEmojiSent.set(this.enemy, this.mg.ticks());
@@ -302,7 +305,7 @@ export class FakeHumanExecution implements Execution {
private maybeSendNuke(other: Player) {
if (this.player === null) throw new Error("not initialized");
if (
this.player.units(UnitType.MissileSilo).length == 0 ||
this.player.units(UnitType.MissileSilo).length === 0 ||
this.player.gold() <
this.mg.config().unitInfo(UnitType.AtomBomb).cost(this.player) ||
this.player.isOnSameTeam(other)
@@ -311,12 +314,12 @@ export class FakeHumanExecution implements Execution {
}
outer: for (let i = 0; i < 10; i++) {
const tile = this.randTerritoryTile(other);
if (tile == null) {
if (tile === null) {
return;
}
for (const t of this.mg.bfs(tile, manhattanDistFN(tile, 15))) {
// Make sure we nuke at least 15 tiles in border
if (this.mg.owner(t) != other) {
if (this.mg.owner(t) !== other) {
continue outer;
}
}
@@ -339,7 +342,7 @@ export class FakeHumanExecution implements Execution {
),
Array.from(other.borderTiles()).filter((t) => this.mg.isOceanShore(t)),
);
if (closest == null) {
if (closest === null) {
return;
}
this.mg.addExecution(
@@ -356,7 +359,7 @@ export class FakeHumanExecution implements Execution {
const player = this.player;
if (player === null) return;
const ports = player.units(UnitType.Port);
if (ports.length == 0 && player.gold() > this.cost(UnitType.Port)) {
if (ports.length === 0 && player.gold() > this.cost(UnitType.Port)) {
const oceanTiles = Array.from(player.borderTiles()).filter((t) =>
this.mg.isOceanShore(t),
);
@@ -401,11 +404,11 @@ export class FakeHumanExecution implements Execution {
return;
}
const tile = this.randTerritoryTile(this.player);
if (tile == null) {
if (tile === null) {
return;
}
const canBuild = this.player.canBuild(type, tile);
if (canBuild == false) {
if (canBuild === false) {
return;
}
this.mg.addExecution(build(tile));
@@ -420,16 +423,16 @@ export class FakeHumanExecution implements Execution {
const ships = this.player.units(UnitType.Warship);
if (
ports.length > 0 &&
ships.length == 0 &&
ships.length === 0 &&
this.player.gold() > this.cost(UnitType.Warship)
) {
const port = this.random.randElement(ports);
const targetTile = this.warshipSpawnTile(port.tile());
if (targetTile == null) {
if (targetTile === null) {
return false;
}
const canBuild = this.player.canBuild(UnitType.Warship, targetTile);
if (canBuild == false) {
if (canBuild === false) {
consolex.warn("cannot spawn destroyer");
return false;
}
@@ -455,7 +458,7 @@ export class FakeHumanExecution implements Execution {
continue;
}
const randTile = this.mg.ref(randX, randY);
if (this.mg.owner(randTile) == p) {
if (this.mg.owner(randTile) === p) {
return randTile;
}
}
@@ -528,14 +531,14 @@ export class FakeHumanExecution implements Execution {
const oceanShore = Array.from(this.player.borderTiles()).filter((t) =>
this.mg.isOceanShore(t),
);
if (oceanShore.length == 0) {
if (oceanShore.length === 0) {
return;
}
const src = this.random.randElement(oceanShore);
const dst = this.randOceanShoreTile(src, 150);
if (dst == null) {
if (dst === null) {
return;
}
@@ -564,7 +567,7 @@ export class FakeHumanExecution implements Execution {
const tile = this.mg.ref(x, y);
if (this.mg.isLand(tile) && !this.mg.hasOwner(tile)) {
if (
this.mg.terrainType(tile) == TerrainType.Mountain &&
this.mg.terrainType(tile) === TerrainType.Mountain &&
this.random.chance(2)
) {
continue;
+8 -7
View File
@@ -23,7 +23,7 @@ export class MirvExecution implements Execution {
private mg: Game;
private nuke: Unit;
private nuke: Unit | null = null;
private mirvRange = 1500;
private warheadCount = 350;
@@ -64,9 +64,9 @@ export class MirvExecution implements Execution {
}
tick(ticks: number): void {
if (this.nuke == null) {
if (this.nuke === null) {
const spawn = this.player.canBuild(UnitType.MIRV, this.dst);
if (spawn == false) {
if (spawn === false) {
consolex.warn(`cannot build MIRV`);
this.active = false;
return;
@@ -112,12 +112,13 @@ export class MirvExecution implements Execution {
}
private separate() {
if (this.nuke === null) throw new Error("uninitialized");
const dsts: TileRef[] = [this.dst];
let attempts = 1000;
while (attempts > 0 && dsts.length < this.warheadCount) {
attempts--;
const potential = this.randomLand(this.dst, dsts);
if (potential == null) {
if (potential === null) {
continue;
}
dsts.push(potential);
@@ -144,10 +145,10 @@ export class MirvExecution implements Execution {
}
if (this.targetPlayer.isPlayer()) {
const alliance = this.player.allianceWith(this.targetPlayer);
if (alliance != null) {
if (alliance !== null) {
this.player.breakAlliance(alliance);
}
if (this.targetPlayer != this.player) {
if (this.targetPlayer !== this.player) {
this.targetPlayer.updateRelation(this.player, -100);
}
}
@@ -178,7 +179,7 @@ export class MirvExecution implements Execution {
if (this.mg.euclideanDistSquared(tile, ref) > mirvRange2) {
continue;
}
if (this.mg.owner(tile) != this.targetPlayer) {
if (this.mg.owner(tile) !== this.targetPlayer) {
continue;
}
for (const t of taken) {