Ejemplo n.º 1
0
def _dfs(g: MancalaGame, record: List[List[int]]) -> (Result, int, List[List[int]]):
    if g.state is not Result.IN_BATTLE:
        return g.state, g.score, record
    win = Result.WIN_PRE if g.side == 0 else Result.WIN_EPI
    lose = Result.WIN_EPI if g.side == 0 else Result.WIN_PRE
    best = None
    for pos in g.pos_candidates():
        gg = g.copy()
        gg.move(pos)
        res = _dfs(gg, record + [[g.side, pos]])
        if best is None:
            best = res
        if res[0] is win:
            if best[0] is not win:
                best = res
            elif best[1] < res[1]:
                # スコアが良い
                best = res
            elif best[1] == res[1] and len(best[2]) > len(res[2]):
                # スコアが同じならできるだけ早く勝つ
                best = res
        elif res[0] is Result.DRAW:
            if best[0] is lose:
                best = res
            elif len(best[2]) < len(res[2]):
                # 引き分けならばできるだけ試合を引っ張る
                best = res
        elif best[0] is lose:
            if best[1] > res[1]:
                # 負け具合を緩和
                best = res
            elif len(best[2]) < len(res[2]):
                # できるだけ試合を引っ張る
                best = res
    return best
Ejemplo n.º 2
0
def _dfs_result_only(g: MancalaGame, record: List[List[int]]) -> (Result, List[List[int]]):
    if g.state is not Result.IN_BATTLE:
        return g.state, record
    win = Result.WIN_PRE if g.side == 0 else Result.WIN_EPI
    lose = Result.WIN_EPI if g.side == 0 else Result.WIN_PRE
    best = None
    for pos in g.pos_candidates():
        gg = g.copy()
        gg.move(pos)
        res = _dfs_result_only(gg, record + [[g.side, pos]])
        if best is None:
            best = res
        if res[0] is win:
            best = res
            break
        elif res[0] is Result.DRAW:
            if best[0] is lose:
                best = res
            elif len(best[1]) < len(res[1]):
                # 引き分けならばできるだけ試合を引っ張る
                best = res
        elif best[0] is lose:
            if len(best[1]) < len(res[1]):
                # できるだけ試合を引っ張る
                best = res
    return best
Ejemplo n.º 3
0
    def iter_g(self):
        from random import choice

        while True:
            g = MancalaGame(self.pit, self.stone)
            while g.state is Result.IN_BATTLE:
                yield g
                pos = choice(g.pos_candidates())
                g.move(pos)
Ejemplo n.º 4
0
 def think(self, g: MancalaGame):
     while True:
         pos = self.input_int('pos: ')
         try:
             g.copy().move(pos)
             break
         except MancalaGameError as e:
             print(e)
     return [pos]
Ejemplo n.º 5
0
 def iter_nex(g: MancalaGame):
     ini_side = g.side
     stack = [g]
     while stack:
         g = stack.pop()
         for pos in g.pos_candidates():
             gg = g.copy()
             nex = gg.move(pos)
             if gg.state is Result.IN_BATTLE:
                 if nex == ini_side:
                     stack.append(gg)
                     continue
             yield gg
Ejemplo n.º 6
0
 def iter_pos(g: MancalaGame):
     ini_side = g.side
     stack = [[g, []]]
     while stack:
         g, pos_list = stack.pop()
         for pos in g.pos_candidates():
             gg = g.copy()
             pp = pos_list + [pos]
             nex = gg.move(pos)
             if gg.state is Result.IN_BATTLE:
                 if nex == ini_side:
                     stack.append([gg, pp])
                     continue
             yield gg, tuple(pp)
Ejemplo n.º 7
0
 def _evf_ml(side: int, g: MancalaGame):
     m = model[g.side]
     vec = g.to_vec()
     score = m.predict([vec])[0]
     if side == 0:
         return score
     else:
         return -score
Ejemplo n.º 8
0
def evf_point_diff(side: int, g: MancalaGame) -> int:
    res = _eval_result(side, g)
    if res is not None:
        return res
    pre, epi = g.get_points()
    if side == 0:
        return pre - epi
    else:
        return epi - pre
Ejemplo n.º 9
0
class BattleManager:
    def __init__(self, pit: int, stone: int, ai1: AIBase, ai2: AIBase):
        self.pit = pit
        self.stone = stone
        self.ai_list = [ai1, ai2]
        self.game = MancalaGame(self.pit, self.stone)

    def battle(self, debug=False):
        if debug:
            print(self.game.purity_dumps())
        while self.game.state is Result.IN_BATTLE:
            this_side = self.game.side
            assert this_side in [0, 1]
            ai = self.ai_list[this_side]
            pos_list = ai.think(self.game.copy())
            assert isinstance(pos_list, (list, tuple)), pos_list
            assert len(pos_list) >= 1, pos_list
            try:
                for pos in pos_list:
                    assert self.game.side == this_side
                    self.game.move(pos)
                    if debug:
                        print()
                        print(f'side: {this_side}')
                        print(f'pos: {pos}')
                        print(self.game.purity_dumps())
            except MancalaGameError as e:
                print(ai, e)
                if this_side == 0:
                    return Result.WIN_EPI,
                else:
                    return Result.WIN_PRE
        p1, p2 = self.game.get_points()
        print(self.game.state, p1, p2)
        return self.game.state
Ejemplo n.º 10
0
def interact():
    def input_int(prompt):
        while True:
            try:
                return int(input(prompt))
            except ValueError:
                pass

    pit = input_int('pit: ')
    stone = input_int('stone: ')
    g = MancalaGame(pit, stone)
    while g.state is Result.IN_BATTLE:
        print(g.purity_dumps())
        print(f'next: {g.side}')
        while True:
            pos = input_int('pos: ')
            try:
                g.move(pos)
                break
            except MancalaGameError as e:
                print(e)
        print()
    print(g.state)
Ejemplo n.º 11
0
def main():
    tasks = {
        'dfs': dfs,
        'dfs_result_only': dfs_result_only,
    }
    p = argparse.ArgumentParser()
    p.add_argument('task', choices=list(tasks))
    p.add_argument('--pit', '-p', type=int, default=4)
    p.add_argument('--stone', '-s', type=int, default=4)
    p.add_argument('--no-debug', action='store_true')
    p.add_argument('--output', '-o')
    args = p.parse_args()

    result = tasks[args.task](args.pit, args.stone)
    g = MancalaGame(args.pit, args.stone)
    data = {
        'pit': args.pit,
        'stone': args.stone,
        'board': [],
    }
    print(f'pit={args.pit}')
    print(f'stone={args.stone}')
    if not args.no_debug:
        print(g.purity_dumps())
    for side, pos in result.record:
        g.move(pos)
        if not args.no_debug:
            print()
            print(f'side={side}')
            print(f'pos={pos}')
            print(g.purity_dumps())
        data['board'].append(g.copy().board)
    print(result.result)
    print(f'score={result.score}')

    if args.output:
        path = Path(args.output)
        with path.open('w') as f:
            json.dump(data, f, indent=4)
Ejemplo n.º 12
0
 def think(self, g: MancalaGame):
     from random import choice
     return [choice(g.pos_candidates())]
Ejemplo n.º 13
0
def dfs_result_only(pit, stone) -> SearchResult:
    g = MancalaGame(pit, stone)
    result, record = _dfs_result_only(g, [])
    return SearchResult(result, record, None)
Ejemplo n.º 14
0
def dfs(pit, stone) -> SearchResult:
    g = MancalaGame(pit, stone)
    result, score, record = _dfs(g, [])
    return SearchResult(result, record, score)
Ejemplo n.º 15
0
 def __init__(self, pit: int, stone: int, ai1: AIBase, ai2: AIBase):
     self.pit = pit
     self.stone = stone
     self.ai_list = [ai1, ai2]
     self.game = MancalaGame(self.pit, self.stone)