mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 06:02:20 +00:00
a8a8d0b7ca
## Description: The branch includes some improvements in AttackExecution including caching and improved queueing of tiles. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors ## Please put your Discord username so you can be contacted if a bug or regression is found: 1brucben
85 lines
2.1 KiB
TypeScript
85 lines
2.1 KiB
TypeScript
import { TileRef } from "../../game/GameMap";
|
|
|
|
/**
|
|
* Lightweight min-heap specialised for (priority:number, tile:TileRef) pairs.
|
|
* - priorities stored in a contiguous Float32Array
|
|
* - tiles stored in a parallel object array
|
|
*/
|
|
export class FlatBinaryHeap {
|
|
/** parallel arrays: pri[ i ] is the priority of tiles[ i ] */
|
|
private pri: Float32Array;
|
|
private tiles: TileRef[];
|
|
private len = 0; // current number of elements
|
|
|
|
constructor(capacity = 1024) {
|
|
this.pri = new Float32Array(capacity);
|
|
this.tiles = new Array<TileRef>(capacity);
|
|
}
|
|
|
|
/** remove every element without reallocating */
|
|
clear(): void {
|
|
this.len = 0;
|
|
}
|
|
|
|
/** current heap size */
|
|
size(): number {
|
|
return this.len;
|
|
}
|
|
|
|
//insert tiles
|
|
enqueue(tile: TileRef, priority: number): void {
|
|
if (this.len === this.pri.length) this.grow(); // ensure space
|
|
let i = this.len++;
|
|
|
|
/* sift-up */
|
|
while (i > 0) {
|
|
const parent = (i - 1) >> 1;
|
|
if (priority >= this.pri[parent]) break;
|
|
this.pri[i] = this.pri[parent];
|
|
this.tiles[i] = this.tiles[parent];
|
|
i = parent;
|
|
}
|
|
this.pri[i] = priority;
|
|
this.tiles[i] = tile;
|
|
}
|
|
|
|
//remove tiles
|
|
dequeue(): [TileRef, number] {
|
|
if (this.len === 0) throw new Error("heap empty");
|
|
|
|
const topTile = this.tiles[0];
|
|
const topPri = this.pri[0];
|
|
|
|
const lastPri = this.pri[--this.len];
|
|
const lastTile = this.tiles[this.len];
|
|
|
|
/* sift-down */
|
|
let i = 0;
|
|
while (true) {
|
|
const left = (i << 1) + 1;
|
|
if (left >= this.len) break;
|
|
const right = left + 1;
|
|
const child =
|
|
right < this.len && this.pri[right] < this.pri[left] ? right : left;
|
|
if (lastPri <= this.pri[child]) break;
|
|
this.pri[i] = this.pri[child];
|
|
this.tiles[i] = this.tiles[child];
|
|
i = child;
|
|
}
|
|
this.pri[i] = lastPri;
|
|
this.tiles[i] = lastTile;
|
|
return [topTile, topPri];
|
|
}
|
|
|
|
/** double the underlying storage */
|
|
private grow(): void {
|
|
const newCap = this.pri.length << 1;
|
|
|
|
const newPri = new Float32Array(newCap);
|
|
newPri.set(this.pri);
|
|
this.pri = newPri;
|
|
|
|
this.tiles.length = newCap;
|
|
}
|
|
}
|