mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-24 04:48:00 +00:00
keep
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}),
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user