mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:40:44 +00:00
use tiles to improve perf
This commit is contained in:
@@ -56,12 +56,12 @@ class Client {
|
||||
this.lobbiesContainer.appendChild(button);
|
||||
});
|
||||
|
||||
// Join first lobby
|
||||
if (!this.hasJoined && lobbies.length > 0) {
|
||||
this.hasJoined = true
|
||||
console.log(`joining lobby ${lobbies[0].id}`)
|
||||
this.joinLobby(lobbies[0].id)
|
||||
}
|
||||
// // Join first lobby
|
||||
// if (!this.hasJoined && lobbies.length > 0) {
|
||||
// this.hasJoined = true
|
||||
// console.log(`joining lobby ${lobbies[0].id}`)
|
||||
// this.joinLobby(lobbies[0].id)
|
||||
// }
|
||||
}
|
||||
|
||||
async fetchLobbies() {
|
||||
|
||||
@@ -95,7 +95,7 @@ export class ClientGame {
|
||||
|
||||
this.renderer.initialize()
|
||||
this.input.initialize()
|
||||
this.executor.spawnBots(500)
|
||||
this.executor.spawnBots(1000)
|
||||
|
||||
|
||||
setInterval(() => this.tick(), 10);
|
||||
@@ -148,7 +148,7 @@ export class ClientGame {
|
||||
const owner = tile.owner()
|
||||
const targetID = owner.isPlayer() ? owner.id() : null
|
||||
if (tile.owner() != this.myPlayer) {
|
||||
if (this.myPlayer.sharesBorderWith(tile.owner())) {
|
||||
if (this.myPlayer.sharesBorderWith(tile.owner())) {
|
||||
this.sendAttackIntent(targetID, cell)
|
||||
} else {
|
||||
// TODO verify on ocean
|
||||
|
||||
@@ -193,15 +193,15 @@ export class GameRenderer {
|
||||
|
||||
tileUpdate(event: TileEvent) {
|
||||
this.paintTile(event.tile)
|
||||
this.gs.neighbors(event.tile.cell()).forEach(c => this.paintTile(this.gs.tile(c)))
|
||||
event.tile.neighbors().forEach(t => this.paintTile(t))
|
||||
}
|
||||
|
||||
playerEvent(event: PlayerEvent) {
|
||||
}
|
||||
|
||||
boatEvent(event: BoatEvent) {
|
||||
this.paintCell(event.boat.cell(), new Colord({r: 255, g: 255, b: 255}))
|
||||
this.gs.neighbors(event.boat.cell()).map(c => this.gs.tile(c)).forEach(t => this.paintTile(t))
|
||||
this.paintCell(event.boat.tile().cell(), new Colord({r: 255, g: 255, b: 255}))
|
||||
this.gs.neighbors(event.boat.tile()).forEach(t => this.paintTile(t))
|
||||
}
|
||||
|
||||
resize(width: number, height: number): void {
|
||||
|
||||
+4
-4
@@ -75,13 +75,13 @@ export interface Tile {
|
||||
|
||||
export interface Boat {
|
||||
troops(): number
|
||||
cell(): Cell
|
||||
tile(): Tile
|
||||
owner(): Player
|
||||
target(): Player | TerraNullius
|
||||
}
|
||||
|
||||
export interface MutableBoat extends Boat {
|
||||
move(cell: Cell): void
|
||||
move(tile: Tile): void
|
||||
owner(): MutablePlayer
|
||||
target(): MutablePlayer | TerraNullius
|
||||
setTroops(troops: number): void
|
||||
@@ -115,7 +115,7 @@ export interface MutablePlayer extends Player {
|
||||
executions(): Execution[]
|
||||
neighbors(): (MutablePlayer | TerraNullius)[]
|
||||
boats(): MutableBoat[]
|
||||
addBoat(troops: number, cell: Cell, target: Player | TerraNullius): MutableBoat
|
||||
addBoat(troops: number, tile: Tile, target: Player | TerraNullius): MutableBoat
|
||||
}
|
||||
|
||||
export interface Game {
|
||||
@@ -124,7 +124,7 @@ export interface Game {
|
||||
players(): Player[]
|
||||
tile(cell: Cell): Tile
|
||||
isOnMap(cell: Cell): boolean
|
||||
neighbors(cell: Cell): Cell[]
|
||||
neighbors(cell: Cell | Tile): Tile[]
|
||||
width(): number
|
||||
height(): number
|
||||
forEachTile(fn: (tile: Tile) => void): void
|
||||
|
||||
+42
-32
@@ -9,6 +9,8 @@ type CellString = string
|
||||
|
||||
class TileImpl implements Tile {
|
||||
|
||||
public _isBorder = false
|
||||
|
||||
constructor(
|
||||
private readonly gs: GameImpl,
|
||||
public _owner: PlayerImpl | TerraNulliusImpl,
|
||||
@@ -24,13 +26,13 @@ class TileImpl implements Tile {
|
||||
|
||||
hasOwner(): boolean {return this._owner != this.gs._terraNullius}
|
||||
owner(): MutablePlayer | TerraNullius {return this._owner}
|
||||
isBorder(): boolean {return this.gs.isBorder(this)}
|
||||
isBorder(): boolean {return this._isBorder}
|
||||
isInterior(): boolean {return this.hasOwner() && !this.isBorder()}
|
||||
cell(): Cell {return this._cell}
|
||||
terrain(): TerrainType {return this._terrain}
|
||||
|
||||
neighbors(): Tile[] {
|
||||
return this.gs.neighbors(this._cell).map(c => this.gs.tile(c))
|
||||
return this.gs.neighbors(this)
|
||||
}
|
||||
|
||||
game(): Game {return this.gs}
|
||||
@@ -40,14 +42,14 @@ export class BoatImpl implements MutableBoat {
|
||||
|
||||
constructor(
|
||||
private g: GameImpl,
|
||||
private _cell: Cell,
|
||||
private _tile: Tile,
|
||||
private _troops: number,
|
||||
private _owner: PlayerImpl,
|
||||
private _target: PlayerImpl | TerraNulliusImpl
|
||||
) { }
|
||||
|
||||
move(cell: Cell): void {
|
||||
this._cell = cell
|
||||
move(tile: Tile): void {
|
||||
this._tile = tile
|
||||
this.g.fireBoatUpdateEvent(this)
|
||||
}
|
||||
setTroops(troops: number): void {
|
||||
@@ -56,8 +58,8 @@ export class BoatImpl implements MutableBoat {
|
||||
troops(): number {
|
||||
return this._troops
|
||||
}
|
||||
cell(): Cell {
|
||||
return this._cell
|
||||
tile(): Tile {
|
||||
return this._tile
|
||||
}
|
||||
owner(): PlayerImpl {
|
||||
return this._owner
|
||||
@@ -77,8 +79,8 @@ export class PlayerImpl implements MutablePlayer {
|
||||
constructor(private gs: GameImpl, public readonly _id: PlayerID, public readonly playerInfo: PlayerInfo, private _troops) {
|
||||
}
|
||||
|
||||
addBoat(troops: number, cell: Cell, target: Player | TerraNullius): BoatImpl {
|
||||
const b = new BoatImpl(this.gs, cell, troops, this, target as PlayerImpl | TerraNulliusImpl)
|
||||
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)
|
||||
return b
|
||||
@@ -184,6 +186,7 @@ export class GameImpl implements MutableGame {
|
||||
private _height: number
|
||||
_terraNullius: TerraNulliusImpl
|
||||
|
||||
|
||||
constructor(terrainMap: TerrainMap, private eventBus: EventBus) {
|
||||
this._terraNullius = new TerraNulliusImpl(this)
|
||||
this._width = terrainMap.width();
|
||||
@@ -281,21 +284,26 @@ export class GameImpl implements MutableGame {
|
||||
&& cell.y < this._height
|
||||
}
|
||||
|
||||
neighbors(cell: Cell): Cell[] {
|
||||
this.assertIsOnMap(cell)
|
||||
const ns = [
|
||||
new Cell(cell.x + 1, cell.y),
|
||||
new Cell(cell.x - 1, cell.y),
|
||||
new Cell(cell.x, cell.y + 1),
|
||||
new Cell(cell.x, cell.y - 1)
|
||||
].filter(c => this.isOnMap(c))
|
||||
neighbors(tile: Tile): Tile[] {
|
||||
this.assertIsOnMap(tile.cell())
|
||||
const x = tile.cell().x
|
||||
const y = tile.cell().y
|
||||
const ns: TileImpl[] = []
|
||||
if (y > 0) {
|
||||
ns.push(this.map[x][y - 1])
|
||||
}
|
||||
if (y < this._height - 1) {
|
||||
ns.push(this.map[x][y + 1])
|
||||
}
|
||||
if (x > 0) {
|
||||
ns.push(this.map[x - 1][y])
|
||||
}
|
||||
if (x < this._width - 1) {
|
||||
ns.push(this.map[x + 1][y])
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
tileNeighbors(tile: Tile): Tile[] {
|
||||
return this.neighbors(tile.cell()).map(c => this.tile(c))
|
||||
}
|
||||
|
||||
private assertIsOnMap(cell: Cell) {
|
||||
if (!this.isOnMap(cell)) {
|
||||
throw new Error(`cell ${cell.toString()} is not on map`)
|
||||
@@ -318,35 +326,37 @@ export class GameImpl implements MutableGame {
|
||||
previousOwner.tiles.delete(cell.toString())
|
||||
previousOwner._borderTiles.delete(cell.toString())
|
||||
previousOwner._borderTileSet.delete(tile)
|
||||
tile._isBorder = false
|
||||
}
|
||||
tile._owner = owner
|
||||
owner.tiles.set(cell.toString(), tile)
|
||||
this.updateBorders(cell)
|
||||
this.updateBorders(tile)
|
||||
this.eventBus.emit(new TileEvent(tile))
|
||||
}
|
||||
|
||||
private updateBorders(cell: Cell) {
|
||||
const cells: Cell[] = []
|
||||
cells.push(cell)
|
||||
this.neighbors(cell).forEach(c => cells.push(c))
|
||||
cells.map(c => this.tile(c)).filter(c => c.hasOwner()).forEach(t => {
|
||||
private updateBorders(tile: Tile) {
|
||||
const tiles: Tile[] = []
|
||||
tiles.push(tile)
|
||||
tile.neighbors().forEach(t => tiles.push(t))
|
||||
tiles.filter(t => t.hasOwner()).forEach(t => {
|
||||
if (this.isBorder(t)) {
|
||||
(t.owner() as PlayerImpl)._borderTiles.set(t.cell().toString(), t);
|
||||
(t.owner() as PlayerImpl)._borderTileSet.add(t)
|
||||
(t.owner() as PlayerImpl)._borderTileSet.add(t);
|
||||
(t as TileImpl)._isBorder = true
|
||||
} else {
|
||||
(t.owner() as PlayerImpl)._borderTiles.delete(t.cell().toString());
|
||||
(t.owner() as PlayerImpl)._borderTileSet.delete(t)
|
||||
(t.owner() as PlayerImpl)._borderTileSet.delete(t);
|
||||
(t as TileImpl)._isBorder = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
isBorder(tile: Tile): boolean {
|
||||
this.assertIsOnMap(tile.cell())
|
||||
if (!tile.hasOwner()) {
|
||||
return false
|
||||
}
|
||||
for (const neighbor of this.neighbors(tile.cell())) {
|
||||
let bordersEnemy = this.tile(neighbor).owner() != tile.owner()
|
||||
for (const neighbor of tile.neighbors()) {
|
||||
let bordersEnemy = tile.owner() != neighbor.owner()
|
||||
if (bordersEnemy) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {manhattanDist} from "../Util";
|
||||
|
||||
export class AttackExecution implements Execution {
|
||||
private active: boolean = true;
|
||||
private toConquer: PriorityQueue<TileContainer> = new PriorityQueue<TileContainer>(11, (a: TileContainer, b: TileContainer) => a.priority - b.priority);
|
||||
private toConquer: PriorityQueue<TileContainer> = new PriorityQueue<TileContainer>(1000, (a: TileContainer, b: TileContainer) => a.priority - b.priority);
|
||||
private random = new PseudoRandom(123)
|
||||
|
||||
private _owner: MutablePlayer
|
||||
@@ -50,7 +50,7 @@ export class AttackExecution implements Execution {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.toConquer.size() < 10) {
|
||||
if (this.toConquer.size() < 5) {
|
||||
this.calculateToConquer()
|
||||
}
|
||||
if (this.toConquer.size() == 0) {
|
||||
@@ -130,7 +130,7 @@ export class AttackExecution implements Execution {
|
||||
// .filter(t => t.terrain() == TerrainTypes.Land)
|
||||
// .filter(t => t.owner() == this._owner)
|
||||
// .length
|
||||
this.toConquer.add(new TileContainer(neighbor, + this.random.nextInt(0, 4)))
|
||||
this.toConquer.add(new TileContainer(neighbor, 1))
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
@@ -50,7 +50,7 @@ export class BoatAttackExecution implements Execution {
|
||||
this.path = this.computePath(this.src, this.dst)
|
||||
if (this.path != null) {
|
||||
console.log(`got path ${this.path.map(t => t.cell().toString())}`)
|
||||
this.boat = this.attacker.addBoat(1000, this.src.cell(), this.target)
|
||||
this.boat = this.attacker.addBoat(1000, this.src, this.target)
|
||||
} else {
|
||||
console.log('got null path')
|
||||
this.active = false
|
||||
@@ -80,7 +80,7 @@ export class BoatAttackExecution implements Execution {
|
||||
}
|
||||
|
||||
const nextTile = this.path[this.currTileIndex]
|
||||
this.boat.move(nextTile.cell())
|
||||
this.boat.move(nextTile)
|
||||
}
|
||||
|
||||
owner(): MutablePlayer {
|
||||
|
||||
@@ -12,7 +12,7 @@ export class BotExecution implements Execution {
|
||||
constructor(private bot: MutablePlayer) {
|
||||
|
||||
this.random = new PseudoRandom(bot.id())
|
||||
this.attackRate = this.random.nextInt(50, 200)
|
||||
this.attackRate = this.random.nextInt(10, 50)
|
||||
}
|
||||
|
||||
init(gs: MutableGame, ticks: number) {
|
||||
@@ -35,7 +35,7 @@ export class BotExecution implements Execution {
|
||||
const toAttack = ns[this.random.nextInt(0, ns.length)]
|
||||
|
||||
this.gs.addExecution(new AttackExecution(
|
||||
this.bot.troops() / 5,
|
||||
this.bot.troops() / 100,
|
||||
this.bot.id(),
|
||||
toAttack.isPlayer() ? toAttack.id() : null,
|
||||
null
|
||||
|
||||
Reference in New Issue
Block a user