Python(オセロ15_評価での安定石)

■評価軸としての裏返すことができない石について。
四隅や手の数などの評価軸の中で、裏返すことができない石(安定石)というものがあった。こちらについても評価の1つとして取り入れたい。

例えば、四隅に置かれる石は挟まれないので、裏返ることはない。そこから横や縦につながる石も裏返されるパターンが無い。こういったものを安定石とする。置く場所が無いので裏返されないというものは含めない。

例えば、下の図なら、左上に固まっている10つの石がそれにあたる。

これを求めるコードを生成AIで出したものが下(ただし近似的なもの)。

def count_stableStones(board, stone):
    stable = np.zeros((10, 10), dtype=bool)

    corners = [
        (1, 1),
        (1, 8),
        (8, 1),
        (8, 8)
    ]

    changed = True

    # 角を安定石にする
    for r, c in corners:
        if board[r, c] == stone:
            stable[r, c] = True

    while changed:
        changed = False
        for r in range(1, 9):
            for c in range(1, 9):

                if board[r, c] != stone:
                    continue

                if stable[r, c]:
                    continue

                horizontal = False
                vertical = False

                # 左方向
                left_ok = True
                for x in range(c - 1, 0, -1):
                    if board[r, x] != stone:
                        left_ok = False
                        break
                    if stable[r, x]:
                        break

                # 右方向
                right_ok = True
                for x in range(c + 1, 9):
                    if board[r, x] != stone:
                        right_ok = False
                        break
                    if stable[r, x]:
                        break

                horizontal = left_ok or right_ok

                # 上方向
                up_ok = True
                for y in range(r - 1, 0, -1):
                    if board[y, c] != stone:
                        up_ok = False
                        break
                    if stable[y, c]:
                        break

                # 下方向
                down_ok = True
                for y in range(r + 1, 9):
                    if board[y, c] != stone:
                        down_ok = False
                        break
                    if stable[y, c]:
                        break

                vertical = up_ok or down_ok

                if horizontal and vertical:
                    stable[r, c] = True
                    changed = True
    return np.sum(stable)

これは左右、上下に安定石が隣接するかチェックし、周りにあればその石も安定石とするコード。先の例で実行すると、10と正しく判定されている。
下のような例では11として、赤の四角で囲んだところも安定石として判定されている。これは誤判定となるので、あくまで近似的なものと分かる。

下の例では、黒(●)が16、白(○)が11として四隅それぞれで正しくカウントされている。

この安定石を含めて、その盤面で置くことができる手の数(黒、白)、現在の石の数(黒、白)、安定石(黒、白)、四隅に置かれている数、リスクがある場所(四隅の斜め前)に置かれている数の指標を取得できるようにした。データの持ち方はもう少し検討だけど、次くらいでEloレーティングを使いつつ、いくつかのロジックで結果まで見てみたい。