mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 08:11:54 +00:00
moved attack logic to config
This commit is contained in:
@@ -11,7 +11,6 @@ To build the project, you will need to have Node.js and npm installed. You can d
|
|||||||
Before building the project, you will need to install the dependencies. You can do this by running the following command in the project directory:
|
Before building the project, you will need to install the dependencies. You can do this by running the following command in the project directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git submodule update --init --recursive
|
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ export class PlayerImpl implements MutablePlayer {
|
|||||||
}
|
}
|
||||||
removeTroops(troops: number): void {
|
removeTroops(troops: number): void {
|
||||||
this._troops -= troops
|
this._troops -= troops
|
||||||
|
this._troops = Math.max(this._troops, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlayer(): this is MutablePlayer {return true as const}
|
isPlayer(): this is MutablePlayer {return true as const}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import {Player, PlayerID, PlayerInfo, TerrainType, TerrainTypes, TerraNullius} from "../Game";
|
import {Player, PlayerID, PlayerInfo, TerrainType, TerrainTypes, TerraNullius, Tile} from "../Game";
|
||||||
import {Colord, colord} from "colord";
|
import {Colord, colord} from "colord";
|
||||||
import {pastelTheme} from "./PastelTheme";
|
import {pastelTheme} from "./PastelTheme";
|
||||||
|
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
theme(): Theme;
|
theme(): Theme;
|
||||||
player(): PlayerConfig
|
player(): PlayerConfig
|
||||||
@@ -13,7 +14,12 @@ export interface Config {
|
|||||||
export interface PlayerConfig {
|
export interface PlayerConfig {
|
||||||
startTroops(playerInfo: PlayerInfo): number
|
startTroops(playerInfo: PlayerInfo): number
|
||||||
troopAdditionRate(player: Player): number
|
troopAdditionRate(player: Player): number
|
||||||
attackLogic(attack: Player, defender: Player | TerraNullius): number
|
attackTilesPerTick(attacker: Player, defender: Player | TerraNullius, numAdjacentTilesWithEnemy: number): number
|
||||||
|
attackLogic(attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): {
|
||||||
|
attackerTroopLoss: number,
|
||||||
|
defenderTroopLoss: number,
|
||||||
|
tilesPerTickUsed: number
|
||||||
|
}
|
||||||
attackAmount(attacker: Player, defender: Player | TerraNullius): number
|
attackAmount(attacker: Player, defender: Player | TerraNullius): number
|
||||||
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number
|
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Player, PlayerInfo, TerraNullius} from "../Game";
|
import {Player, PlayerInfo, TerraNullius, Tile} from "../Game";
|
||||||
import {Config, PlayerConfig, Theme} from "./Config";
|
import {Config, PlayerConfig, Theme} from "./Config";
|
||||||
import {pastelTheme} from "./PastelTheme";
|
import {pastelTheme} from "./PastelTheme";
|
||||||
|
|
||||||
@@ -19,9 +19,28 @@ export const defaultConfig = new class implements Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const defaultPlayerConfig = new class implements PlayerConfig {
|
export const defaultPlayerConfig = new class implements PlayerConfig {
|
||||||
|
|
||||||
|
attackLogic(attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): {attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number} {
|
||||||
|
if (defender.isPlayer()) {
|
||||||
|
return {
|
||||||
|
attackerTroopLoss: Math.max(defender.troops() / attacker.troops(), 1),
|
||||||
|
defenderTroopLoss: 0,
|
||||||
|
tilesPerTickUsed: Math.max(defender.troops() / attacker.troops(), .25)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {attackerTroopLoss: 1, defenderTroopLoss: 0, tilesPerTickUsed: 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
attackTilesPerTick(attacker: Player, defender: Player | TerraNullius, numAdjacentTilesWithEnemy: number): number {
|
||||||
|
return numAdjacentTilesWithEnemy / 4
|
||||||
|
}
|
||||||
|
|
||||||
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number {
|
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number {
|
||||||
return attacker.troops() / 5
|
return attacker.troops() / 5
|
||||||
}
|
}
|
||||||
|
|
||||||
attackAmount(attacker: Player, defender: Player | TerraNullius) {
|
attackAmount(attacker: Player, defender: Player | TerraNullius) {
|
||||||
if (attacker.info().isBot) {
|
if (attacker.info().isBot) {
|
||||||
return attacker.troops() / 20
|
return attacker.troops() / 20
|
||||||
@@ -44,8 +63,4 @@ export const defaultPlayerConfig = new class implements PlayerConfig {
|
|||||||
return Math.min(player.troops() + toAdd, max)
|
return Math.min(player.troops() + toAdd, max)
|
||||||
}
|
}
|
||||||
|
|
||||||
attackLogic(attack: Player, defender: Player | TerraNullius): number {
|
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import PriorityQueue from "priority-queue-typescript";
|
|||||||
import {Cell, Execution, MutableGame, MutablePlayer, PlayerID, Player, TerrainTypes, TerraNullius, Tile} from "../Game";
|
import {Cell, Execution, MutableGame, MutablePlayer, PlayerID, Player, TerrainTypes, TerraNullius, Tile} from "../Game";
|
||||||
import {PseudoRandom} from "../PseudoRandom";
|
import {PseudoRandom} from "../PseudoRandom";
|
||||||
import {manhattanDist} from "../Util";
|
import {manhattanDist} from "../Util";
|
||||||
|
import {PlayerConfig} from "../configuration/Config";
|
||||||
|
|
||||||
export class AttackExecution implements Execution {
|
export class AttackExecution implements Execution {
|
||||||
private active: boolean = true;
|
private active: boolean = true;
|
||||||
@@ -20,7 +21,8 @@ export class AttackExecution implements Execution {
|
|||||||
private troops: number,
|
private troops: number,
|
||||||
private _ownerID: PlayerID,
|
private _ownerID: PlayerID,
|
||||||
private targetID: PlayerID | null,
|
private targetID: PlayerID | null,
|
||||||
private targetCell: Cell | null
|
private targetCell: Cell | null,
|
||||||
|
private playerConfig: PlayerConfig
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
init(mg: MutableGame, ticks: number) {
|
init(mg: MutableGame, ticks: number) {
|
||||||
@@ -61,7 +63,7 @@ export class AttackExecution implements Execution {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let numTilesPerTick = this.numTilesWithEnemy / 4
|
let numTilesPerTick = this.playerConfig.attackTilesPerTick(this._owner, this.target, this.numTilesWithEnemy)
|
||||||
if (this.targetCell != null) {
|
if (this.targetCell != null) {
|
||||||
numTilesPerTick /= 2
|
numTilesPerTick /= 2
|
||||||
}
|
}
|
||||||
@@ -88,15 +90,13 @@ export class AttackExecution implements Execution {
|
|||||||
badTiles++
|
badTiles++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO: move this to configs
|
const {attackerTroopLoss, defenderTroopLoss, tilesPerTickUsed} = this.playerConfig.attackLogic(this._owner, this.target, tileToConquer)
|
||||||
this._owner.conquer(tileToConquer)
|
numTilesPerTick -= tilesPerTickUsed
|
||||||
|
this.troops -= attackerTroopLoss
|
||||||
if (this.target.isPlayer()) {
|
if (this.target.isPlayer()) {
|
||||||
this.troops -= Math.max(this.target.troops() / this._owner.troops(), 1)
|
this.target.removeTroops(defenderTroopLoss)
|
||||||
numTilesPerTick -= Math.max(this.target.troops() / this._owner.troops(), .25)
|
|
||||||
} else {
|
|
||||||
this.troops -= 1
|
|
||||||
numTilesPerTick -= 1
|
|
||||||
}
|
}
|
||||||
|
this._owner.conquer(tileToConquer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import PriorityQueue from "priority-queue-typescript";
|
|||||||
import {Boat, Cell, Execution, MutableBoat, MutableGame, MutablePlayer, Player, PlayerID, Tile} from "../Game";
|
import {Boat, Cell, Execution, MutableBoat, MutableGame, MutablePlayer, Player, PlayerID, Tile} from "../Game";
|
||||||
import {manhattanDist} from "../Util";
|
import {manhattanDist} from "../Util";
|
||||||
import {AttackExecution} from "./AttackExecution";
|
import {AttackExecution} from "./AttackExecution";
|
||||||
|
import {PlayerConfig} from "../configuration/Config";
|
||||||
|
|
||||||
export class BoatAttackExecution implements Execution {
|
export class BoatAttackExecution implements Execution {
|
||||||
|
|
||||||
@@ -29,7 +30,8 @@ export class BoatAttackExecution implements Execution {
|
|||||||
private attackerID: PlayerID,
|
private attackerID: PlayerID,
|
||||||
private targetID: PlayerID | null,
|
private targetID: PlayerID | null,
|
||||||
private cell: Cell,
|
private cell: Cell,
|
||||||
private troops: number
|
private troops: number,
|
||||||
|
private playerConfig: PlayerConfig
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
init(mg: MutableGame, ticks: number) {
|
init(mg: MutableGame, ticks: number) {
|
||||||
@@ -48,7 +50,7 @@ export class BoatAttackExecution implements Execution {
|
|||||||
this.src = this.closestShoreTileToTarget(this.attacker, this.cell)
|
this.src = this.closestShoreTileToTarget(this.attacker, this.cell)
|
||||||
this.dst = this.closestShoreTileToTarget(this.target, this.cell)
|
this.dst = this.closestShoreTileToTarget(this.target, this.cell)
|
||||||
|
|
||||||
if(this.src == null || this.dst == null) {
|
if (this.src == null || this.dst == null) {
|
||||||
this.active = false
|
this.active = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -80,7 +82,7 @@ export class BoatAttackExecution implements Execution {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.attacker.conquer(this.dst)
|
this.attacker.conquer(this.dst)
|
||||||
this.mg.addExecution(new AttackExecution(this.troops, this.attacker.id(), this.targetID, null))
|
this.mg.addExecution(new AttackExecution(this.troops, this.attacker.id(), this.targetID, null, this.playerConfig))
|
||||||
this.active = false
|
this.active = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import {PlayerConfig} from "../configuration/Config";
|
||||||
import {Cell, Execution, MutableGame, MutablePlayer, Player, PlayerID, PlayerInfo, TerraNullius} from "../Game"
|
import {Cell, Execution, MutableGame, MutablePlayer, Player, PlayerID, PlayerInfo, TerraNullius} from "../Game"
|
||||||
import {PseudoRandom} from "../PseudoRandom"
|
import {PseudoRandom} from "../PseudoRandom"
|
||||||
import {AttackExecution} from "./AttackExecution";
|
import {AttackExecution} from "./AttackExecution";
|
||||||
@@ -10,7 +11,7 @@ export class BotExecution implements Execution {
|
|||||||
private gs: MutableGame
|
private gs: MutableGame
|
||||||
private neighborsTerra = true
|
private neighborsTerra = true
|
||||||
|
|
||||||
constructor(private bot: MutablePlayer) {
|
constructor(private bot: MutablePlayer, private playerConfig: PlayerConfig) {
|
||||||
|
|
||||||
this.random = new PseudoRandom(bot.id())
|
this.random = new PseudoRandom(bot.id())
|
||||||
this.attackRate = this.random.nextInt(10, 50)
|
this.attackRate = this.random.nextInt(10, 50)
|
||||||
@@ -57,7 +58,8 @@ export class BotExecution implements Execution {
|
|||||||
this.bot.troops() / 20,
|
this.bot.troops() / 20,
|
||||||
this.bot.id(),
|
this.bot.id(),
|
||||||
toAttack.isPlayer() ? toAttack.id() : null,
|
toAttack.isPlayer() ? toAttack.id() : null,
|
||||||
null
|
null,
|
||||||
|
this.playerConfig
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ export class Executor {
|
|||||||
intent.troops,
|
intent.troops,
|
||||||
intent.attackerID,
|
intent.attackerID,
|
||||||
intent.targetID,
|
intent.targetID,
|
||||||
new Cell(intent.targetX, intent.targetY)
|
new Cell(intent.targetX, intent.targetY),
|
||||||
|
this.playerConfig
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else if (intent.type == "spawn") {
|
} else if (intent.type == "spawn") {
|
||||||
@@ -43,6 +44,7 @@ export class Executor {
|
|||||||
intent.targetID,
|
intent.targetID,
|
||||||
new Cell(intent.x, intent.y),
|
new Cell(intent.x, intent.y),
|
||||||
intent.troops,
|
intent.troops,
|
||||||
|
this.playerConfig
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export class SpawnExecution implements Execution {
|
|||||||
})
|
})
|
||||||
this.gs.addExecution(new PlayerExecution(player.id(), this.playerConfig))
|
this.gs.addExecution(new PlayerExecution(player.id(), this.playerConfig))
|
||||||
if (player.info().isBot) {
|
if (player.info().isBot) {
|
||||||
this.gs.addExecution(new BotExecution(player))
|
this.gs.addExecution(new BotExecution(player, this.playerConfig))
|
||||||
}
|
}
|
||||||
this.active = false
|
this.active = false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user