2 Commits

Author SHA1 Message Date
93243165bf 寻路:reachable 与 find_path 两个独立工具(完整版 + 可达性判断)
用户裁定:完整版寻路 + 可达性判断,且这两个是**两个独立工具**;
未加载走到边界为止并如实报告;执行方式两者都给。

新增 mcfold/pathfind.py:
- 移动词表对齐 mineflayer movements.js:forward/step_up/step_down/drop/jump/dig/place
- A*(八向 + 高度),可按「节点数/半径」有界
- reachable:只答「能不能到 + 大概多远」,**不给路线**,默认不挖不放
- find_path:给具体路线 + world_changes(要挖/放哪些方块,逐格列出)

修的真 bug(6 个):
1. is_ground(这格是实心底)与 is_standable(脚能停这格)语义混淆,差一格
   → 混用导致平地找不到落脚点,只肯搭桥
2. can_already_pass 判据用错对象(拿「更上方 standable」当「已能通过」,
   而那是挖完才成立)→ dig 永不生成,2 格墙走不通
3. dig 只支持挖 1 格 → 4 格墙永远不通。改「挖穿一列」,代价按格数线性
4. 代价权重失衡 → 1 格台阶被挖而不是 step_up(挖穿一排墙)
   调高 dig/place 代价 + 加「背离目标的额外代价」后修正
5. ★ 未加载被报成 exhausted(听起来像「地形不通」):根因是 neighbors()
   在未加载格不生成移动 ⇒ A* 的未加载检测永远执行不到
   → 改为主动探测边界,现在报 hit_unloaded + 停在边界 + 已走步数
6. Terrain.known 调用签名错;挖清单会含空气

诚实性(用户最在意的一条):
- 未加载格所有判定回 None,**不当成空旷**
- 岩浆/水不当地面;solid=True 但致命的(仙人掌/岩浆块/篝火)也被排除
- 认不出的方块 → 不知道(None),不猜
- 碰撞粒度只有 block/empty 两档这个限制**写在返回值里**

判据 19 项;5 项变异全被抓。
★ 「岩浆当地面」变异第一次**没被抓** —— 查下去发现我的判据测的是冗余代码
  (lava/water 本来 solid=False,去掉 hazard 检查也不会红);
  真正承载语义的是 solid=True 但致命的那批方块 → 改用仙人掌才抓到。
2026-09-26 13:42:32 +08:00
94bcd37e66 M7:面向 LLM 的 API 形状(23 个工具)+ 17 项判据
新增 mcfold/api.py:把 M3/M4/M5/M6 包成 agent 能自己摸清的工具箱
- 观察 14:where_am_i/block_at/column/see/raycast/walkable/slice/
            nearby_blocks/nearby_entities/inventory/surroundings/look_at
- 事件  1:events(含细分层按前缀查)
- 操作  7:chat/command/look/look_at/move/dig/place/use_item/select_slot
- 会话  2:status/describe
- call(name, **kwargs) 派发入口

照 plan §1d 五个维度落地:
- 参数:全部 keyword-only(坐标必须按名字传,LLM 不会搞混 x/y/z)
- 返回:每条带 describe(人类可读摘要)
- 失败:永不抛异常 → ok:false + why + how_to
- 规模:限量 + total/remaining/truncated,明说被截断
- 发现:describe() 一次列全工具 + 约定字典 + 4 条提示;目录与实现双向一致

判据抓到的真问题:坐标工具原允许位置传参 ⇒ 已全改 keyword-only。
★ 判据自身也修正过一次:我把「不能有必填参数」误当成规则,
  实际要判的是参数**种类**(关键字专用)——「坐标必需」与「可位置传」是两件事。

★ 操作失误:变异测试用过期 /tmp 备份覆盖了 state.py(丢 113 行),
  导致一个变异「被抓」其实是坏代码造成 ⇒ 恢复必须用 git,
  且每个变异单独确认基线绿。重做该变异后才确认判据有效。

163 项全通过;5 项变异全被抓
2026-09-26 13:17:17 +08:00