mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-04 22:06:05 +00:00
fix bot attacks each other same time bug, improve spawns
This commit is contained in:
@@ -50,16 +50,20 @@
|
||||
* store & delay tile updates for lag compensation DONE 8/26/2024
|
||||
* BUG: error if don't spawn and then click after spawn mode DONE 8/26/2024
|
||||
* BUG: change player name after join lobby DONE 8/26/2024
|
||||
* REFACTOR: use new priority queue
|
||||
* BUG: players attack each other same time creates islands
|
||||
* add shader to dim border
|
||||
* REFACTOR: remove player.info()
|
||||
* REFACTOR: use new priority queue DONE 8/27/2024
|
||||
* BUG: players attack each other same time creates islands DONE 8/28/2024
|
||||
* make bot spawn better DONE 8/28/2024
|
||||
* make UX for attacking TerraNullius by boat better
|
||||
* make bots more likely to attack weaker players
|
||||
* make bot territory less funky (more likely attack neighbors with larger border)
|
||||
- maybe use bounding box, bots want to be circular?
|
||||
* PERF: use hierarchical a* search for boats
|
||||
* precompute spawns
|
||||
* end game when no players left (or after 1 hour or so?)
|
||||
* boats can go around the world
|
||||
* Add terrain elevation to map
|
||||
* use better favicon
|
||||
* REFACTOR: give terranullius an ID, game.player() returns terranullius
|
||||
* REFACTOR: ocean is considered TerraNullius ?
|
||||
* REFACTOR: remove player config?
|
||||
* PERF: use hierarchical a* search for boats
|
||||
* PERF: render tiles more efficiently
|
||||
* Add terrain elevation to map
|
||||
* boats can go around the world
|
||||
* make bots more likely to attack weaker players
|
||||
* use better favicon
|
||||
@@ -287,8 +287,8 @@ export class GameImpl implements MutableGame {
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.executions().forEach(e => {
|
||||
if (!this.inSpawnPhase() || e.activeDuringSpawnPhase()) {
|
||||
this.execs.forEach(e => {
|
||||
if (e.isActive() && (!this.inSpawnPhase() || e.activeDuringSpawnPhase())) {
|
||||
e.tick(this._ticks)
|
||||
}
|
||||
})
|
||||
@@ -349,7 +349,7 @@ export class GameImpl implements MutableGame {
|
||||
}
|
||||
|
||||
executions(): Execution[] {
|
||||
return this.execs
|
||||
return [...this.execs, ...this.unInitExecs]
|
||||
}
|
||||
|
||||
addExecution(...exec: Execution[]) {
|
||||
@@ -357,7 +357,8 @@ export class GameImpl implements MutableGame {
|
||||
}
|
||||
|
||||
removeExecution(exec: Execution) {
|
||||
this.execs.filter(execution => execution !== exec)
|
||||
this.execs = this.execs.filter(execution => execution !== exec)
|
||||
this.unInitExecs = this.unInitExecs.filter(execution => execution !== exec)
|
||||
}
|
||||
|
||||
width(): number {
|
||||
|
||||
@@ -3,24 +3,24 @@ import {PlayerConfig} from "./Config";
|
||||
import {DefaultConfig, DefaultPlayerConfig, defaultPlayerConfig} from "./DefaultConfig";
|
||||
|
||||
export const devConfig = new class extends DefaultConfig {
|
||||
// numSpawnPhaseTurns(): number {
|
||||
// return 40
|
||||
// }
|
||||
// gameCreationRate(): number {
|
||||
// return 3 * 1000
|
||||
// }
|
||||
// lobbyLifetime(): number {
|
||||
// return 3 * 1000
|
||||
// }
|
||||
// turnIntervalMs(): number {
|
||||
// return 100
|
||||
// }
|
||||
// player(): PlayerConfig {
|
||||
// return devPlayerConfig
|
||||
// }
|
||||
// numBots(): number {
|
||||
// return 250
|
||||
// }
|
||||
numSpawnPhaseTurns(): number {
|
||||
return 40
|
||||
}
|
||||
gameCreationRate(): number {
|
||||
return 3 * 1000
|
||||
}
|
||||
lobbyLifetime(): number {
|
||||
return 3 * 1000
|
||||
}
|
||||
turnIntervalMs(): number {
|
||||
return 100
|
||||
}
|
||||
player(): PlayerConfig {
|
||||
return devPlayerConfig
|
||||
}
|
||||
numBots(): number {
|
||||
return 250
|
||||
}
|
||||
}
|
||||
|
||||
export const devPlayerConfig = new class extends DefaultPlayerConfig {
|
||||
|
||||
@@ -29,6 +29,10 @@ export class AttackExecution implements Execution {
|
||||
}
|
||||
|
||||
init(mg: MutableGame, ticks: number) {
|
||||
if (!this.active) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// TODO: remove this and fix directed expansion.
|
||||
this.targetCell = null
|
||||
@@ -40,13 +44,13 @@ export class AttackExecution implements Execution {
|
||||
this.mg = mg
|
||||
|
||||
for (const exec of mg.executions()) {
|
||||
if (exec.isActive() && exec instanceof AttackExecution) {
|
||||
if (exec.isActive() && exec instanceof AttackExecution && exec != this) {
|
||||
const otherAttack = exec as AttackExecution
|
||||
// Target has opposing attack, cancel them out
|
||||
if (this.target.isPlayer() && otherAttack.target == this._owner && this.target == otherAttack._owner) {
|
||||
if (this.target.isPlayer() && otherAttack.targetID == this._ownerID && this.targetID == otherAttack._ownerID) {
|
||||
if (otherAttack.troops > this.troops) {
|
||||
otherAttack.troops -= this.troops
|
||||
otherAttack.calculateToConquer()
|
||||
// otherAttack.calculateToConquer()
|
||||
this.active = false
|
||||
return
|
||||
} else {
|
||||
@@ -55,7 +59,7 @@ export class AttackExecution implements Execution {
|
||||
}
|
||||
}
|
||||
// Existing attack on same target, add troops
|
||||
if (otherAttack._owner == this._owner && otherAttack.target == this.target) {
|
||||
if (otherAttack._owner == this._owner && otherAttack.targetID == this.targetID) {
|
||||
otherAttack.troops += this.troops
|
||||
otherAttack.calculateToConquer()
|
||||
this.active = false
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {Cell, Game} from "../Game";
|
||||
import {PseudoRandom} from "../PseudoRandom";
|
||||
import {SpawnIntent} from "../Schemas";
|
||||
import {bfs} from "../Util";
|
||||
import {getSpawnCells} from "./Util";
|
||||
|
||||
|
||||
export class BotSpawner {
|
||||
private cellToIndex;
|
||||
private cellToIndex: Map<string, number>;
|
||||
private freeTiles: Cell[];
|
||||
private numFreeTiles;
|
||||
private random = new PseudoRandom(123);
|
||||
@@ -39,8 +40,7 @@ export class BotSpawner {
|
||||
spawnBot(botName: string): SpawnIntent {
|
||||
const rand = this.random.nextInt(0, this.numFreeTiles);
|
||||
const spawn = this.freeTiles[rand];
|
||||
const spawnCells = getSpawnCells(this.gs, spawn);
|
||||
spawnCells.forEach(c => this.removeCell(c));
|
||||
bfs(this.gs.tile(spawn), 50).forEach(t => this.removeCell(t.cell()))
|
||||
const spawnIntent: SpawnIntent = {
|
||||
type: 'spawn',
|
||||
name: botName,
|
||||
@@ -52,9 +52,14 @@ export class BotSpawner {
|
||||
}
|
||||
|
||||
private removeCell(cell: Cell) {
|
||||
const index = this.cellToIndex[cell.toString()];
|
||||
if (!this.cellToIndex.has(cell.toString())) {
|
||||
return
|
||||
}
|
||||
const index = this.cellToIndex.get(cell.toString());
|
||||
this.cellToIndex.delete(cell.toString())
|
||||
|
||||
this.freeTiles[index] = this.freeTiles[this.numFreeTiles - 1];
|
||||
this.cellToIndex[this.freeTiles[index].toString()] = index;
|
||||
this.cellToIndex.set(this.freeTiles[index].toString(), index);
|
||||
this.numFreeTiles--;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user