mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-04 14:26:10 +00:00
create territoryBound, have player execution check units for capture
fix bug where PortExecution tries to get random element from empty list and crashes
This commit is contained in:
@@ -12,26 +12,32 @@ export class DefaultConfig implements Config {
|
||||
case UnitType.TransportShip:
|
||||
return {
|
||||
cost: 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Destroyer:
|
||||
return {
|
||||
cost: 100_000
|
||||
cost: 100_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Port:
|
||||
return {
|
||||
cost: 300_000
|
||||
cost: 300_000,
|
||||
territoryBound: true
|
||||
}
|
||||
case UnitType.Nuke:
|
||||
return {
|
||||
cost: 1_000_000
|
||||
cost: 1_000_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.TradeShip:
|
||||
return {
|
||||
cost: 0
|
||||
cost: 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.MissileSilo:
|
||||
return {
|
||||
cost: 1_000_000
|
||||
cost: 1_000_000,
|
||||
territoryBound: true
|
||||
}
|
||||
default:
|
||||
assertNever(type)
|
||||
|
||||
@@ -34,10 +34,6 @@ export class MissileSiloExecution implements Execution {
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
if (this.silo.tile().owner() != this.silo.owner()) {
|
||||
this.silo.setOwner(this.silo.tile().owner() as Player)
|
||||
this.player = this.silo.owner()
|
||||
}
|
||||
}
|
||||
|
||||
owner(): MutablePlayer {
|
||||
|
||||
@@ -46,6 +46,21 @@ export class PlayerExecution implements Execution {
|
||||
}
|
||||
}
|
||||
|
||||
this.player.units().forEach(u => {
|
||||
const tileOwner = u.tile().owner()
|
||||
if (u.info().territoryBound) {
|
||||
if (tileOwner.isPlayer()) {
|
||||
if (tileOwner != this.player) {
|
||||
this.mg.player(tileOwner.id()).captureUnit(u)
|
||||
}
|
||||
} else {
|
||||
u.delete()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
if (ticks - this.lastCalc > this.ticksPerClusterCalc) {
|
||||
this.lastCalc = ticks
|
||||
const start = performance.now()
|
||||
|
||||
@@ -46,17 +46,6 @@ export class PortExecution implements Execution {
|
||||
this.port = this.player.buildUnit(UnitType.Port, 0, spawns[0])
|
||||
}
|
||||
|
||||
|
||||
if (!this.port.tile().hasOwner()) {
|
||||
this.port.delete()
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
if (this.port.tile().owner() != this.port.owner()) {
|
||||
this.port.setOwner(this.port.tile().owner() as Player)
|
||||
this.player = this.port.owner()
|
||||
}
|
||||
|
||||
const allPorts = this.mg.units(UnitType.Port)
|
||||
.filter(u => u.owner() != this.player)
|
||||
if (allPorts.length == 0) {
|
||||
@@ -82,7 +71,7 @@ export class PortExecution implements Execution {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.random.chance(50)) {
|
||||
if (this.portPaths.size > 0 && this.random.chance(50)) {
|
||||
const port = this.random.randElement(
|
||||
Array.from(this.portPaths.keys())
|
||||
.filter(p => this.port.owner().isAlliedWith(p.owner()))
|
||||
|
||||
@@ -24,6 +24,8 @@ export enum GameMap {
|
||||
|
||||
export interface UnitInfo {
|
||||
cost: Gold
|
||||
// Determines if its owner changes when its tile is conquered.
|
||||
territoryBound: boolean
|
||||
}
|
||||
|
||||
export enum UnitType {
|
||||
@@ -155,6 +157,7 @@ export interface Unit {
|
||||
tile(): Tile
|
||||
owner(): Player
|
||||
isActive(): boolean
|
||||
info(): UnitInfo
|
||||
}
|
||||
|
||||
export interface MutableUnit extends Unit {
|
||||
@@ -162,7 +165,6 @@ export interface MutableUnit extends Unit {
|
||||
owner(): MutablePlayer
|
||||
setTroops(troops: number): void
|
||||
delete(): void
|
||||
setOwner(newOwner: Player): void
|
||||
}
|
||||
|
||||
export interface TerraNullius {
|
||||
@@ -247,6 +249,7 @@ export interface MutablePlayer extends Player {
|
||||
removeTroops(troops: number): number
|
||||
|
||||
buildUnit(type: UnitType, troops: number, tile: Tile): MutableUnit
|
||||
captureUnit(unit: MutableUnit): void
|
||||
}
|
||||
|
||||
export interface Game {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit } from "./Game";
|
||||
import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit, MutableUnit } from "./Game";
|
||||
import { ClientID } from "../Schemas";
|
||||
import { assertNever, bfs, closestOceanShoreFromPlayer, dist, distSortUnit, manhattanDist, manhattanDistWrapped, processName, simpleHash, sourceDstOceanShore } from "../Util";
|
||||
import { CellString, GameImpl } from "./GameImpl";
|
||||
@@ -81,6 +81,7 @@ export class PlayerImpl implements MutablePlayer {
|
||||
return this._units.filter(u => ts.has(u.type()));
|
||||
}
|
||||
|
||||
|
||||
sharesBorderWith(other: Player | TerraNullius): boolean {
|
||||
for (const border of this._borderTiles) {
|
||||
for (const neighbor of border.neighbors()) {
|
||||
@@ -319,6 +320,16 @@ export class PlayerImpl implements MutablePlayer {
|
||||
return toRemove
|
||||
}
|
||||
|
||||
captureUnit(unit: MutableUnit): void {
|
||||
if (unit.owner() == this) {
|
||||
throw new Error(`Cannot capture unit, ${this} already owns ${unit}`)
|
||||
}
|
||||
const prev = unit.owner();
|
||||
(prev as PlayerImpl)._units = (prev as PlayerImpl)._units.filter(u => u != unit);
|
||||
(unit as UnitImpl)._owner = this
|
||||
this._units.push(unit as UnitImpl)
|
||||
}
|
||||
|
||||
buildUnit(type: UnitType, troops: number, spawnTile: Tile): UnitImpl {
|
||||
const b = new UnitImpl(type, this.gs, spawnTile, troops, this);
|
||||
this._units.push(b);
|
||||
@@ -328,6 +339,7 @@ export class PlayerImpl implements MutablePlayer {
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
canBuild(unitType: UnitType, targetTile: Tile): Tile | false {
|
||||
const cost = this.gs.unitInfo(unitType).cost
|
||||
if (!this.isAlive() || this.gold() < cost) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MutableUnit, Tile, TerraNullius, UnitType, Player } from "./Game";
|
||||
import { MutableUnit, Tile, TerraNullius, UnitType, Player, UnitInfo } from "./Game";
|
||||
import { GameImpl } from "./GameImpl";
|
||||
import { PlayerImpl } from "./PlayerImpl";
|
||||
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||
@@ -12,7 +12,7 @@ export class UnitImpl implements MutableUnit {
|
||||
private g: GameImpl,
|
||||
private _tile: Tile,
|
||||
private _troops: number,
|
||||
private _owner: PlayerImpl,
|
||||
public _owner: PlayerImpl,
|
||||
) { }
|
||||
|
||||
type(): UnitType {
|
||||
@@ -37,6 +37,10 @@ export class UnitImpl implements MutableUnit {
|
||||
return this._owner;
|
||||
}
|
||||
|
||||
info(): UnitInfo {
|
||||
return this.g.unitInfo(this._type)
|
||||
}
|
||||
|
||||
setOwner(newOwner: Player): void {
|
||||
this._owner = newOwner as PlayerImpl
|
||||
this.g.fireUnitUpdateEvent(this, this.tile())
|
||||
|
||||
Reference in New Issue
Block a user