diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index a5dbd79db..230499652 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -1,6 +1,6 @@ import { Colord } from "colord"; import { Theme } from "../../../core/configuration/Config"; -import { Boat, BoatEvent, Cell, Game, Tile } from "../../../core/game/Game"; +import { Unit, BoatEvent, Cell, Game, Tile } from "../../../core/game/Game"; import { bfs, dist } from "../../../core/Util"; import { Layer } from "./Layer"; import { EventBus } from "../../../core/EventBus"; @@ -10,7 +10,7 @@ export class UnitLayer implements Layer { private context: CanvasRenderingContext2D private imageData: ImageData - private boatToTrail = new Map>() + private boatToTrail = new Map>() private theme: Theme = null diff --git a/src/client/graphics/layers/radial/RadialMenu.ts b/src/client/graphics/layers/radial/RadialMenu.ts index 48a8010f1..ab087ab66 100644 --- a/src/client/graphics/layers/radial/RadialMenu.ts +++ b/src/client/graphics/layers/radial/RadialMenu.ts @@ -1,5 +1,5 @@ import { EventBus } from "../../../../core/EventBus"; -import { AllPlayers, Cell, Game, Player } from "../../../../core/game/Game"; +import { AllPlayers, Cell, Game, Player, UnitType } from "../../../../core/game/Game"; import { ClientID } from "../../../../core/Schemas"; import { and, bfs, dist, manhattanDist, manhattanDistWrapped, sourceDstOceanShore } from "../../../../core/Util"; import { ContextMenuEvent, MouseUpEvent } from "../../../InputHandler"; @@ -305,7 +305,7 @@ export class RadialMenu implements Layer { if (!tile.isLand()) { return } - if (myPlayer.boats().length >= this.game.config().boatMaxNumber()) { + if (myPlayer.units(UnitType.TransportShip).length >= this.game.config().boatMaxNumber()) { return } diff --git a/src/core/execution/BoatAttackExecution.ts b/src/core/execution/BoatAttackExecution.ts index 23ae6bf4c..c653ee376 100644 --- a/src/core/execution/BoatAttackExecution.ts +++ b/src/core/execution/BoatAttackExecution.ts @@ -1,5 +1,5 @@ import { PriorityQueue } from "@datastructures-js/priority-queue"; -import { Boat, Cell, Execution, MutableBoat, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile, TileEvent } from "../game/Game"; +import { Unit, Cell, Execution, MutableUnit, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile, TileEvent, UnitType } from "../game/Game"; import { and, bfs, manhattanDistWrapped, sourceDstOceanShore } from "../Util"; import { AttackExecution } from "./AttackExecution"; import { DisplayMessageEvent, MessageType } from "../../client/graphics/layers/EventsDisplay"; @@ -24,7 +24,7 @@ export class BoatAttackExecution implements Execution { private currTileIndex: number = 0 - private boat: MutableBoat + private boat: MutableUnit private aStarPre: AStar private aStarComplete: AStar @@ -48,7 +48,7 @@ export class BoatAttackExecution implements Execution { this.attacker = mg.player(this.attackerID) - if (this.attacker.boats().length >= mg.config().boatMaxNumber()) { + if (this.attacker.units(UnitType.TransportShip).length >= mg.config().boatMaxNumber()) { mg.displayMessage(`No boats available, max ${mg.config().boatMaxNumber()}`, MessageType.WARN, this.attackerID) this.active = false this.attacker.addTroops(this.troops) diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index ddfae6680..63708290c 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -25,6 +25,10 @@ export enum GameMap { Mena } +export enum UnitType { + TransportShip +} + export class Item { constructor(public readonly name: string, public readonly cost: Gold) { } } @@ -145,18 +149,17 @@ export interface Tile { onShore(): boolean } -export interface Boat { +export interface Unit { + type(): UnitType troops(): number tile(): Tile owner(): Player - target(): Player | TerraNullius isActive(): boolean } -export interface MutableBoat extends Boat { +export interface MutableUnit extends Unit { move(tile: Tile): void owner(): MutablePlayer - target(): MutablePlayer | TerraNullius setTroops(troops: number): void delete(): void } @@ -175,7 +178,7 @@ export interface Player { clientID(): ClientID id(): PlayerID type(): PlayerType - boats(): Boat[] + units(...types: UnitType[]): Unit[] ownsTile(cell: Cell): boolean isAlive(): boolean borderTiles(): ReadonlySet @@ -216,14 +219,14 @@ export interface MutablePlayer extends Player { relinquish(tile: Tile): void executions(): Execution[] neighbors(): (MutablePlayer | TerraNullius)[] - boats(): MutableBoat[] + units(...types: UnitType[]): MutableUnit[] incomingAllianceRequests(): MutableAllianceRequest[] outgoingAllianceRequests(): MutableAllianceRequest[] alliances(): MutableAlliance[] allianceWith(other: Player): MutableAlliance | null breakAlliance(alliance: Alliance): void createAllianceRequest(recipient: Player): MutableAllianceRequest - addBoat(troops: number, tile: Tile, target: Player | TerraNullius): MutableBoat + addBoat(troops: number, tile: Tile, target: Player | TerraNullius): MutableUnit target(other: Player): void targets(): MutablePlayer[] transitiveTargets(): MutablePlayer[] @@ -263,7 +266,7 @@ export interface Game { nations(): Nation[] config(): Config displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void - boats(): Boat[] + boats(): Unit[] } export interface MutableGame extends Game { @@ -272,7 +275,7 @@ export interface MutableGame extends Game { players(): MutablePlayer[] addPlayer(playerInfo: PlayerInfo, manpower: number): MutablePlayer executions(): Execution[] - boats(): MutableBoat[] + boats(): MutableUnit[] } export class TileEvent implements GameEvent { @@ -284,7 +287,7 @@ export class PlayerEvent implements GameEvent { } export class BoatEvent implements GameEvent { - constructor(public readonly boat: Boat, public oldTile: Tile) { } + constructor(public readonly boat: Unit, public oldTile: Tile) { } } export class AllianceRequestEvent implements GameEvent { diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 117c537ac..45f44517a 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -1,16 +1,16 @@ -import {info} from "console"; -import {Config} from "../configuration/Config"; -import {EventBus} from "../EventBus"; -import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, BoatEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation} from "./Game"; -import {TerrainMap} from "./TerrainMapLoader"; -import {PlayerImpl} from "./PlayerImpl"; -import {TerraNulliusImpl} from "./TerraNulliusImpl"; -import {TileImpl} from "./TileImpl"; -import {AllianceRequestImpl} from "./AllianceRequestImpl"; -import {AllianceImpl} from "./AllianceImpl"; -import {ClientID} from "../Schemas"; -import {DisplayMessageEvent, MessageType} from "../../client/graphics/layers/EventsDisplay"; -import {BoatImpl} from "./BoatImpl"; +import { info } from "console"; +import { Config } from "../configuration/Config"; +import { EventBus } from "../EventBus"; +import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Unit, BoatEvent as UnitEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation } from "./Game"; +import { TerrainMap } from "./TerrainMapLoader"; +import { PlayerImpl } from "./PlayerImpl"; +import { TerraNulliusImpl } from "./TerraNulliusImpl"; +import { TileImpl } from "./TileImpl"; +import { AllianceRequestImpl } from "./AllianceRequestImpl"; +import { AllianceImpl } from "./AllianceImpl"; +import { ClientID } from "../Schemas"; +import { DisplayMessageEvent, MessageType } from "../../client/graphics/layers/EventsDisplay"; +import { UnitImpl } from "./UnitImpl"; export function createGame(terrainMap: TerrainMap, eventBus: EventBus, config: Config): Game { return new GameImpl(terrainMap, eventBus, config) @@ -58,8 +58,8 @@ export class GameImpl implements MutableGame { n.strength )) } - boats(): BoatImpl[] { - return Array.from(this._players.values()).flatMap(p => p._boats) + boats(): UnitImpl[] { + return Array.from(this._players.values()).flatMap(p => p._units) } nations(): Nation[] { return this.nations_ @@ -354,8 +354,8 @@ export class GameImpl implements MutableGame { return false } - public fireBoatUpdateEvent(boat: Boat, oldTile: Tile) { - this.eventBus.emit(new BoatEvent(boat, oldTile)) + public fireUnitUpdateEvent(boat: Unit, oldTile: Tile) { + this.eventBus.emit(new UnitEvent(boat, oldTile)) } public breakAlliance(breaker: Player, alliance: Alliance) { diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index eb3b0b03c..0079aa72d 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -1,8 +1,8 @@ -import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold } from "./Game"; +import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType } from "./Game"; import { ClientID } from "../Schemas"; import { processName, simpleHash } from "../Util"; import { CellString, GameImpl } from "./GameImpl"; -import { BoatImpl } from "./BoatImpl"; +import { UnitImpl } from "./UnitImpl"; import { TileImpl } from "./TileImpl"; import { TerraNulliusImpl } from "./TerraNulliusImpl"; import { MessageType } from "../../client/graphics/layers/EventsDisplay"; @@ -29,7 +29,7 @@ export class PlayerImpl implements MutablePlayer { public _borderTiles: Set = new Set(); - public _boats: BoatImpl[] = []; + public _units: UnitImpl[] = []; public _tiles: Map = new Map(); private _name: string; @@ -73,15 +73,16 @@ export class PlayerImpl implements MutablePlayer { } - addBoat(troops: number, tile: Tile, target: Player | TerraNullius): BoatImpl { - const b = new BoatImpl(this.gs, tile, troops, this, target as PlayerImpl | TerraNulliusImpl); - this._boats.push(b); - this.gs.fireBoatUpdateEvent(b, b.tile()); + addBoat(troops: number, tile: Tile): UnitImpl { + const b = new UnitImpl(UnitType.TransportShip, this.gs, tile, troops, this); + this._units.push(b); + this.gs.fireUnitUpdateEvent(b, b.tile()); return b; } - boats(): BoatImpl[] { - return this._boats; + units(...types: UnitType[]): UnitImpl[] { + const ts = new Set(types) + return this._units.filter(u => ts.has(u.type())); } sharesBorderWith(other: Player | TerraNullius): boolean { diff --git a/src/core/game/BoatImpl.ts b/src/core/game/UnitImpl.ts similarity index 55% rename from src/core/game/BoatImpl.ts rename to src/core/game/UnitImpl.ts index fe13cc3c6..249c30ea3 100644 --- a/src/core/game/BoatImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -1,24 +1,28 @@ -import {MutableBoat, Tile, TerraNullius} from "./Game"; -import {GameImpl} from "./GameImpl"; -import {PlayerImpl} from "./PlayerImpl"; -import {TerraNulliusImpl} from "./TerraNulliusImpl"; +import { MutableUnit, Tile, TerraNullius, UnitType } from "./Game"; +import { GameImpl } from "./GameImpl"; +import { PlayerImpl } from "./PlayerImpl"; +import { TerraNulliusImpl } from "./TerraNulliusImpl"; -export class BoatImpl implements MutableBoat { +export class UnitImpl implements MutableUnit { private _active = true; constructor( + private _type: UnitType, private g: GameImpl, private _tile: Tile, private _troops: number, private _owner: PlayerImpl, - private _target: PlayerImpl | TerraNulliusImpl ) { } + type(): UnitType { + return this._type + } + move(tile: Tile): void { const oldTile = this._tile; this._tile = tile; - this.g.fireBoatUpdateEvent(this, oldTile); + this.g.fireUnitUpdateEvent(this, oldTile); } setTroops(troops: number): void { this._troops = troops; @@ -32,13 +36,11 @@ export class BoatImpl implements MutableBoat { owner(): PlayerImpl { return this._owner; } - target(): PlayerImpl | TerraNullius { - return this._target; - } + delete(): void { - this._owner._boats = this._owner._boats.filter(b => b != this); + this._owner._units = this._owner._units.filter(b => b != this); this._active = false; - this.g.fireBoatUpdateEvent(this, this._tile); + this.g.fireUnitUpdateEvent(this, this._tile); } isActive(): boolean { return this._active;