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 CHANGED
@@ -178,6 +178,12 @@ pnpm check
178
178
 
179
179
  构建结果同时包含 ESM、CommonJS、类型声明和 source map。
180
180
 
181
+ ## 参与贡献
182
+
183
+ 欢迎通过 GitHub 提交错误报告、规则和文案改进、新机制、测试、文档,以及可复现的模型评测成绩。开发流程和评测报告要求请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)。
184
+
185
+ 当前的模型对比报告位于 [`benchmarks/`](./benchmarks/default-maze-model-comparison-2026-09-17.md)。欢迎提交任何模型、任何平台的结果;报告需要保留原始回答,并记录准确的模型、推理设置、试题参数、工具权限和评分方式。
186
+
181
187
  ## 许可证
182
188
 
183
189
  [MIT](./LICENSE) © ziioai
package/README.md CHANGED
@@ -191,6 +191,12 @@ pnpm check
191
191
 
192
192
  The build emits ESM, CommonJS, type declarations, and source maps to `dist/`.
193
193
 
194
+ ## Contributing
195
+
196
+ Bug reports, rule and wording improvements, new mechanisms, tests, documentation, and reproducible model evaluation results are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) for the development workflow and benchmark submission requirements.
197
+
198
+ The current comparison report is available under [`benchmarks/`](./benchmarks/default-maze-model-comparison-2026-09-17.md). Results from any model or platform are welcome; scores should preserve the raw response and document the exact model, reasoning setting, parameters, tool access, and scoring method.
199
+
194
200
  ## License
195
201
 
196
202
  [MIT](./LICENSE) © ziioai
package/dist/cli.cjs CHANGED
@@ -362,7 +362,8 @@ function analyzeSolidCellMaze(maze) {
362
362
  const distances = bfsDistances(maze.entry, graph);
363
363
  const degreeValues = [...graph.values()].map((items) => items.length);
364
364
  const edgeCount = degreeValues.reduce((sum, value) => sum + value, 0) / 2;
365
- const mainPath = shortestPath(maze, maze.entry, maze.goal);
365
+ const mainPath = shortestPathInGraph(graph, maze.entry, maze.goal);
366
+ const entryGoalSeparators = separatingCellKeys(graph, maze.entry, maze.goal);
366
367
  const objectCounts = {};
367
368
  for (const object of maze.objects ?? []) {
368
369
  objectCounts[object.type] = (objectCounts[object.type] ?? 0) + 1;
@@ -380,7 +381,7 @@ function analyzeSolidCellMaze(maze) {
380
381
  entryGoalDistance: mainPath.length > 0 ? mainPath.length - 1 : null,
381
382
  doorCount: maze.doors.length,
382
383
  gatingDoorCount: maze.doors.filter(
383
- (door) => shortestPath(maze, maze.entry, maze.goal, door.position).length === 0
384
+ (door) => entryGoalSeparators.has(cellKey(door.position))
384
385
  ).length,
385
386
  objectCounts
386
387
  };
@@ -450,6 +451,9 @@ function validateSolidCellMaze(maze) {
450
451
  function shortestPath(maze, start, goal, excludedCell = null) {
451
452
  if (excludedCell && (sameCell(start, excludedCell) || sameCell(goal, excludedCell))) return [];
452
453
  const graph = adjacency(maze, excludedCell);
454
+ return shortestPathInGraph(graph, start, goal);
455
+ }
456
+ function shortestPathInGraph(graph, start, goal) {
453
457
  const queue = [start];
454
458
  const parent = /* @__PURE__ */ new Map([[cellKey(start), null]]);
455
459
  const values = /* @__PURE__ */ new Map([[cellKey(start), start]]);
@@ -581,12 +585,14 @@ function degreeMap(maze) {
581
585
  }
582
586
  function selectGatingDoorIndices(maze, mainPath, count) {
583
587
  if (count === 0) return [];
584
- const degrees = degreeMap(maze);
588
+ const graph = adjacency(maze);
589
+ const separators = separatingCellKeys(graph, maze.entry, maze.goal);
585
590
  const candidates = [];
586
591
  for (let index = 3; index < mainPath.length - 3; index += 1) {
587
592
  const pathCell = mainPath[index];
588
- if (!pathCell || (degrees.get(cellKey(pathCell)) ?? 0) !== 2) continue;
589
- if (shortestPath(maze, maze.entry, maze.goal, pathCell).length === 0) candidates.push(index);
593
+ if (!pathCell) continue;
594
+ const key = cellKey(pathCell);
595
+ if ((graph.get(key)?.length ?? 0) === 2 && separators.has(key)) candidates.push(index);
590
596
  }
591
597
  if (candidates.length < count) {
592
598
  throw new Error(`Only ${candidates.length} non-bypassable path cells are available for ${count} doors.`);
@@ -605,6 +611,59 @@ function selectGatingDoorIndices(maze, mainPath, count) {
605
611
  if (selected.length !== count) throw new Error(`Could not space ${count} doors along the main path.`);
606
612
  return selected.sort((left, right) => left - right);
607
613
  }
614
+ function separatingCellKeys(graph, start, goal) {
615
+ const startKey = cellKey(start);
616
+ const goalKey = cellKey(goal);
617
+ if (!graph.has(startKey) || !graph.has(goalKey)) return /* @__PURE__ */ new Set();
618
+ const discovered = /* @__PURE__ */ new Map();
619
+ const low = /* @__PURE__ */ new Map();
620
+ const parent = /* @__PURE__ */ new Map([[startKey, null]]);
621
+ const stack = [
622
+ { key: startKey, nextNeighbor: 0 }
623
+ ];
624
+ let order = 1;
625
+ discovered.set(startKey, order);
626
+ low.set(startKey, order);
627
+ while (stack.length > 0) {
628
+ const frame = stack.at(-1);
629
+ if (!frame) break;
630
+ const adjacent = graph.get(frame.key) ?? [];
631
+ const next = adjacent[frame.nextNeighbor];
632
+ if (next) {
633
+ frame.nextNeighbor += 1;
634
+ const nextKey = cellKey(next);
635
+ if (!discovered.has(nextKey)) {
636
+ order += 1;
637
+ discovered.set(nextKey, order);
638
+ low.set(nextKey, order);
639
+ parent.set(nextKey, frame.key);
640
+ stack.push({ key: nextKey, nextNeighbor: 0 });
641
+ continue;
642
+ }
643
+ if (nextKey !== parent.get(frame.key)) {
644
+ low.set(frame.key, Math.min(low.get(frame.key) ?? order, discovered.get(nextKey) ?? order));
645
+ }
646
+ continue;
647
+ }
648
+ stack.pop();
649
+ const parentKey = parent.get(frame.key);
650
+ if (parentKey) {
651
+ low.set(parentKey, Math.min(low.get(parentKey) ?? order, low.get(frame.key) ?? order));
652
+ }
653
+ }
654
+ if (!discovered.has(goalKey)) return /* @__PURE__ */ new Set();
655
+ const separators = /* @__PURE__ */ new Set();
656
+ let childKey = goalKey;
657
+ while (childKey !== startKey) {
658
+ const parentKey = parent.get(childKey);
659
+ if (!parentKey) break;
660
+ if (parentKey !== startKey && (low.get(childKey) ?? Number.POSITIVE_INFINITY) >= (discovered.get(parentKey) ?? Number.NEGATIVE_INFINITY)) {
661
+ separators.add(parentKey);
662
+ }
663
+ childKey = parentKey;
664
+ }
665
+ return separators;
666
+ }
608
667
  function freePathCellBefore(mainPath, preferredIndex, occupied) {
609
668
  for (let distance = 0; distance < mainPath.length; distance += 1) {
610
669
  for (const index of [preferredIndex - distance, preferredIndex + distance]) {