{
  "lead": "五子棋规则简单，却足以展示博弈 AI 的核心思路：「如果我走这里，对手最好的应对是什么，我再怎么应对……」把这棵走法树往下展开几层，在叶子上给局面打分，再一层层往回推，就能选出当前最好的一步。这个 AI 用 Rust 实现了带 α-β 剪枝的搜索，每一步都在浏览器里实时计算。",
  "formulas": [
    [
      "score(n) = max<sub>m</sub> −score(child(n, m))",
      "负极大值（negamax）：对手的最好就是我的最坏"
    ]
  ],
  "terms": [
    [
      "局面评估：五元组",
      "棋盘上所有连续 5 格的窗口共有 572 个。只含一方棋子的窗口按子数计分（1 子 1 分、2 子 12 分、3 子 150 分、4 子 2000 分），双方都有子的窗口已经不可能连成五，记 0 分。一条活四会同时出现在两个「4 子窗口」里，所以自然比冲四分高；「XX_X」这样中间有空的棋型也能被识别。"
    ],
    [
      "α-β 剪枝",
      "搜索时记住「我方至少能拿到的分」α 和「对手最多允许的分」β。一旦发现某个分支已经不可能比已知的更好，就不再展开它的其余走法。走法排序越好，剪掉的越多，同样时间能搜得更深。"
    ],
    [
      "候选走法",
      "只考虑已有棋子周围 2 格内的空位，并按「进攻价值 + 防守价值」排序，只展开最好的 12 个。这样每层分支数从两百多降到 12，4 层搜索也只需要几万个局面。"
    ],
    [
      "战术优先",
      "搜索之前先检查两件事：自己有没有一步就能连五的点（有就直接下），对手有没有（有就必须堵）。更复杂的战术（比如堵活三、做双三）交给搜索去发现。"
    ],
    [
      "服务端 AI：多线程分摊顶层着法",
      "选择「服务端」后，同一份 <code>gomoku</code> 源码编译成原生程序（<code>crates/native/compute</code>），由 <code>/api/compute/gomoku</code> 调用。顶层的候选着法（最多 12 个）分给多个线程各自往下搜，线程之间共享当前最好的分数 α 来剪枝，所以能在几秒内搜到 8～9 层，而浏览器单线程通常止步于 5 层。"
    ],
    [
      "结果和单线程完全一致",
      "并行时，一个着法开始搜索时 α 可能已经被别的线程抬高，它只拿到“不超过某值”的上界。搜完后，凡是上界恰好等于最高分的着法，都用完整窗口重新搜一次拿到精确分数，再按“精确分数最高、候选顺序最靠前”选择——正是单线程的规则。测试保证同样的局面和深度下，服务端和浏览器走同一步、给出同一个评估。"
    ]
  ],
  "flow": [
    [
      "js",
      "点击棋盘时，JS 把像素坐标换算成交叉点，调用 <code>gomoku_play(x, y)</code>，Rust 检查是否合法、是否连成五子。"
    ],
    [
      "rust",
      "轮到 AI 时，JS 调用 <code>gomoku_ai_move(深度)</code>。Rust 在棋盘副本上做 α-β 搜索，返回落点、搜索过的局面数和评分。"
    ],
    [
      "js",
      "JS 先让浏览器画出玩家的棋子，再开始计算（搜索会占用主线程），然后落下 AI 的棋子，并高亮最后一手或获胜的五子。"
    ]
  ],
  "perf": [
    "难度对应搜索深度。每多搜一层，局面数大约乘以有效分支数（剪枝后通常只有 3~5），所以 5 层比 3 层慢一个数量级左右。底部会显示每一步实际搜索的局面数和耗时。",
    "实测（Node 中运行同一个 WASM，AI 自我对弈 30 手）：深度 3 每步约 1ms，深度 4 中位数 4ms，深度 5 中位数 9ms、最慢 23ms，最多搜索约 5,800 个局面。搜索在主线程同步运行，这个量级不会让页面卡顿；如果继续加深，可以把搜索放进 Web Worker。",
    "这是无禁手规则：黑棋先手有明显优势，长连（6 子以上）也算获胜。",
    "服务端的加速比受顶层候选数（最多 12 个）限制，而且先开始的线程 α 还低、剪枝少，总节点数比单线程多；20 线程下 7～9 层大约快 3～4 倍。更深的搜索才是棋力提升的来源：「AI 对战」里可以看到服务端 6 层以上稳定赢浏览器 2～3 层。"
  ],
  "src": [
    [
      "crates/games/gomoku/src/lib.rs",
      ""
    ],
    [
      "www/gomoku/index.js",
      ""
    ],
    [
      "crates/native/compute/src/lib.rs",
      "服务端调用"
    ]
  ]
}
