键只用了每个角色的首字母

三次重复需要一种方法来判断“这是同一个局面”。Mistboard 把每个局面转成一个字符串,并统计每个字符串出现了几次。

function repetitionKey(position):
    parts = []
    for sq, p in position.pieces (sorted by sq):
        # red chariot on a1: "a1" + "r" + "c"
        parts.append(sq + p.color[0] + p.role[0])
    return position.turn + "|" + join(parts, ",")

after every move:
    seen[repetitionKey(position)] += 1
    if it reaches 3: draw (or a perpetual-check loss)

role[0] 是角色名的首字母,而象棋的七种角色里有两种以 c 开头。a1 上的红车和 b3 上的红炮分别写成 a1rc 和 b3rc。两者互换后,写出来仍然是 a1rc 和 b3rc。

左:开局。右:红方 a1 的车和 b3 的炮互换了位置。旧的键分不出两者。

十四步合法着法,判出一盘和棋

红方用五步完成互换,同时黑方把一个车走出去再走回来;然后双方各把一个马跳出去再跳回来:

走完旧计数实际计数
开局1开局局面:1
互换,每方 5 步2互换局面:1
马跳出再跳回3,判和互换局面:2

十四步合法着法,网站就判了和棋。没有棋手报告过这个问题;它是在给揭棋加上重复局面规则时,阅读这段代码发现的。

修复:把角色名完整写出

# red chariot on a1: "a1:r.chariot"
parts.append(sq + ":" + p.color[0] + "." + p.role)

一个测试会走完这十四步,并检查对局仍在继续。迷雾国际象棋(王 king 和马 knight 都是 k)和鸭子象棋里也有同样的简写;两者都已修复。

对网站意味着什么

已结束的对局:没有一盘改变。用修正后的键重放,全部 29 盘象棋重复局面和棋、2 盘长将判负、2 盘鸭子象棋和棋和 19 盘迷雾国际象棋和棋,结果都一样。

新对局:象棋、迷雾象棋、迷雾国际象棋和鸭子象棋,只有在同一局面真正出现三次时,才会因重复局面结束。

谜题:谜题挖掘器的查重会同时识别新旧两种写法,所以已发布的谜题不会被当成新题再出现。

用缩写拼成的键需要一项检查,而这项检查从任何单个缩写上都看不出来:没有两个名字缩写成同一个东西。手写的字母表在有人为车选定 r 的那一刻,就做了这项检查。role[0] 从来没有做过。