Skip to content

Commit ef8079d

Browse files
committed
First draft of using terrain depth for boat path calculations
1 parent d3bef74 commit ef8079d

3 files changed

Lines changed: 27 additions & 14 deletions

File tree

src/game/bot/BotPlayer.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import {BotConstraints, selectBotConstraints} from "./modifier/BotConstraints";
66
import {BotStrategy, selectBotStrategy} from "./BotStrategy";
77
import {territoryManager} from "../TerritoryManager";
88
import {random} from "../Random";
9-
import {onNeighbors} from "../../util/MathUtil";
10-
import {rayTraceWater} from "../../util/VoxelRayTrace";
119
import {gameMap, gameMode} from "../GameData";
1210
import {boatManager} from "../boat/BoatManager";
1311
import {borderManager} from "../BorderManager";
@@ -32,20 +30,15 @@ export class BotPlayer extends Player {
3230
if (target !== null) {
3331
//TODO: Attack percentage should be configurable
3432
actuallyHandleAttack(this, target, 100);
35-
} else if (this.waterTiles > 0) {
33+
} else if (this.waterTiles > 0 && this.strategy.canSpawnBoat()) {
3634
const borderTiles = Array.from(borderManager.getBorderTiles(this.id)); //TODO: Check the performance hit this causes
3735
const startTile = borderTiles[random.nextInt(borderTiles.length)];
38-
const possibleStarts: number[] = [];
39-
onNeighbors(startTile, tile => {
40-
if (territoryManager.isWater(tile)) {
41-
possibleStarts.push(tile);
42-
}
43-
});
44-
if (possibleStarts.length < 1) return;
45-
const start = possibleStarts[random.nextInt(possibleStarts.length)];
46-
const end = rayTraceWater(start % gameMap.width, Math.floor(start / gameMap.width), random.next() - 0.5, random.next() - 0.5);
47-
if (end !== null && gameMode.canAttack(this.id, territoryManager.getOwner(end))) {
48-
boatManager.addBoatInternal(this, [start, end], 100);
36+
const targets = gameMap.boatTargets[startTile];
37+
if (targets === undefined) return;
38+
const target = targets[random.nextInt(targets.length)];
39+
if (gameMode.canAttack(this.id, territoryManager.getOwner(target.tile))) {
40+
//TODO: boat starts and ends on territory; Actually use proper path
41+
boatManager.addBoatInternal(this, [startTile, target.tile], 100);
4942
}
5043
}
5144
}

src/game/bot/BotStrategy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ export class BotStrategy {
7575

7676
return targets[random.nextInt(targets.length)];
7777
}
78+
79+
canSpawnBoat() {
80+
return random.nextInt(100) < 30; //TODO: This needs to be integrated better
81+
}
7882
}
7983

8084
/**

src/map/GameMap.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class GameMap {
1313
readonly areaSizes: number[];
1414
readonly tileInfluence: Uint32Array;
1515
readonly distanceMap: Int16Array;
16+
readonly boatTargets: { tile: number, distance: number, midPoint: number }[][] = [];
1617

1718
constructor(name: string, width: number, height: number, tileTypes: TileTypeBase[]) {
1819
this.name = name;
@@ -112,6 +113,7 @@ export class GameMap {
112113
const queue = new PriorityQueue<[number, number, number[]]>((a, b) => Math.abs(a[0]) < Math.abs(b[0]));
113114
const waterCache = new Map<number, number[]>();
114115
const landCache = new Map<number, number[]>();
116+
const markerCache = new Map<number, boolean[]>();
115117

116118
for (let i = 0; i < this.areaMap.length; i++) {
117119
if (this.getTile(i).navigable) {
@@ -156,13 +158,27 @@ export class GameMap {
156158
while (!queue.isEmpty()) {
157159
const [distance, bias, array] = queue.pop();
158160
const newArray: number[] = [];
161+
const markerAlias = new Map<number, Map<number, [number, number]>>();
159162
for (let i = 0; i < array.length; i += 2) {
160163
this.onNeighbors(array[i], neighbor => {
161164
if (this.distanceMap[neighbor] === -(2 ** 15)) {
162165
this.distanceMap[neighbor] = distance;
163166
this.tileInfluence[neighbor] = array[i + 1];
164167
newArray.push(neighbor);
165168
newArray.push(array[i + 1]);
169+
} else if (distance < 0 && array[i + 1] < this.tileInfluence[neighbor] && !markerCache.get(array[i + 1])?.[this.tileInfluence[neighbor]]) {
170+
const a1 = neighbor % this.width - array[i + 1] % this.width;
171+
const a2 = Math.floor(neighbor / this.width) - Math.floor(array[i + 1] / this.width);
172+
const b1 = neighbor % this.width - this.tileInfluence[neighbor] % this.width;
173+
const b2 = Math.floor(neighbor / this.width) - Math.floor(this.tileInfluence[neighbor] / this.width);
174+
const angle = Math.acos((a1 * b1 + a2 * b2) / Math.sqrt((a1 ** 2 + a2 ** 2) * (b1 ** 2 + b2 ** 2)));
175+
//TODO: clean up; remove senseless markers on borders
176+
// @ts-expect-error - TS doesn't know that the key exists
177+
if (angle >= Math.PI / 2 && (!markerAlias.get(array[i + 1])?.has(this.tileInfluence[neighbor]) || angle > markerAlias.get(array[i + 1])?.get(this.tileInfluence[neighbor])?.[0])) {
178+
if (!markerAlias.has(array[i + 1])) markerAlias.set(array[i + 1], new Map());
179+
// @ts-expect-error - TS doesn't know that the key exists
180+
markerAlias.get(array[i + 1]).set(this.tileInfluence[neighbor], [angle, neighbor]);
181+
}
166182
}
167183
});
168184
}

0 commit comments

Comments
 (0)