move methods from GameRunner to PlayerImpl

This commit is contained in:
Evan
2025-01-24 10:25:47 -08:00
parent 7325cfc7e6
commit 5f5f8ddf64
3 changed files with 97 additions and 95 deletions
+6 -92
View File
@@ -110,8 +110,8 @@ export class GameRunner {
const player = this.game.player(playerID)
const tile = this.game.ref(x, y)
const actions = {
canBoat: this.canBoat(player, tile),
canAttack: this.canAttack(player, tile),
canBoat: player.canBoat(tile),
canAttack: player.canAttack(tile),
buildableUnits: Object.values(UnitType).filter(ut => player.canBuild(ut, tile) != false),
canSendEmojiAllPlayers: player.canSendEmoji(AllPlayers)
} as PlayerActions
@@ -130,97 +130,11 @@ export class GameRunner {
return actions
}
public playerProfile(playerID: number): PlayerProfile {
const player = this.game.players().filter(p => p.smallID() == playerID)[0];
if (!player) {
throw new Error(`player with id ${playerID} not found`);
}
const rel = {
relations: Object.fromEntries(
player.allRelationsSorted()
.map(({ player, relation }) => [player.smallID(), relation])
),
alliances: player.alliances().map(a => a.other(player).smallID())
};
return rel
}
private canBoat(myPlayer: Player, tile: TileRef): boolean {
const other = this.game.owner(tile)
if (myPlayer.units(UnitType.TransportShip).length >= this.game.config().boatMaxNumber()) {
return false
}
let myPlayerBordersOcean = false
for (const bt of myPlayer.borderTiles()) {
if (this.game.isOceanShore(bt)) {
myPlayerBordersOcean = true
break
}
}
let otherPlayerBordersOcean = false
if (!this.game.hasOwner(tile)) {
otherPlayerBordersOcean = true
} else {
for (const bt of (other as Player).borderTiles()) {
if (this.game.isOceanShore(bt)) {
otherPlayerBordersOcean = true
break
}
}
}
if (other.isPlayer() && myPlayer.allianceWith(other)) {
return false
}
let nearOcean = false
for (const t of this.game.bfs(tile, andFN((gm, t) => gm.ownerID(t) == gm.ownerID(tile) && gm.isLand(t), manhattanDistFN(tile, 25)))) {
if (this.game.isOceanShore(t)) {
nearOcean = true
break
}
}
if (!nearOcean) {
return false
}
if (myPlayerBordersOcean && otherPlayerBordersOcean) {
const dst = targetTransportTile(this.game, tile)
if (dst != null) {
if (myPlayer.canBuild(UnitType.TransportShip, dst)) {
return true
}
}
}
}
private canAttack(myPlayer: Player, tile: TileRef): boolean {
if (this.game.owner(tile) == myPlayer) {
return false
}
// TODO: fix event bus
if (this.game.hasOwner(tile) && myPlayer.isAlliedWith(this.game.owner(tile) as Player)) {
// this.eventBus.emit(new DisplayMessageEvent("Cannot attack ally", MessageType.WARN))
return false
}
if (!this.game.isLand(tile)) {
return false
}
if (this.game.hasOwner(tile)) {
return myPlayer.sharesBorderWith(this.game.owner(tile))
} else {
for (const t of this.game.bfs(tile, andFN((gm, t) => !gm.hasOwner(t) && gm.isLand(t), manhattanDistFN(tile, 200)))) {
for (const n of this.game.neighbors(t)) {
if (this.game.owner(n) == myPlayer) {
return true
}
}
}
return false
const player = this.game.playerBySmallID(playerID)
if (!player.isPlayer()) {
throw new Error(`player with id ${playerID} not found`)
}
return player.playerProfile()
}
}
+3
View File
@@ -283,6 +283,9 @@ export interface Player {
// Misc
executions(): Execution[]
toUpdate(): PlayerUpdate
playerProfile(): PlayerProfile
canBoat(tile: TileRef): boolean
canAttack(tile: TileRef)
}
export interface Game extends GameMap {
+88 -3
View File
@@ -1,14 +1,14 @@
import { Player, PlayerInfo, PlayerID, PlayerType, TerraNullius, Cell, Execution, AllianceRequest, MutableAlliance, Alliance, Tick, AllPlayers, Gold, UnitType, Unit, Relation, EmojiMessage } from "./Game";
import { Player, PlayerInfo, PlayerID, PlayerType, TerraNullius, Cell, Execution, AllianceRequest, MutableAlliance, Alliance, Tick, AllPlayers, Gold, UnitType, Unit, Relation, EmojiMessage, PlayerProfile } from "./Game";
import { PlayerUpdate } from "./GameUpdates";
import { GameUpdateType } from "./GameUpdates";
import { ClientID } from "../Schemas";
import { assertNever, closestOceanShoreFromPlayer, distSortUnit, simpleHash, sourceDstOceanShore, within } from "../Util";
import { assertNever, closestOceanShoreFromPlayer, distSortUnit, simpleHash, sourceDstOceanShore, targetTransportTile, within } from "../Util";
import { CellString, GameImpl } from "./GameImpl";
import { UnitImpl } from "./UnitImpl";
import { MessageType } from './Game';
import { renderTroops } from "../../client/Utils";
import { TerraNulliusImpl } from "./TerraNulliusImpl";
import { manhattanDistFN, TileRef } from "./GameMap";
import { andFN, manhattanDistFN, TileRef } from "./GameMap";
import { Emoji } from "discord.js";
interface Target {
@@ -548,4 +548,89 @@ export class PlayerImpl implements Player {
toString(): string {
return `Player:{name:${this.info().name},clientID:${this.info().clientID},isAlive:${this.isAlive()},troops:${this._troops},numTileOwned:${this.numTilesOwned()}}]`;
}
public playerProfile(): PlayerProfile {
const rel = {
relations: Object.fromEntries(
this.allRelationsSorted()
.map(({ player, relation }) => [player.smallID(), relation])
),
alliances: this.alliances().map(a => a.other(this).smallID())
};
return rel
}
public canBoat(tile: TileRef): boolean {
const other = this.mg.owner(tile)
if (this.units(UnitType.TransportShip).length >= this.mg.config().boatMaxNumber()) {
return false
}
let myPlayerBordersOcean = false
for (const bt of this.borderTiles()) {
if (this.mg.isOceanShore(bt)) {
myPlayerBordersOcean = true
break
}
}
let otherPlayerBordersOcean = false
if (!this.mg.hasOwner(tile)) {
otherPlayerBordersOcean = true
} else {
for (const bt of (other as Player).borderTiles()) {
if (this.mg.isOceanShore(bt)) {
otherPlayerBordersOcean = true
break
}
}
}
if (other.isPlayer() && this.allianceWith(other)) {
return false
}
let nearOcean = false
for (const t of this.mg.bfs(tile, andFN((gm, t) => gm.ownerID(t) == gm.ownerID(tile) && gm.isLand(t), manhattanDistFN(tile, 25)))) {
if (this.mg.isOceanShore(t)) {
nearOcean = true
break
}
}
if (!nearOcean) {
return false
}
if (myPlayerBordersOcean && otherPlayerBordersOcean) {
const dst = targetTransportTile(this.mg, tile)
if (dst != null) {
if (this.canBuild(UnitType.TransportShip, dst)) {
return true
}
}
}
}
public canAttack(tile: TileRef): boolean {
if (this.mg.owner(tile) == this) {
return false
}
if (this.mg.hasOwner(tile) && this.isAlliedWith(this.mg.owner(tile) as Player)) {
return false
}
if (!this.mg.isLand(tile)) {
return false
}
if (this.mg.hasOwner(tile)) {
return this.sharesBorderWith(this.mg.owner(tile))
} else {
for (const t of this.mg.bfs(tile, andFN((gm, t) => !gm.hasOwner(t) && gm.isLand(t), manhattanDistFN(tile, 200)))) {
for (const n of this.mg.neighbors(t)) {
if (this.mg.owner(n) == this) {
return true
}
}
}
return false
}
}
}