俺の備忘録

個人的な備忘録です。

Pythonの勉強がてらオセロAIを作ってみる③

はじめに

前回(Pythonの勉強がてらオセロAIを作ってみる① - 俺の備忘録)からの続き

  1. オセロの基本ロジックの実装
  2. 完全ランダムな手で打つAIの実装
  3. 今現在、最もたくさん石が取れる手を選ぶAIの実装 
  4. ちょっとだけオセロの定石を知ってるAIの実装
  5. もうちょっとオセロの定石を知っているAIの実装  <= 本稿はココ
  6. MinMax法で打つAIの実装
  7. AlphaBeta法で打つAIの実装
  8. モンテカルロ法で打つAIの実装
  9. モンテカルロ木探索?で打つAIの実装
  10. (このあたりで機械学習を取り入れたい?)

ちょっとだけオセロの定石を知っているAIの実装

以下の最低限の定石を加味した手を選ぶAIを作ってみた。

  • 4隅を優先して取る
  • 4隅に隣接する場所は避ける

初回(Pythonの勉強がてらオセロAIを作ってみる① - 俺の備忘録)のPlayer.pyを拡張した。

class RandomAiKnowGoodMove(Player):
    """ 最低限の手の良し悪しを知っているAI """

    def next_move(self, board):
        known_good_moves = [[0, 0], [0, 7], [7, 0], [7, 7]]
        known_bad_moves = [[0, 1], [1, 0], [1, 1], [0, 6], [1, 6], [1, 7], [6, 0], [6, 1], [7, 1], [7, 6], [6, 7], [6, 6]]

        all_candidates = ReverseCommon.get_puttable_points(board, self._color)

        # 4隅が取れるなら取る
        good_moves = filter(lambda good_move: good_move in known_good_moves, all_candidates)
        if len(good_moves) > 0:
            return good_moves[random.randint(0, len(good_moves) - 1)]

        # 4隅に隣接する場所は避ける
        not_bad_moves = filter(lambda  not_bad_move: not_bad_move not in (known_good_moves + known_bad_moves), all_candidates)
        if len(not_bad_moves) > 0:
            return not_bad_moves[random.randint(0, len(not_bad_moves) - 1)]

        return all_candidates[random.randint(0, len(all_candidates) - 1)]

戦わせてみる

それぞれのパターンで3000回ずつ戦わせてみた。 ※初回 (Pythonの勉強がてらオセロAIを作ってみる① - 俺の備忘録)のMain.pyを拡張し、30行目から34行目でAIを切り替えて戦わせる

パターン①:
黒(完全ランダムAI):72勝
白(定石知ってるAI):928勝

パターン②:
黒(定石を知っているAI):849勝
白(完全ランダムAI):151勝

パターン③:
黒(最も石を取る手を選ぶAI):89勝
白(定石知ってるAI):911

パターン④:
黒(定石を知っているAI):872勝
白(最も石を取る手を選ぶAI):128勝

やっぱり4隅の影響力は大きいなぁ。。。