mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-14 18:06:37 +00:00
Merge branch 'main' into 2393-show-boat-troops-as-attacking-troops
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
Cell,
|
||||
Difficulty,
|
||||
Execution,
|
||||
Game,
|
||||
Gold,
|
||||
@@ -46,6 +47,11 @@ export class FakeHumanExecution implements Execution {
|
||||
private readonly lastMIRVSent: [Tick, TileRef][] = [];
|
||||
private readonly embargoMalusApplied = new Set<PlayerID>();
|
||||
|
||||
// Track our transport ships we currently own
|
||||
private trackedTransportShips: Set<Unit> = new Set();
|
||||
// Track our trade ships we currently own
|
||||
private trackedTradeShips: Set<Unit> = new Set();
|
||||
|
||||
/** MIRV Strategy Constants */
|
||||
|
||||
/** Ticks until MIRV can be attempted again */
|
||||
@@ -133,6 +139,16 @@ export class FakeHumanExecution implements Execution {
|
||||
}
|
||||
|
||||
tick(ticks: number) {
|
||||
// Ship tracking
|
||||
if (
|
||||
this.player !== null &&
|
||||
this.player.isAlive() &&
|
||||
this.mg.config().gameConfig().difficulty !== Difficulty.Easy
|
||||
) {
|
||||
this.trackTransportShipsAndRetaliate();
|
||||
this.trackTradeShipsAndRetaliate();
|
||||
}
|
||||
|
||||
if (ticks % this.attackRate !== this.attackTick) {
|
||||
return;
|
||||
}
|
||||
@@ -901,6 +917,70 @@ export class FakeHumanExecution implements Execution {
|
||||
}
|
||||
}
|
||||
|
||||
// Send out a warship if our transport ship got captured
|
||||
private trackTransportShipsAndRetaliate(): void {
|
||||
if (this.player === null) return;
|
||||
|
||||
// Add any currently owned transport ships to our tracking set
|
||||
this.player
|
||||
.units(UnitType.TransportShip)
|
||||
.forEach((u) => this.trackedTransportShips.add(u));
|
||||
|
||||
// Iterate tracked transport ships; if it got destroyed by an enemy: retaliate
|
||||
for (const ship of Array.from(this.trackedTransportShips)) {
|
||||
if (!ship.isActive()) {
|
||||
// Distinguish between arrival/retreat and enemy destruction
|
||||
if (ship.wasDestroyedByEnemy()) {
|
||||
this.maybeRetaliateWithWarship(ship.tile());
|
||||
}
|
||||
this.trackedTransportShips.delete(ship);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send out a warship if our trade ship got captured
|
||||
private trackTradeShipsAndRetaliate(): void {
|
||||
if (this.player === null) return;
|
||||
|
||||
// Add any currently owned trade ships to our tracking map
|
||||
this.player
|
||||
.units(UnitType.TradeShip)
|
||||
.forEach((u) => this.trackedTradeShips.add(u));
|
||||
|
||||
// Iterate tracked trade ships; if we no longer own it, it was captured: retaliate
|
||||
for (const ship of Array.from(this.trackedTradeShips)) {
|
||||
if (!ship.isActive()) {
|
||||
this.trackedTradeShips.delete(ship);
|
||||
continue;
|
||||
}
|
||||
if (ship.owner().id() !== this.player.id()) {
|
||||
// Ship was ours and is now owned by someone else -> captured
|
||||
this.maybeRetaliateWithWarship(ship.tile());
|
||||
this.trackedTradeShips.delete(ship);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private maybeRetaliateWithWarship(tile: TileRef): void {
|
||||
if (this.player === null) return;
|
||||
|
||||
const { difficulty } = this.mg.config().gameConfig();
|
||||
// In Easy never retaliate. In Medium retaliate with 15% chance. Hard with 50%, Impossible with 80%.
|
||||
if (
|
||||
(difficulty === Difficulty.Medium && this.random.nextInt(0, 100) < 15) ||
|
||||
(difficulty === Difficulty.Hard && this.random.nextInt(0, 100) < 50) ||
|
||||
(difficulty === Difficulty.Impossible && this.random.nextInt(0, 100) < 80)
|
||||
) {
|
||||
const canBuild = this.player.canBuild(UnitType.Warship, tile);
|
||||
if (canBuild === false) {
|
||||
return;
|
||||
}
|
||||
this.mg.addExecution(
|
||||
new ConstructionExecution(this.player, UnitType.Warship, tile),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
@@ -451,6 +451,7 @@ export interface Unit {
|
||||
toUpdate(): UnitUpdate;
|
||||
hasTrainStation(): boolean;
|
||||
setTrainStation(trainStation: boolean): void;
|
||||
wasDestroyedByEnemy(): boolean;
|
||||
|
||||
// Train
|
||||
trainType(): TrainType | undefined;
|
||||
|
||||
@@ -24,6 +24,7 @@ export class UnitImpl implements Unit {
|
||||
private _retreating: boolean = false;
|
||||
private _targetedBySAM = false;
|
||||
private _reachedTarget = false;
|
||||
private _wasDestroyedByEnemy: boolean = false;
|
||||
private _lastSetSafeFromPirates: number; // Only for trade ships
|
||||
private _constructionType: UnitType | undefined;
|
||||
private _lastOwner: PlayerImpl | null = null;
|
||||
@@ -254,6 +255,10 @@ export class UnitImpl implements Unit {
|
||||
if (!this.isActive()) {
|
||||
throw new Error(`cannot delete ${this} not active`);
|
||||
}
|
||||
|
||||
// Record whether this unit was destroyed by an enemy (vs. arrived / retreated)
|
||||
this._wasDestroyedByEnemy = destroyer !== undefined;
|
||||
|
||||
this._owner._units = this._owner._units.filter((b) => b !== this);
|
||||
this._active = false;
|
||||
this.mg.addUpdate(this.toUpdate());
|
||||
@@ -307,6 +312,10 @@ export class UnitImpl implements Unit {
|
||||
return this._active;
|
||||
}
|
||||
|
||||
wasDestroyedByEnemy(): boolean {
|
||||
return this._wasDestroyedByEnemy;
|
||||
}
|
||||
|
||||
retreating(): boolean {
|
||||
return this._retreating;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user