mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-24 13:52:45 +00:00
Merge branch 'main' of https://github.com/openfrontio/OpenFrontIO into meta3
This commit is contained in:
@@ -10,8 +10,7 @@ import {
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { AirPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
import { NukeExecution } from "./NukeExecution";
|
||||
@@ -30,7 +29,7 @@ export class MirvExecution implements Execution {
|
||||
|
||||
private random: PseudoRandom;
|
||||
|
||||
private pathFinder: PathFinder;
|
||||
private pathFinder: AirPathFinder;
|
||||
|
||||
private targetPlayer: Player | TerraNullius;
|
||||
|
||||
@@ -50,7 +49,7 @@ export class MirvExecution implements Execution {
|
||||
|
||||
this.random = new PseudoRandom(mg.ticks() + simpleHash(this.senderID));
|
||||
this.mg = mg;
|
||||
this.pathFinder = PathFinder.Mini(mg, 10_000);
|
||||
this.pathFinder = new AirPathFinder(mg, this.random);
|
||||
this.player = mg.player(this.senderID);
|
||||
this.targetPlayer = this.mg.owner(this.dst);
|
||||
|
||||
@@ -90,23 +89,12 @@ export class MirvExecution implements Execution {
|
||||
this.nuke.tile(),
|
||||
this.separateDst,
|
||||
);
|
||||
switch (result.type) {
|
||||
case PathFindResultType.Completed:
|
||||
this.nuke.move(result.tile);
|
||||
this.separate();
|
||||
this.active = false;
|
||||
return;
|
||||
case PathFindResultType.NextTile:
|
||||
this.nuke.move(result.tile);
|
||||
break;
|
||||
case PathFindResultType.Pending:
|
||||
break;
|
||||
case PathFindResultType.PathNotFound:
|
||||
consolex.warn(
|
||||
`nuke cannot find path from ${this.nuke.tile()} to ${this.dst}`,
|
||||
);
|
||||
this.active = false;
|
||||
return;
|
||||
if (result === true) {
|
||||
this.separate();
|
||||
this.active = false;
|
||||
return;
|
||||
} else {
|
||||
this.nuke.move(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { AirPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
|
||||
export class NukeExecution implements Execution {
|
||||
@@ -20,6 +21,7 @@ export class NukeExecution implements Execution {
|
||||
private nuke: Unit;
|
||||
|
||||
private random: PseudoRandom;
|
||||
private pathFinder: AirPathFinder;
|
||||
|
||||
constructor(
|
||||
private type: NukeType,
|
||||
@@ -43,6 +45,7 @@ export class NukeExecution implements Execution {
|
||||
if (this.speed == -1) {
|
||||
this.speed = this.mg.config().defaultNukeSpeed();
|
||||
}
|
||||
this.pathFinder = new AirPathFinder(mg, this.random);
|
||||
}
|
||||
|
||||
public target(): Player | TerraNullius {
|
||||
@@ -143,45 +146,14 @@ export class NukeExecution implements Execution {
|
||||
return;
|
||||
}
|
||||
|
||||
const r = (this.mg.y(this.dst) * this.mg.x(this.dst)) % 10;
|
||||
const s = this.speed + (this.mg.ticks() % r);
|
||||
|
||||
for (let i = 0; i < this.speed; i++) {
|
||||
const x = this.mg.x(this.nuke.tile());
|
||||
const y = this.mg.y(this.nuke.tile());
|
||||
const dstX = this.mg.x(this.dst);
|
||||
const dstY = this.mg.y(this.dst);
|
||||
|
||||
// If we've reached the destination, detonate
|
||||
if (x === dstX && y === dstY) {
|
||||
// Move to next tile
|
||||
const nextTile = this.pathFinder.nextTile(this.nuke.tile(), this.dst);
|
||||
if (nextTile === true) {
|
||||
this.detonate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate next position
|
||||
let nextX = x;
|
||||
let nextY = y;
|
||||
|
||||
const ratio = Math.floor(
|
||||
1 + Math.abs(dstY - y) / (Math.abs(dstX - x) + 1),
|
||||
);
|
||||
|
||||
if (this.random.chance(ratio) && x != dstX) {
|
||||
if (x < dstX) nextX++;
|
||||
else if (x > dstX) nextX--;
|
||||
} else {
|
||||
if (y < dstY) nextY++;
|
||||
else if (y > dstY) nextY--;
|
||||
}
|
||||
|
||||
// Move to next tile
|
||||
const nextTile = this.mg.ref(nextX, nextY);
|
||||
if (nextTile !== undefined) {
|
||||
this.nuke.move(nextTile);
|
||||
} else {
|
||||
consolex.warn(`invalid tile position ${nextX},${nextY}`);
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { consolex } from "../Consolex";
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
@@ -8,12 +7,12 @@ import {
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { AirPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
|
||||
export class SAMMissileExecution implements Execution {
|
||||
private active = true;
|
||||
private pathFinder: PathFinder;
|
||||
private pathFinder: AirPathFinder;
|
||||
private SAMMissile: Unit;
|
||||
private mg: Game;
|
||||
|
||||
@@ -26,7 +25,7 @@ export class SAMMissileExecution implements Execution {
|
||||
) {}
|
||||
|
||||
init(mg: Game, ticks: number): void {
|
||||
this.pathFinder = PathFinder.Mini(mg, 2000, 10);
|
||||
this.pathFinder = new AirPathFinder(mg, new PseudoRandom(mg.ticks()));
|
||||
this.mg = mg;
|
||||
}
|
||||
|
||||
@@ -58,29 +57,19 @@ export class SAMMissileExecution implements Execution {
|
||||
const result = this.pathFinder.nextTile(
|
||||
this.SAMMissile.tile(),
|
||||
this.target.tile(),
|
||||
3,
|
||||
);
|
||||
switch (result.type) {
|
||||
case PathFindResultType.Completed:
|
||||
this.mg.displayMessage(
|
||||
`Missile intercepted ${this.target.type()}`,
|
||||
MessageType.SUCCESS,
|
||||
this._owner.id(),
|
||||
);
|
||||
this.active = false;
|
||||
this.target.delete();
|
||||
this.SAMMissile.delete(false);
|
||||
return;
|
||||
case PathFindResultType.NextTile:
|
||||
this.SAMMissile.move(result.tile);
|
||||
break;
|
||||
case PathFindResultType.Pending:
|
||||
return;
|
||||
case PathFindResultType.PathNotFound:
|
||||
consolex.log(`Missile ${this.SAMMissile} could not find target`);
|
||||
this.active = false;
|
||||
this.SAMMissile.delete(false);
|
||||
return;
|
||||
if (result === true) {
|
||||
this.mg.displayMessage(
|
||||
`Missile intercepted ${this.target.type()}`,
|
||||
MessageType.SUCCESS,
|
||||
this._owner.id(),
|
||||
);
|
||||
this.active = false;
|
||||
this.target.delete();
|
||||
this.SAMMissile.delete(false);
|
||||
return;
|
||||
} else {
|
||||
this.SAMMissile.move(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,46 @@
|
||||
import { consolex } from "../Consolex";
|
||||
import { Game } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { GameMap, TileRef } from "../game/GameMap";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { AStar, PathFindResultType, TileResult } from "./AStar";
|
||||
import { MiniAStar } from "./MiniAStar";
|
||||
|
||||
export class AirPathFinder {
|
||||
constructor(
|
||||
private mg: GameMap,
|
||||
private random: PseudoRandom,
|
||||
) {}
|
||||
|
||||
nextTile(tile: TileRef, dst: TileRef): TileRef | true {
|
||||
const x = this.mg.x(tile);
|
||||
const y = this.mg.y(tile);
|
||||
const dstX = this.mg.x(dst);
|
||||
const dstY = this.mg.y(dst);
|
||||
|
||||
if (x === dstX && y === dstY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate next position
|
||||
let nextX = x;
|
||||
let nextY = y;
|
||||
|
||||
const ratio = Math.floor(1 + Math.abs(dstY - y) / (Math.abs(dstX - x) + 1));
|
||||
|
||||
if (this.random.chance(ratio) && x != dstX) {
|
||||
if (x < dstX) nextX++;
|
||||
else if (x > dstX) nextX--;
|
||||
} else {
|
||||
if (y < dstY) nextY++;
|
||||
else if (y > dstY) nextY--;
|
||||
}
|
||||
if (nextX == x && nextY == y) {
|
||||
return true;
|
||||
}
|
||||
return this.mg.ref(nextX, nextY);
|
||||
}
|
||||
}
|
||||
|
||||
export class PathFinder {
|
||||
private curr: TileRef = null;
|
||||
private dst: TileRef = null;
|
||||
|
||||
@@ -356,7 +356,7 @@ export class GameServer {
|
||||
client.ws.close(1000, "game has ended");
|
||||
}
|
||||
});
|
||||
if (!this._hasPrestarted || !this._hasStarted) {
|
||||
if (!this._hasPrestarted && !this._hasStarted) {
|
||||
this.log.info(`game not started, not archiving game`);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user