Subscribed unsubscribe Subscribe Subscribe

最中限にハマった

id:nishiohirokazuさんの作った最中限オンライン。
http://saichugen-online.appspot.com/
これが面白くてついついハマってしまいまして。
参考:http://d.hatena.ne.jp/nishiohirokazu/searchdiary?word=%2a%5b%BA%C7%C3%E6%B8%C2%5d


現在29戦で9得点、まだまだ下っ端。
しかし負けっぱなしは悔しい!!
ということでAIを作ってみることにした。
Python素人なりに、id:nishiohirokazuさんが公開してくださっているソースを元にお勉強。


http://coderepos.org/share/browser/lang/python/saichugen/saichugen.py
とりあえずオンラインでゴニョゴニョ、は難しそうだからまずはローカルで!
MyAIを作ってみたぉ!

# -*- encoding: utf-8 -*-

from saichugen import Player
from saichugenlib import *

class MyAI(Player):
    name = "MyAI"
    dicision = [(1, 0, -1), (0, 0, 0), (-1, 0, 1)]
    def __init__(self, hand):
        hand.sort()
        self.hand = hand
    def play(self, info):
        handstr = map(to_str, self.hand)
        import copy
        # 未知カードから自分の手持ちを考慮
        self.unknowns = copy.copy(info['unknowns'])
        for i in self.hand:
            self.unknowns.remove(i)
        # 手持ちカードのそれぞれを出したときの得点率を計算
        a = []
        for i in self.hand:
            lt = 0
            gt = 0
            for j in self.unknowns:
                if j < i:
                    lt += 1
                else:
                    gt += 1
            percentage = (1.0 * lt * gt) / (len(self.unknowns) * (len(self.unknowns) - 1))
            a.append([i, percentage])
        # 得点率の平均を算出
        sum = 0.0
        for d in a:
            sum += d[1]
        ave = sum / len(a)
        # ゲームの状況
        if info['game_score'][0] < get_mid(info['game_score']):
            game_ranking = 0
        elif info['game_score'][0] > get_mid(info['game_score']):
            game_ranking = 2
        else:
            game_ranking = 1
        # 現在のラウンドの状況
        if info['round_score'][0] < get_mid(info['round_score']):
            round_ranking = 0
        elif info['round_score'][0] > get_mid(info['round_score']):
            round_ranking = 2
        else:
            round_ranking = 1

        # 候補を考える
        # 得点すべきときには得点率が平均以上のものから選択
        # 得点すべきでないときには得点率が平均以下のものから選択
        recommend = []
        for i in range(len(a)):
            if (a[i][1] - ave) * self.dicision[game_ranking][round_ranking] > 0:
                recommend.append(i)
        if len(recommend) == 0:
            recommend = range(len(a))

        from random import choice
        return self.hand.pop(choice(recommend))

単純に、自分のカードの中から1枚を選択したときにそれが得点になる確率をあらかじめ計算しておいて、自分の現在のゲームスコア、ラウンドスコアを考慮した上で得点率の高いものや低いものを選択する、というようにしてみた。
# ん?確率は比較につかうだけならわざわざ割り算する必要なかったかな…


では、その効果は!?
mainの部分をちょちょい、と書き換えて…

...
DISABLE_DISPLAY = True
DISABLE_LOG = True
...
if __name__ == "__main__":
#    run_game([ConsoleHuman, RandomAI, GoodAI])
    from myai import MyAI
    total = [0, 0, 0]
    for i in range(10000):
        result = run_game([MyAI, RandomAI, RandomAI])
        for i in range(3):
            total[i] += result[i]
    print total

結果は!?

$ time python saichugen.py

[649, -113, -536]

real	0m46.048s
user	0m45.456s
sys	0m0.151s

おぉ、ランダムAI相手ならちょっとは勝てそうな感じだ!
もうちょい状況考慮とか条件分岐を細かくしたらもうちょい期待できるかも!?