mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-18 09:14:09 +00:00
improve remove clusters, kill player if surrounded
This commit is contained in:
@@ -67,6 +67,9 @@
|
|||||||
* Have terrain affect attack DONE 8/31/2024
|
* Have terrain affect attack DONE 8/31/2024
|
||||||
* PERF: enable CDN DONE 8/31/2024
|
* PERF: enable CDN DONE 8/31/2024
|
||||||
* enable load balancing metrics DONE 8/31/2024
|
* enable load balancing metrics DONE 8/31/2024
|
||||||
|
* BUG: island don't check if inscribed, just try to remove it DONE 8/31/2024
|
||||||
|
* if completely surrounded by same enemy, lose island DONE 8/31/2024
|
||||||
|
* fix boat leaves trail bug
|
||||||
* end game when no players left (or after 1 hour or so?)
|
* end game when no players left (or after 1 hour or so?)
|
||||||
* use better favicon
|
* use better favicon
|
||||||
* BUG: tiles get left behind during conquer
|
* BUG: tiles get left behind during conquer
|
||||||
@@ -78,3 +81,5 @@
|
|||||||
* directed expansion
|
* directed expansion
|
||||||
* REFACTOR: give terranullius an ID, game.player() returns terranullius
|
* REFACTOR: give terranullius an ID, game.player() returns terranullius
|
||||||
* REFACTOR: ocean is considered TerraNullius ?
|
* REFACTOR: ocean is considered TerraNullius ?
|
||||||
|
* BUG: sometimes islands don't get removed
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ export class AttackExecution implements Execution {
|
|||||||
// if (numOwnedByMe > 3) {
|
// if (numOwnedByMe > 3) {
|
||||||
// numOwnedByMe = 1000
|
// numOwnedByMe = 1000
|
||||||
// }
|
// }
|
||||||
this.toConquer.enqueue(new TileContainer(neighbor, this.random.nextInt(0, 2) - numOwnedByMe + tile.magnitude() / 5))
|
this.toConquer.enqueue(new TileContainer(neighbor, this.random.nextInt(0, 4) - numOwnedByMe + tile.magnitude() / 5))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.borderTiles = newBorder
|
this.borderTiles = newBorder
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import cluster from "cluster"
|
|
||||||
import {Config} from "../configuration/Config"
|
import {Config} from "../configuration/Config"
|
||||||
import {Execution, MutableGame, MutablePlayer, PlayerID, Tile} from "../Game"
|
import {Execution, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile} from "../Game"
|
||||||
import {bfs, calculateBoundingBox, getMode, inscribed, simpleHash} from "../Util"
|
import {bfs, calculateBoundingBox, getMode, inscribed, simpleHash} from "../Util"
|
||||||
import {GameImpl} from "../GameImpl"
|
import {GameImpl} from "../GameImpl"
|
||||||
|
|
||||||
export class PlayerExecution implements Execution {
|
export class PlayerExecution implements Execution {
|
||||||
|
|
||||||
private readonly ticksPerIslandCalc = 50
|
private readonly ticksPerClusterCalc = 10
|
||||||
|
|
||||||
private player: MutablePlayer
|
private player: MutablePlayer
|
||||||
private config: Config
|
private config: Config
|
||||||
@@ -24,7 +23,7 @@ export class PlayerExecution implements Execution {
|
|||||||
this.mg = mg
|
this.mg = mg
|
||||||
this.config = mg.config()
|
this.config = mg.config()
|
||||||
this.player = mg.player(this.playerID)
|
this.player = mg.player(this.playerID)
|
||||||
this.lastCalc = ticks + (simpleHash(this.player.name()) % this.ticksPerIslandCalc)
|
this.lastCalc = ticks + (simpleHash(this.player.name()) % this.ticksPerClusterCalc)
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(ticks: number) {
|
tick(ticks: number) {
|
||||||
@@ -33,10 +32,10 @@ export class PlayerExecution implements Execution {
|
|||||||
}
|
}
|
||||||
this.player.setTroops(this.config.troopAdditionRate(this.player))
|
this.player.setTroops(this.config.troopAdditionRate(this.player))
|
||||||
|
|
||||||
if (ticks - this.lastCalc > this.ticksPerIslandCalc) {
|
if (ticks - this.lastCalc > this.ticksPerClusterCalc) {
|
||||||
this.lastCalc = ticks
|
this.lastCalc = ticks
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
this.removeIslands()
|
this.removeClusters()
|
||||||
const end = performance.now()
|
const end = performance.now()
|
||||||
if (end - start > 1000) {
|
if (end - start > 1000) {
|
||||||
console.log(`player ${this.player.name()}, took ${end - start}ms`)
|
console.log(`player ${this.player.name()}, took ${end - start}ms`)
|
||||||
@@ -44,35 +43,65 @@ export class PlayerExecution implements Execution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeIslands() {
|
private removeClusters() {
|
||||||
const clusters = this.calculateClusters()
|
const clusters = this.calculateClusters()
|
||||||
if (clusters.length <= 1) {
|
// if (clusters.length <= 1) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
clusters.sort((a, b) => b.size - a.size);
|
clusters.sort((a, b) => b.size - a.size);
|
||||||
const main = clusters.shift()
|
|
||||||
const mainBox = calculateBoundingBox(main)
|
|
||||||
for (const toRemove of clusters) {
|
|
||||||
const toRemoveBox = calculateBoundingBox(toRemove)
|
|
||||||
if (inscribed(mainBox, toRemoveBox)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const tile of toRemove) {
|
const main = clusters.shift()
|
||||||
if (tile.isOceanShore()) {
|
if (this.isSurroundedBySamePlayer(main)) {
|
||||||
return
|
this.removeCluster(main)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const cluster of clusters) {
|
||||||
|
if (this.isSurrounded(cluster)) {
|
||||||
|
this.removeCluster(cluster)
|
||||||
}
|
}
|
||||||
this.removeIsland(toRemove)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeIsland(cluster: Set<Tile>) {
|
private isSurroundedBySamePlayer(cluster: Set<Tile>): boolean {
|
||||||
console.log('removing island!')
|
const enemies = new Set<Player>()
|
||||||
|
for (const tile of cluster) {
|
||||||
|
if (tile.isOceanShore() || tile.neighbors().find(n => !n.hasOwner())) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tile.neighbors()
|
||||||
|
.filter(n => n.hasOwner() && n.owner() != this.player)
|
||||||
|
.forEach(p => enemies.add(p.owner() as Player))
|
||||||
|
if (enemies.size != 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private isSurrounded(cluster: Set<Tile>): boolean {
|
||||||
|
let enemyTiles = new Set<Tile>()
|
||||||
|
for (const tile of cluster) {
|
||||||
|
if (tile.isOceanShore()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tile.neighbors()
|
||||||
|
.filter(n => n.hasOwner() && n.owner() != this.player)
|
||||||
|
.forEach(n => enemyTiles.add(n))
|
||||||
|
}
|
||||||
|
if (enemyTiles.size == 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const enemyBox = calculateBoundingBox(enemyTiles)
|
||||||
|
const clusterBox = calculateBoundingBox(cluster)
|
||||||
|
return inscribed(enemyBox, clusterBox)
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeCluster(cluster: Set<Tile>) {
|
||||||
|
console.log('removing cluster!')
|
||||||
const arr = Array.from(cluster)
|
const arr = Array.from(cluster)
|
||||||
const mode = getMode(arr.flatMap(t => t.neighbors()).filter(t => t.hasOwner() && t.owner() != this.player).map(t => t.owner().id()))
|
const mode = getMode(arr.flatMap(t => t.neighbors()).filter(t => t.hasOwner() && t.owner() != this.player).map(t => t.owner().id()))
|
||||||
if (mode == null) {
|
if (!this.mg.hasPlayer(mode)) {
|
||||||
console.warn('mode is null')
|
console.warn('mode is not found')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const firstTile = arr[0]
|
const firstTile = arr[0]
|
||||||
@@ -108,10 +137,6 @@ export class PlayerExecution implements Execution {
|
|||||||
|
|
||||||
const neighbors = (this.mg as GameImpl).neighborsWithDiag(curr)
|
const neighbors = (this.mg as GameImpl).neighborsWithDiag(curr)
|
||||||
for (const neighbor of neighbors) {
|
for (const neighbor of neighbors) {
|
||||||
// if (this.mg.ticks() == 736 && loops > 580000) {
|
|
||||||
// // console.log(`got neighbor ${neighbor.cell().toString()}`)
|
|
||||||
// gr.paintBlack(neighbor)
|
|
||||||
// }
|
|
||||||
if (neighbor.isBorder() && border.has(neighbor)) {
|
if (neighbor.isBorder() && border.has(neighbor)) {
|
||||||
if (!seen.has(neighbor)) {
|
if (!seen.has(neighbor)) {
|
||||||
queue.push(neighbor)
|
queue.push(neighbor)
|
||||||
@@ -129,9 +154,7 @@ export class PlayerExecution implements Execution {
|
|||||||
return this.player
|
return this.player
|
||||||
}
|
}
|
||||||
|
|
||||||
private active = true
|
|
||||||
isActive(): boolean {
|
isActive(): boolean {
|
||||||
// return this.player.isAlive()
|
return this.player.isAlive()
|
||||||
return this.active
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user