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.js
CHANGED
|
@@ -337,7 +337,8 @@ function analyzeSolidCellMaze(maze) {
|
|
|
337
337
|
const distances = bfsDistances(maze.entry, graph);
|
|
338
338
|
const degreeValues = [...graph.values()].map((items) => items.length);
|
|
339
339
|
const edgeCount = degreeValues.reduce((sum, value) => sum + value, 0) / 2;
|
|
340
|
-
const mainPath =
|
|
340
|
+
const mainPath = shortestPathInGraph(graph, maze.entry, maze.goal);
|
|
341
|
+
const entryGoalSeparators = separatingCellKeys(graph, maze.entry, maze.goal);
|
|
341
342
|
const objectCounts = {};
|
|
342
343
|
for (const object of maze.objects ?? []) {
|
|
343
344
|
objectCounts[object.type] = (objectCounts[object.type] ?? 0) + 1;
|
|
@@ -355,7 +356,7 @@ function analyzeSolidCellMaze(maze) {
|
|
|
355
356
|
entryGoalDistance: mainPath.length > 0 ? mainPath.length - 1 : null,
|
|
356
357
|
doorCount: maze.doors.length,
|
|
357
358
|
gatingDoorCount: maze.doors.filter(
|
|
358
|
-
(door) =>
|
|
359
|
+
(door) => entryGoalSeparators.has(cellKey(door.position))
|
|
359
360
|
).length,
|
|
360
361
|
objectCounts
|
|
361
362
|
};
|
|
@@ -425,6 +426,9 @@ function validateSolidCellMaze(maze) {
|
|
|
425
426
|
function shortestPath(maze, start, goal, excludedCell = null) {
|
|
426
427
|
if (excludedCell && (sameCell(start, excludedCell) || sameCell(goal, excludedCell))) return [];
|
|
427
428
|
const graph = adjacency(maze, excludedCell);
|
|
429
|
+
return shortestPathInGraph(graph, start, goal);
|
|
430
|
+
}
|
|
431
|
+
function shortestPathInGraph(graph, start, goal) {
|
|
428
432
|
const queue = [start];
|
|
429
433
|
const parent = /* @__PURE__ */ new Map([[cellKey(start), null]]);
|
|
430
434
|
const values = /* @__PURE__ */ new Map([[cellKey(start), start]]);
|
|
@@ -556,12 +560,14 @@ function degreeMap(maze) {
|
|
|
556
560
|
}
|
|
557
561
|
function selectGatingDoorIndices(maze, mainPath, count) {
|
|
558
562
|
if (count === 0) return [];
|
|
559
|
-
const
|
|
563
|
+
const graph = adjacency(maze);
|
|
564
|
+
const separators = separatingCellKeys(graph, maze.entry, maze.goal);
|
|
560
565
|
const candidates = [];
|
|
561
566
|
for (let index = 3; index < mainPath.length - 3; index += 1) {
|
|
562
567
|
const pathCell = mainPath[index];
|
|
563
|
-
if (!pathCell
|
|
564
|
-
|
|
568
|
+
if (!pathCell) continue;
|
|
569
|
+
const key = cellKey(pathCell);
|
|
570
|
+
if ((graph.get(key)?.length ?? 0) === 2 && separators.has(key)) candidates.push(index);
|
|
565
571
|
}
|
|
566
572
|
if (candidates.length < count) {
|
|
567
573
|
throw new Error(`Only ${candidates.length} non-bypassable path cells are available for ${count} doors.`);
|
|
@@ -580,6 +586,59 @@ function selectGatingDoorIndices(maze, mainPath, count) {
|
|
|
580
586
|
if (selected.length !== count) throw new Error(`Could not space ${count} doors along the main path.`);
|
|
581
587
|
return selected.sort((left, right) => left - right);
|
|
582
588
|
}
|
|
589
|
+
function separatingCellKeys(graph, start, goal) {
|
|
590
|
+
const startKey = cellKey(start);
|
|
591
|
+
const goalKey = cellKey(goal);
|
|
592
|
+
if (!graph.has(startKey) || !graph.has(goalKey)) return /* @__PURE__ */ new Set();
|
|
593
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
594
|
+
const low = /* @__PURE__ */ new Map();
|
|
595
|
+
const parent = /* @__PURE__ */ new Map([[startKey, null]]);
|
|
596
|
+
const stack = [
|
|
597
|
+
{ key: startKey, nextNeighbor: 0 }
|
|
598
|
+
];
|
|
599
|
+
let order = 1;
|
|
600
|
+
discovered.set(startKey, order);
|
|
601
|
+
low.set(startKey, order);
|
|
602
|
+
while (stack.length > 0) {
|
|
603
|
+
const frame = stack.at(-1);
|
|
604
|
+
if (!frame) break;
|
|
605
|
+
const adjacent = graph.get(frame.key) ?? [];
|
|
606
|
+
const next = adjacent[frame.nextNeighbor];
|
|
607
|
+
if (next) {
|
|
608
|
+
frame.nextNeighbor += 1;
|
|
609
|
+
const nextKey = cellKey(next);
|
|
610
|
+
if (!discovered.has(nextKey)) {
|
|
611
|
+
order += 1;
|
|
612
|
+
discovered.set(nextKey, order);
|
|
613
|
+
low.set(nextKey, order);
|
|
614
|
+
parent.set(nextKey, frame.key);
|
|
615
|
+
stack.push({ key: nextKey, nextNeighbor: 0 });
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
if (nextKey !== parent.get(frame.key)) {
|
|
619
|
+
low.set(frame.key, Math.min(low.get(frame.key) ?? order, discovered.get(nextKey) ?? order));
|
|
620
|
+
}
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
stack.pop();
|
|
624
|
+
const parentKey = parent.get(frame.key);
|
|
625
|
+
if (parentKey) {
|
|
626
|
+
low.set(parentKey, Math.min(low.get(parentKey) ?? order, low.get(frame.key) ?? order));
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
if (!discovered.has(goalKey)) return /* @__PURE__ */ new Set();
|
|
630
|
+
const separators = /* @__PURE__ */ new Set();
|
|
631
|
+
let childKey = goalKey;
|
|
632
|
+
while (childKey !== startKey) {
|
|
633
|
+
const parentKey = parent.get(childKey);
|
|
634
|
+
if (!parentKey) break;
|
|
635
|
+
if (parentKey !== startKey && (low.get(childKey) ?? Number.POSITIVE_INFINITY) >= (discovered.get(parentKey) ?? Number.NEGATIVE_INFINITY)) {
|
|
636
|
+
separators.add(parentKey);
|
|
637
|
+
}
|
|
638
|
+
childKey = parentKey;
|
|
639
|
+
}
|
|
640
|
+
return separators;
|
|
641
|
+
}
|
|
583
642
|
function freePathCellBefore(mainPath, preferredIndex, occupied) {
|
|
584
643
|
for (let distance = 0; distance < mainPath.length; distance += 1) {
|
|
585
644
|
for (const index of [preferredIndex - distance, preferredIndex + distance]) {
|