maze-test 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-CN.md +6 -0
- package/README.md +6 -0
- package/dist/cli.cjs +64 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +64 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +64 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +64 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -390,7 +390,8 @@ function analyzeSolidCellMaze(maze) {
|
|
|
390
390
|
const distances = bfsDistances(maze.entry, graph);
|
|
391
391
|
const degreeValues = [...graph.values()].map((items) => items.length);
|
|
392
392
|
const edgeCount = degreeValues.reduce((sum, value) => sum + value, 0) / 2;
|
|
393
|
-
const mainPath =
|
|
393
|
+
const mainPath = shortestPathInGraph(graph, maze.entry, maze.goal);
|
|
394
|
+
const entryGoalSeparators = separatingCellKeys(graph, maze.entry, maze.goal);
|
|
394
395
|
const objectCounts = {};
|
|
395
396
|
for (const object of maze.objects ?? []) {
|
|
396
397
|
objectCounts[object.type] = (objectCounts[object.type] ?? 0) + 1;
|
|
@@ -408,7 +409,7 @@ function analyzeSolidCellMaze(maze) {
|
|
|
408
409
|
entryGoalDistance: mainPath.length > 0 ? mainPath.length - 1 : null,
|
|
409
410
|
doorCount: maze.doors.length,
|
|
410
411
|
gatingDoorCount: maze.doors.filter(
|
|
411
|
-
(door) =>
|
|
412
|
+
(door) => entryGoalSeparators.has(cellKey(door.position))
|
|
412
413
|
).length,
|
|
413
414
|
objectCounts
|
|
414
415
|
};
|
|
@@ -478,6 +479,9 @@ function validateSolidCellMaze(maze) {
|
|
|
478
479
|
function shortestPath(maze, start, goal, excludedCell = null) {
|
|
479
480
|
if (excludedCell && (sameCell(start, excludedCell) || sameCell(goal, excludedCell))) return [];
|
|
480
481
|
const graph = adjacency(maze, excludedCell);
|
|
482
|
+
return shortestPathInGraph(graph, start, goal);
|
|
483
|
+
}
|
|
484
|
+
function shortestPathInGraph(graph, start, goal) {
|
|
481
485
|
const queue = [start];
|
|
482
486
|
const parent = /* @__PURE__ */ new Map([[cellKey(start), null]]);
|
|
483
487
|
const values = /* @__PURE__ */ new Map([[cellKey(start), start]]);
|
|
@@ -609,12 +613,14 @@ function degreeMap(maze) {
|
|
|
609
613
|
}
|
|
610
614
|
function selectGatingDoorIndices(maze, mainPath, count) {
|
|
611
615
|
if (count === 0) return [];
|
|
612
|
-
const
|
|
616
|
+
const graph = adjacency(maze);
|
|
617
|
+
const separators = separatingCellKeys(graph, maze.entry, maze.goal);
|
|
613
618
|
const candidates = [];
|
|
614
619
|
for (let index = 3; index < mainPath.length - 3; index += 1) {
|
|
615
620
|
const pathCell = mainPath[index];
|
|
616
|
-
if (!pathCell
|
|
617
|
-
|
|
621
|
+
if (!pathCell) continue;
|
|
622
|
+
const key = cellKey(pathCell);
|
|
623
|
+
if ((graph.get(key)?.length ?? 0) === 2 && separators.has(key)) candidates.push(index);
|
|
618
624
|
}
|
|
619
625
|
if (candidates.length < count) {
|
|
620
626
|
throw new Error(`Only ${candidates.length} non-bypassable path cells are available for ${count} doors.`);
|
|
@@ -633,6 +639,59 @@ function selectGatingDoorIndices(maze, mainPath, count) {
|
|
|
633
639
|
if (selected.length !== count) throw new Error(`Could not space ${count} doors along the main path.`);
|
|
634
640
|
return selected.sort((left, right) => left - right);
|
|
635
641
|
}
|
|
642
|
+
function separatingCellKeys(graph, start, goal) {
|
|
643
|
+
const startKey = cellKey(start);
|
|
644
|
+
const goalKey = cellKey(goal);
|
|
645
|
+
if (!graph.has(startKey) || !graph.has(goalKey)) return /* @__PURE__ */ new Set();
|
|
646
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
647
|
+
const low = /* @__PURE__ */ new Map();
|
|
648
|
+
const parent = /* @__PURE__ */ new Map([[startKey, null]]);
|
|
649
|
+
const stack = [
|
|
650
|
+
{ key: startKey, nextNeighbor: 0 }
|
|
651
|
+
];
|
|
652
|
+
let order = 1;
|
|
653
|
+
discovered.set(startKey, order);
|
|
654
|
+
low.set(startKey, order);
|
|
655
|
+
while (stack.length > 0) {
|
|
656
|
+
const frame = stack.at(-1);
|
|
657
|
+
if (!frame) break;
|
|
658
|
+
const adjacent = graph.get(frame.key) ?? [];
|
|
659
|
+
const next = adjacent[frame.nextNeighbor];
|
|
660
|
+
if (next) {
|
|
661
|
+
frame.nextNeighbor += 1;
|
|
662
|
+
const nextKey = cellKey(next);
|
|
663
|
+
if (!discovered.has(nextKey)) {
|
|
664
|
+
order += 1;
|
|
665
|
+
discovered.set(nextKey, order);
|
|
666
|
+
low.set(nextKey, order);
|
|
667
|
+
parent.set(nextKey, frame.key);
|
|
668
|
+
stack.push({ key: nextKey, nextNeighbor: 0 });
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
if (nextKey !== parent.get(frame.key)) {
|
|
672
|
+
low.set(frame.key, Math.min(low.get(frame.key) ?? order, discovered.get(nextKey) ?? order));
|
|
673
|
+
}
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
stack.pop();
|
|
677
|
+
const parentKey = parent.get(frame.key);
|
|
678
|
+
if (parentKey) {
|
|
679
|
+
low.set(parentKey, Math.min(low.get(parentKey) ?? order, low.get(frame.key) ?? order));
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
if (!discovered.has(goalKey)) return /* @__PURE__ */ new Set();
|
|
683
|
+
const separators = /* @__PURE__ */ new Set();
|
|
684
|
+
let childKey = goalKey;
|
|
685
|
+
while (childKey !== startKey) {
|
|
686
|
+
const parentKey = parent.get(childKey);
|
|
687
|
+
if (!parentKey) break;
|
|
688
|
+
if (parentKey !== startKey && (low.get(childKey) ?? Number.POSITIVE_INFINITY) >= (discovered.get(parentKey) ?? Number.NEGATIVE_INFINITY)) {
|
|
689
|
+
separators.add(parentKey);
|
|
690
|
+
}
|
|
691
|
+
childKey = parentKey;
|
|
692
|
+
}
|
|
693
|
+
return separators;
|
|
694
|
+
}
|
|
636
695
|
function freePathCellBefore(mainPath, preferredIndex, occupied) {
|
|
637
696
|
for (let distance = 0; distance < mainPath.length; distance += 1) {
|
|
638
697
|
for (const index of [preferredIndex - distance, preferredIndex + distance]) {
|