mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-26 08:24:36 +00:00
npcs build ports
This commit is contained in:
@@ -80,8 +80,10 @@ export class UnitLayer implements Layer {
|
||||
break;
|
||||
case UnitType.TradeShip:
|
||||
this.handleTradeShipEvent(event)
|
||||
break;
|
||||
case UnitType.AtomBomb:
|
||||
this.handleNuke(event)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DefaultConfig } from "./DefaultConfig";
|
||||
export const devConfig = new class extends DefaultConfig {
|
||||
unitInfo(type: UnitType): UnitInfo {
|
||||
const info = super.unitInfo(type)
|
||||
// info.cost = 0
|
||||
info.cost = 0
|
||||
return info
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tile } from "../game/Game"
|
||||
import { Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tile, UnitType } from "../game/Game"
|
||||
import { PseudoRandom } from "../PseudoRandom"
|
||||
import { and, bfs, dist, simpleHash } from "../Util";
|
||||
import { AttackExecution } from "./AttackExecution";
|
||||
import { TransportShipExecution } from "./TransportShipExecution";
|
||||
import { SpawnExecution } from "./SpawnExecution";
|
||||
import { PortExecution } from "./PortExecution";
|
||||
|
||||
export class FakeHumanExecution implements Execution {
|
||||
|
||||
@@ -35,7 +36,6 @@ export class FakeHumanExecution implements Execution {
|
||||
}
|
||||
|
||||
tick(ticks: number) {
|
||||
|
||||
if (this.mg.inSpawnPhase()) {
|
||||
if (ticks % this.random.nextInt(5, 30) == 0) {
|
||||
const rl = this.randomLand()
|
||||
@@ -72,27 +72,13 @@ export class FakeHumanExecution implements Execution {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.player.troops() > 100_000 && this.player.targetTroopRatio() > .7) {
|
||||
this.player.setTargetTroopRatio(.7)
|
||||
}
|
||||
|
||||
this.handleAllianceRequests()
|
||||
|
||||
if (ticks % 100 == 0) {
|
||||
this.enemy = null
|
||||
}
|
||||
|
||||
if (this.enemy == null) {
|
||||
this.enemy = this.mg.executions()
|
||||
.filter(e => e instanceof AttackExecution)
|
||||
.map(e => e as AttackExecution)
|
||||
.filter(e => e.targetID() == this.player.id())
|
||||
.map(e => e.owner())
|
||||
.find(enemy => enemy && enemy.type() == PlayerType.Human)
|
||||
}
|
||||
|
||||
if (this.enemy) {
|
||||
if (this.player.sharesBorderWith(this.enemy)) {
|
||||
this.sendAttack(this.enemy)
|
||||
}
|
||||
return
|
||||
}
|
||||
this.handleEnemies()
|
||||
this.handleUnits()
|
||||
|
||||
|
||||
if (this.neighborsTerraNullius) {
|
||||
@@ -136,6 +122,39 @@ export class FakeHumanExecution implements Execution {
|
||||
}
|
||||
}
|
||||
|
||||
handleEnemies() {
|
||||
if (this.mg.ticks() % 100 == 0) {
|
||||
this.enemy = null
|
||||
}
|
||||
|
||||
if (this.enemy == null) {
|
||||
this.enemy = this.mg.executions()
|
||||
.filter(e => e instanceof AttackExecution)
|
||||
.map(e => e as AttackExecution)
|
||||
.filter(e => e.targetID() == this.player.id())
|
||||
.map(e => e.owner())
|
||||
.find(enemy => enemy && enemy.type() == PlayerType.Human)
|
||||
}
|
||||
|
||||
if (this.enemy) {
|
||||
if (this.player.sharesBorderWith(this.enemy)) {
|
||||
this.sendAttack(this.enemy)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private handleUnits() {
|
||||
if (this.player.units(UnitType.Port).length == 0 && this.player.gold() > this.mg.unitInfo(UnitType.Port).cost) {
|
||||
const oceanTiles = Array.from(this.player.borderTiles()).filter(t => t.isOceanShore())
|
||||
if (oceanTiles.length > 0) {
|
||||
const buildTile = this.random.randElement(oceanTiles)
|
||||
this.mg.addExecution(new PortExecution(this.player.id(), buildTile.cell()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleAllianceRequests() {
|
||||
for (const req of this.player.incomingAllianceRequests()) {
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ export class PortExecution implements Execution {
|
||||
|
||||
private active = true
|
||||
private mg: MutableGame
|
||||
private player: MutablePlayer
|
||||
private port: MutableUnit
|
||||
private random: PseudoRandom
|
||||
private portPaths = new Map<MutableUnit, Tile[]>()
|
||||
@@ -22,20 +21,20 @@ export class PortExecution implements Execution {
|
||||
|
||||
init(mg: MutableGame, ticks: number): void {
|
||||
this.mg = mg
|
||||
this.player = mg.player(this._owner)
|
||||
this.random = new PseudoRandom(mg.ticks())
|
||||
}
|
||||
|
||||
tick(ticks: number): void {
|
||||
if (this.port == null) {
|
||||
const tile = this.mg.tile(this.cell)
|
||||
if (!this.player.canBuild(UnitType.Port, tile)) {
|
||||
console.warn(`player ${this.player} cannot build port at ${this.cell}`)
|
||||
const player = this.mg.player(this._owner)
|
||||
if (!player.canBuild(UnitType.Port, tile)) {
|
||||
console.warn(`player ${player} cannot build port at ${this.cell}`)
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
const spawns = Array.from(bfs(tile, dist(tile, 20)))
|
||||
.filter(t => t.isOceanShore() && t.owner() == this.player)
|
||||
.filter(t => t.isOceanShore() && t.owner() == player)
|
||||
.sort((a, b) => manhattanDist(a.cell(), tile.cell()) - manhattanDist(b.cell(), tile.cell()))
|
||||
|
||||
if (spawns.length == 0) {
|
||||
@@ -43,15 +42,14 @@ export class PortExecution implements Execution {
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
this.port = this.player.buildUnit(UnitType.Port, 0, spawns[0])
|
||||
this.port = player.buildUnit(UnitType.Port, 0, spawns[0])
|
||||
}
|
||||
|
||||
const allPorts = this.mg.units(UnitType.Port)
|
||||
.filter(u => u.owner() != this.player)
|
||||
if (allPorts.length == 0) {
|
||||
return
|
||||
}
|
||||
for (const port of allPorts) {
|
||||
|
||||
const alliedPorts = this.player().alliances().map(a => a.other(this.player())).flatMap(p => p.units(UnitType.Port))
|
||||
const alliedPortsSet = new Set(alliedPorts)
|
||||
|
||||
for (const port of alliedPorts) {
|
||||
if (this.computingPaths.has(port)) {
|
||||
const aStar = this.computingPaths.get(port)
|
||||
switch (aStar.compute()) {
|
||||
@@ -64,24 +62,25 @@ export class PortExecution implements Execution {
|
||||
console.warn(`path not found to port`)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (!this.portPaths.has(port)) {
|
||||
this.computingPaths.set(port, new AStar(this.port.tile(), port.tile(), t => t.isWater(), 10_000, 20))
|
||||
} else if (!this.portPaths.has(port)) {
|
||||
this.computingPaths.set(port, new AStar(this.port.tile(), port.tile(), t => t.isWater(), 2000, 100))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for (const port of this.portPaths.keys()) {
|
||||
if (!port.isActive()) {
|
||||
if (!port.isActive() || !alliedPortsSet.has(port)) {
|
||||
this.portPaths.delete(port)
|
||||
this.computingPaths.delete(port)
|
||||
}
|
||||
}
|
||||
|
||||
const allyPorts = Array.from(this.portPaths.keys())
|
||||
.filter(p => this.port.owner().isAlliedWith(p.owner()))
|
||||
if (allPorts.length > 0 && this.random.chance(50)) {
|
||||
const port = this.random.randElement(allPorts)
|
||||
if (alliedPorts.length > 0 && this.random.chance(50)) {
|
||||
const port = this.random.randElement(alliedPorts)
|
||||
const path = this.portPaths.get(port)
|
||||
this.mg.addExecution(new TradeShipExecution(this._owner, this.port, port, path))
|
||||
if (path != null) {
|
||||
this.mg.addExecution(new TradeShipExecution(this._owner, this.port, port, path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,4 +96,8 @@ export class PortExecution implements Execution {
|
||||
return false
|
||||
}
|
||||
|
||||
player(): MutablePlayer {
|
||||
return this.port.owner()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -328,6 +328,7 @@ export class PlayerImpl implements MutablePlayer {
|
||||
(prev as PlayerImpl)._units = (prev as PlayerImpl)._units.filter(u => u != unit);
|
||||
(unit as UnitImpl)._owner = this
|
||||
this._units.push(unit as UnitImpl)
|
||||
this.gs.fireUnitUpdateEvent(unit, unit.tile())
|
||||
}
|
||||
|
||||
buildUnit(type: UnitType, troops: number, spawnTile: Tile): UnitImpl {
|
||||
|
||||
Reference in New Issue
Block a user