连珠规则

作为五子棋国际标准使用的连珠(連珠)规则,认为先手的黑棋占优,因此只对黑棋设置禁手。黑棋不能下三三、四四和长连(6子以上),白棋则没有任何限制。长连对白棋来说甚至算获胜。

最初用连珠规则做引擎时,白棋几乎变得无敌。因为黑棋能够进攻的棋形被禁手挡住,而白棋却可以用同样的棋形随意获胜。

黑白双方相同的禁手

于是我们修改了规则,让黑白之间没有差别。

  • 三三:黑白双方都是禁手。跳三(●_●●、●●_●)也算作三。
  • 长连:黑白双方都是禁手,6子以上不算获胜。只有正好5子才算赢。
  • 四四:黑白双方都允许。
  • 形成五连的着法先于禁手检查进行判断。获胜的着法任何时候都可以下。
禁手棋形。三三(连三+连三)、三三(跳三+连三)、长连对黑白双方都是禁手,四四允许
禁手棋形。三三(连三+连三)、三三(跳三+连三)、长连对黑白双方都是禁手,四四允许

修改之后白棋依然赢了

修改规则的时间没有留在记录里,所以我们以引擎文件最后一次修改的自动对局第五天为界进行了划分。在那之前的445局中白棋赢了419局(94%),在那之后的42局中赢了38局(90%)。

在训练对局中,白棋一直是VLM,黑棋一直是本地AI。所以仅凭这些记录,无法区分白棋获胜是因为规则,还是因为执黑的本地AI太弱。必须重新进行由同一个AI轮流执黑执白的对局。

这一步的实际代码

这是网页引擎的禁手检查。先看是否是获胜的着法,然后只禁止长连和三三。

omook-web/lib/board.tstypescript · 16 行
export function hasKyungsuBan(
  board: Stone[],
  row: number,
  col: number,
  stone: Stone,
  size: number,
): RejectReason | null {
  if (!inBounds(row, col, size)) return "out_of_bounds";
  if (cell(board, row, col, size) !== EMPTY) return "occupied";
  if (wouldWinIfPlaced(board, row, col, stone, size)) return null;

  const g = withStone(board, row, col, stone, size);
  if (hasOverline(g, row, col, stone, size)) return "changmok";
  if (countOpenThreeAxes(g, row, col, stone, size) >= 2) return "sansan";
  return null;
}

下一篇是“3. 看不到靠跳四取胜的AI”。