mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 17:46:46 +00:00
110 lines
2.9 KiB
TypeScript
110 lines
2.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { GameMapImpl } from "../src/core/game/GameMap";
|
|
import { densePathToKeypointSegments } from "../src/core/game/MotionPlans";
|
|
import { MiniMapTransformer } from "../src/core/pathfinding/transformers/MiniMapTransformer";
|
|
|
|
function makeMap(width: number, height: number): GameMapImpl {
|
|
return new GameMapImpl(width, height, new Uint8Array(width * height), 0);
|
|
}
|
|
|
|
function expandPlanDda(
|
|
map: GameMapImpl,
|
|
points: Uint32Array,
|
|
segmentSteps: Uint32Array,
|
|
): number[] {
|
|
const out: number[] = [];
|
|
if (points.length === 0) return out;
|
|
out.push(points[0] >>> 0);
|
|
for (let i = 0; i < segmentSteps.length; i++) {
|
|
const steps = segmentSteps[i] >>> 0;
|
|
const a = points[i] >>> 0;
|
|
const b = points[i + 1] >>> 0;
|
|
const ax = map.x(a);
|
|
const ay = map.y(a);
|
|
const bx = map.x(b);
|
|
const by = map.y(b);
|
|
const dx = bx - ax;
|
|
const dy = by - ay;
|
|
for (let t = 1; t <= steps; t++) {
|
|
out.push(
|
|
map.ref(
|
|
Math.round(ax + (dx * t) / steps),
|
|
Math.round(ay + (dy * t) / steps),
|
|
) >>> 0,
|
|
);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
describe("densePathToKeypointSegments", () => {
|
|
it("expands back to the dense path for axis segments", () => {
|
|
const map = makeMap(10, 10);
|
|
|
|
const dense = [
|
|
map.ref(1, 1),
|
|
map.ref(2, 1),
|
|
map.ref(3, 1),
|
|
map.ref(4, 1),
|
|
map.ref(4, 2),
|
|
map.ref(4, 3),
|
|
map.ref(4, 4),
|
|
];
|
|
|
|
const plan = densePathToKeypointSegments(dense);
|
|
expect(plan).not.toBeNull();
|
|
if (!plan) return;
|
|
|
|
const expanded = expandPlanDda(map, plan.points, plan.segmentSteps);
|
|
expect(expanded).toEqual(dense.map((t) => t >>> 0));
|
|
});
|
|
});
|
|
|
|
describe("MiniMapTransformer planSegments compression", () => {
|
|
it("preserves endpoints and total steps while merging collinear runs", () => {
|
|
const map = makeMap(10, 10);
|
|
const miniMap = makeMap(5, 5);
|
|
|
|
const miniPath = [
|
|
miniMap.ref(0, 0),
|
|
miniMap.ref(1, 0),
|
|
miniMap.ref(2, 0),
|
|
miniMap.ref(2, 1),
|
|
miniMap.ref(2, 2),
|
|
];
|
|
|
|
const inner = {
|
|
findPath() {
|
|
return miniPath.slice();
|
|
},
|
|
planSegments() {
|
|
return {
|
|
points: Uint32Array.from(miniPath),
|
|
segmentSteps: Uint32Array.from([1, 1, 1, 1]),
|
|
};
|
|
},
|
|
};
|
|
|
|
const transformer = new MiniMapTransformer(inner as any, map, miniMap);
|
|
const from = map.ref(0, 0);
|
|
const to = map.ref(4, 4);
|
|
|
|
const dense = transformer.findPath(from, to);
|
|
expect(dense).not.toBeNull();
|
|
|
|
const plan = transformer.planSegments(from, to);
|
|
expect(plan).not.toBeNull();
|
|
if (!plan) return;
|
|
|
|
expect(Array.from(plan.points)).toEqual([
|
|
from >>> 0,
|
|
map.ref(4, 0) >>> 0,
|
|
to >>> 0,
|
|
]);
|
|
expect(Array.from(plan.segmentSteps)).toEqual([4, 4]);
|
|
|
|
const totalSteps = Array.from(plan.segmentSteps).reduce((a, b) => a + b, 0);
|
|
expect(totalSteps).toBe(8);
|
|
});
|
|
});
|