| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- #!/usr/bin/env python3
- """verify_all_maps.py — 8 张地图全量离线验证: 加载+BFS+A* 通用性证明。
- 每张图: 已知锚点(或自动扫可走格) → BFS 最远可达点 → A* 2格步长规划
- → 逐腿穿墙检查 → 报告耗时/腿数/结果。
- """
- from __future__ import annotations
- import sys
- import time
- from collections import deque
- sys.path.insert(0, "src")
- from pbot.bot.pathfind import LearnedGrid, astar, load_walls_from_map
- DIRS = [(0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1)]
- MAPS = [
- ("等待地图", "0139.map", (24, 30)),
- ("比奇大城", "0.map", (330, 330)),
- ("盟重土城", "3.map", (342, 338)),
- ("天然洞穴一层", "d011.map", None),
- ("比奇矿区", "d401.map", (83, 10)),
- ("地牢一层东(蜈蚣洞穴)", "d601.map", (198, 28)),
- ("沃玛寺庙一层", "d022.map", None),
- ("生死之间", "d613.map", None),
- ]
- def pick_start(walls: set, w: int, h: int) -> tuple[int, int] | None:
- for y in range(h // 4, h * 3 // 4, 3):
- for x in range(w // 4, w * 3 // 4, 3):
- if (x, y) not in walls:
- return (x, y)
- return None
- def bfs_farthest(start: tuple[int, int], walls: set, w: int, h: int
- ) -> tuple[tuple[int, int], int, int]:
- visited = {start}
- dq = deque([(start, 0)])
- far, far_d = start, 0
- while dq:
- (x, y), d = dq.popleft()
- if d > far_d:
- far, far_d = (x, y), d
- for dx, dy in DIRS:
- n = (x + dx, y + dy)
- if n in visited or not (0 <= n[0] < w and 0 <= n[1] < h):
- continue
- if n in walls:
- continue
- visited.add(n)
- dq.append((n, d + 1))
- return far, far_d, len(visited)
- def main() -> int:
- print(f"{'地图':<20} {'尺寸':<12} {'起点':<12} {'BFS最远点':<14} "
- f"{'可达格':<8} {'A*腿数':<8} {'穿墙':<5} {'耗时'}")
- print("-" * 100)
- all_ok = True
- for name, fname, anchor in MAPS:
- t0 = time.time()
- import struct
- with open(f"assets/maps/{fname}", "rb") as f:
- head = f.read(4)
- w, h = struct.unpack("<HH", head)
- walls = load_walls_from_map(f"assets/maps/{fname}")
- t_load = time.time() - t0
- start = anchor if anchor and anchor not in walls else pick_start(walls, w, h)
- if start is None:
- print(f"{name:<20} {w}x{h:<10} — 无可走起点!")
- all_ok = False
- continue
- t0 = time.time()
- far, far_d, reach = bfs_farthest(start, walls, w, h)
- t_bfs = time.time() - t0
- grid = LearnedGrid()
- grid.mark_from_map(walls)
- t0 = time.time()
- path = astar(start, far, grid, max_expand=2_000_000)
- t_astar = time.time() - t0
- cross = 0
- if path:
- for a, b in zip(path, path[1:]):
- mid = ((a[0] + b[0]) // 2, (a[1] + b[1]) // 2)
- if b in walls or (max(abs(b[0]-a[0]), abs(b[1]-a[1])) == 2 and mid in walls):
- cross += 1
- legs = len(path) - 1
- status = "OK" if cross == 0 else f"穿墙{cross}!"
- if cross:
- all_ok = False
- else:
- legs, status = 0, "无路!"
- all_ok = False
- print(f"{name:<20} {w}x{h:<10} {str(start):<12} {str(far):<14} "
- f"{reach:<8} {legs:<8} {cross:<5} "
- f"load {t_load*1000:.0f}ms bfs {t_bfs*1000:.0f}ms astar {t_astar*1000:.0f}ms")
- print("-" * 100)
- print("结论:", "★ 全部通过 — 算法对所有地图有效" if all_ok else "存在失败项!")
- return 0 if all_ok else 1
- if __name__ == "__main__":
- sys.exit(main())
|