make radial menu boat button

This commit is contained in:
evanpelle
2024-09-28 12:58:49 -07:00
parent c06009f64e
commit c4c23de1ec
7 changed files with 137 additions and 123 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ export const BoatAttackIntentSchema = BaseIntentSchema.extend({
type: z.literal('boat'),
attackerID: z.string(),
targetID: z.string().nullable(),
troops: z.number(),
troops: z.number().nullable(),
x: z.number(),
y: z.number(),
})
+36 -1
View File
@@ -1,7 +1,7 @@
import {v4 as uuidv4} from 'uuid';
import {Cell, Player, Tile} from "./game/Game";
import {Cell, Game, Player, TerraNullius, Tile} from "./game/Game";
export function manhattanDist(c1: Cell, c2: Cell): number {
return Math.abs(c1.x - c2.x) + Math.abs(c1.y - c2.y);
@@ -32,6 +32,41 @@ export function and(x: (tile: Tile) => boolean, y: (tile: Tile) => boolean): (ti
return (tile: Tile) => x(tile) && y(tile)
}
// TODO: refactor to new file
export function sourceDstOceanShore(game: Game, src: Player, dst: Player | TerraNullius, cell: Cell): [Tile | null, Tile | null] {
let srcTile = closestOceanShoreFromPlayer(src, cell, game.width())
let dstTile: Tile | null = null
if (dst.isPlayer()) {
dstTile = closestOceanShoreFromPlayer(dst as Player, cell, game.width())
} else {
dstTile = closestOceanShoreTN(game.tile(cell), 300)
}
return [srcTile, dstTile]
}
function closestOceanShoreFromPlayer(player: Player, target: Cell, width: number): Tile | null {
const shoreTiles = Array.from(player.borderTiles()).filter(t => t.isOceanShore())
if (shoreTiles.length == 0) {
return null
}
return shoreTiles.reduce((closest, current) => {
const closestDistance = manhattanDistWrapped(target, closest.cell(), width);
const currentDistance = manhattanDistWrapped(target, current.cell(), width);
return currentDistance < closestDistance ? current : closest;
});
}
function closestOceanShoreTN(tile: Tile, searchDist: number): Tile {
const tn = Array.from(bfs(tile, and(t => !t.hasOwner(), dist(tile, searchDist))))
.filter(t => t.isOceanShore())
.sort((a, b) => manhattanDist(tile.cell(), a.cell()) - manhattanDist(tile.cell(), b.cell()))
if (tn.length == 0) {
return null
}
return tn[0]
}
export function bfs(tile: Tile, filter: (tile: Tile) => boolean): Set<Tile> {
const seen = new Set<Tile>
const q: Tile[] = []
+4 -4
View File
@@ -7,7 +7,7 @@ export const devConfig = new class extends DefaultConfig {
return 95
}
numSpawnPhaseTurns(): number {
return 80
return 40
}
gameCreationRate(): number {
return 2 * 1000
@@ -27,9 +27,9 @@ export const devConfig = new class extends DefaultConfig {
// return 10 * 10
// }
// numFakeHumans(gameID: GameID): number {
// return 0
// }
numFakeHumans(gameID: GameID): number {
return 0
}
// startTroops(playerInfo: PlayerInfo): number {
// if (playerInfo.isBot) {
+11 -20
View File
@@ -1,9 +1,7 @@
import {PriorityQueue} from "@datastructures-js/priority-queue";
import {Boat, Cell, Execution, MutableBoat, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile, TileEvent} from "../game/Game";
import {manhattanDist, manhattanDistWrapped} from "../Util";
import {and, bfs, manhattanDistWrapped, sourceDstOceanShore} from "../Util";
import {AttackExecution} from "./AttackExecution";
import {Config} from "../configuration/Config";
import {EventBus} from "../EventBus";
import {DisplayMessageEvent, MessageType} from "../../client/graphics/layers/EventsDisplay";
export class BoatAttackExecution implements Execution {
@@ -21,8 +19,8 @@ export class BoatAttackExecution implements Execution {
// TODO make private
public path: Tile[]
private src: Tile
private dst: Tile
private src: Tile | null
private dst: Tile | null
private currTileIndex: number = 0
@@ -37,7 +35,7 @@ export class BoatAttackExecution implements Execution {
private attackerID: PlayerID,
private targetID: PlayerID | null,
private cell: Cell,
private troops: number,
private troops: number | null,
) { }
activeDuringSpawnPhase(): boolean {
@@ -63,11 +61,16 @@ export class BoatAttackExecution implements Execution {
this.target = mg.player(this.targetID)
}
if (this.troops == null) {
this.troops = this.mg.config().boatAttackAmount(this.attacker, this.target)
}
this.troops = Math.min(this.troops, this.attacker.troops())
this.attacker.removeTroops(this.troops)
this.src = this.closestShoreTile(this.attacker, this.cell)
this.dst = this.mg.tile(this.cell)
const [srcTile, dstTile]: [Tile | null, Tile | null] = sourceDstOceanShore(this.mg, this.attacker, this.target, this.cell);
this.src = srcTile
this.dst = dstTile
if (this.src == null || this.dst == null) {
this.active = false
@@ -135,18 +138,6 @@ export class BoatAttackExecution implements Execution {
return this.active
}
private closestShoreTile(player: Player, target: Cell): Tile | null {
const shoreTiles = Array.from(player.borderTiles()).filter(t => t.isOceanShore())
if (shoreTiles.length == 0) {
return null
}
return shoreTiles.reduce((closest, current) => {
const closestDistance = manhattanDistWrapped(target, closest.cell(), this.mg.width());
const currentDistance = manhattanDistWrapped(target, current.cell(), this.mg.width());
return currentDistance < closestDistance ? current : closest;
});
}
}
export class AStar {