コード例 #1
0
ファイル: board.py プロジェクト: wsdd2/PikachuGo
    def is_valid_move_numpos(self, pos):
        land_posx, land_posy = util.num_to_pos(pos)
        board_copy = copy.deepcopy(self.board)
        # 最先判断落子位置是不是空点,如果是不是空点,那么一定是不可以下的。
        if self.board[land_posx][land_posy] != EMPTY_STONE:
            return 0
        # 判断它的周围是不是有空点,如果有空点,那么一定是可以下的。
        for i in range(4):
            if 0 <= land_posx + dx[i] < 19 and 0 <= land_posy + dy[i] < 19:
                if self.board[land_posx + dx[i]][land_posy +
                                                 dy[i]] == EMPTY_STONE:
                    return 1
        # 判断吃子的话,先算一下zobrist哈希
        num_pos = util.pos_to_num((land_posx, land_posy))
        hash = self.zob_history[-1]
        if self._current_player() == SIDE_BLACK:
            c_zb_state = zb.STATE_BLACK
            o_zb_state = zb.STATE_WHITE
            current_stone = BLACK_STONE
            opposite_stone = WHITE_STONE
        else:
            c_zb_state = zb.STATE_WHITE
            o_zb_state = zb.STATE_BLACK
            current_stone = WHITE_STONE
            opposite_stone = BLACK_STONE
        # 判断是否吃子了,如果吃子了,那么应该是可以下的,但是要判断打劫,用zb哈希
        has_eat = False
        for key, value in self.group[self._opposite_player()].items():
            if value.count_liberty() == 1:
                if value.has_liberty(util.pos_to_num((land_posx, land_posy))):
                    has_eat = True
                    for s in self.group[self._opposite_player()][key].stone:
                        px, py = util.num_to_pos(s)
                        board_copy[px][py] = EMPTY_STONE
                        # 取消对方子的状态
                        hash = zb.get_new_hash(hash, self.zob_arr, o_zb_state,
                                               s)
                        # 赋予空点的状态
                        hash = zb.get_new_hash(hash, self.zob_arr,
                                               zb.STATE_EMPTY, s)
        board_copy[land_posx][land_posy] = current_stone
        hash = zb.get_new_hash(hash, self.zob_arr, zb.STATE_EMPTY, num_pos)
        hash = zb.get_new_hash(hash, self.zob_arr, c_zb_state, num_pos)

        if has_eat and len(self.zob_history) > 2:
            if self.zob_history[-2] == hash:
                # print 'ko rule!'
                return -1
        if has_eat:
            return 1

        # 如果没有吃子,那么可能就是往对方里面填子,那么用dfs遍历一下,看看这个棋串周围是否有空点
        # pos_x, pos_y是坐标!
        self.found = False
        self._dfs(board_copy, land_posx, land_posy, current_stone)
        if self.found is False:
            self.found = False
            return 0
        return 1
コード例 #2
0
 def recount_liberty(self, side, go_board):
     assert isinstance(go_board, np.ndarray)
     for s in self.stone:
         posx, posy = util.num_to_pos(s)
         for i in range(4):
             if 0 <= posx + dx[i] < 19 and 0 <= posy + dy[i] < 19:
                 if go_board[posx + dx[i]][posy + dy[i]] == EMPTY_STONE:
                     self.add_liberty(util.pos_to_num((posx + dx[i], posy + dy[i])))
コード例 #3
0
 def judge_ladder(self, key):
     self_copy = copy.deepcopy(self)
     pos = -1
     opp = set()
     for st in self_copy.group[self_copy._current_player()][key].stone:
         posx, posy = util.num_to_pos(st)
         pos = st
         for i in range(4):
             if 0 <= posx + dx[i] < 19 and 0 <= posy + dy[i] < 19:
                 if self_copy.board[posx + dx[i]][posy + dy[i]] == self_copy._opposite_stone():
                     opp.add(util.pos_to_num((posx + dx[i], posy + dy[i])))
     """
     
     for st in opp:
         for key, value in self_copy.group[self_copy._opposite_player()].items():
             if value.has_stone(st):
                 self_copy.ladder_string.append(key)
                 break
     """
     self_copy.ladder_string = list(opp)
     return self_copy._judge_ladder(pos)
コード例 #4
0
def gtp_io():
    global board
    PASS_FLAG = 0
    known_commands = [
        'boardsize', 'clear_board', 'komi', 'play', 'genmove', 'quit', 'name',
        'version', 'known_command', 'list_commands', 'protocal_version'
    ]
    while True:
        try:
            line = raw_input().strip()
        except EOFError:
            break

        if line == '':
            continue
        command = [s.lower() for s in line.split()]
        if re.match('\d+', command[0]):
            cmdid = command[0]
            command = command[1:]
        else:
            cmdid = ''
        ret = ''

        if command[0] == 'boardsize':
            debug_print(
                "Warning: Trying to set incompatible boardsize %s (!= %d)" %
                (command[1], 19))
            ret = None
        elif command[0] == 'clear_board':
            board = board.Go()
        elif command[0] == 'komi':
            pass
        elif command[0] == 'play':
            if command[2].upper() == 'PASS':
                go.place_stone_num(-1)
                PASS_FLAG = 1

            if command[1].upper() == 'B':  # and board.current_player == BLACK:
                # print command[2]
                go.place_stone_num(util.gtppos_to_num(command[2].upper()))
            elif command[1].upper(
            ) == 'W':  # and board.current_player == WHITE:
                # print command[2]
                go.place_stone_num(util.gtppos_to_num(command[2].upper()))
        elif command[0] == 'genmove':

            move = -1

            if PASS_FLAG == 1:
                PASS_FLAG = 0
                move = -1
                ret = 'pass'
            else:
                move = make_prediction()
                if move is None:
                    ret = 'pass'
                if move == -1:
                    ret = 'resign'
                else:
                    ret = util.pos_to_gtppos(util.num_to_pos(move))
            go.place_stone_num(move)

        elif command[0] == 'name':
            ret = 'PikachuP, 2018'
        elif command[0] == 'version':
            ret = '0.2'
        elif command[0] == 'list_commands':
            ret = '\n'.join(known_commands)
        elif command[0] == 'protocol_version':
            ret = '2'
        elif command[0] == 'quit':
            print '=%s \n\n' % (cmdid, ),
            exit(0)
        else:
            debug_print("Unknown Command! ")
            ret = None

        if ret is not None:
            print '=%s %s\n\n' % (cmdid, ret),
        else:
            print '?%s ???\n\n' % (cmdid, ),
        sys.stdout.flush()
コード例 #5
0
def make_prediction():
    global go, first_run, first_run_2
    """
    第一步:
            先对盘面生成特征:这是一个16通道的特征。
            使用策略网络(也可能是RL网络)
            
    """
    feature = go.generate()
    """
    
            用iter喂数据给神经网络
            
    """
    iter = mx.io.NDArrayIter(data=feature)
    """
            如果是第一次运行,则绑定模型,并设置参数
    """

    if first_run:
        module.bind(data_shapes=iter.provide_data)
        module.set_params(arg_params, aux_params)
        first_run = False
    """
    t0 = time.clock()
    for i in range(320):
        feature = go.generate()
        iter = mx.io.NDArrayIter(data=feature)
        pred = module.predict(iter).asnumpy()
        pred = feature[0][2].reshape(1, 361) * pred
        out = np.argsort(-pred)
        go.place_stone_num(out[0][0])
    go_plot.go_plot(go.board)
    print time.clock() - t0
    exit(0)
    """
    """
    
            module.predict(iter)  进行预测,结果在pred中。他是一个(1, 361)的numpy数组
    
    """
    pred = module.predict(iter).asnumpy()
    """
                    由于有禁入点的缘故,用feature[0][2]点乘pred。feature[0][2]就是可入点的盘面特征
    """
    pred = feature[0][2].reshape(1, 361) * pred
    """
                    先取反  然后从小到大排   60 40 20...  -60 -40 -20   这样的话就是概率从小到大的顺序。
    """
    out = np.argsort(-pred)
    """
            X_prior    ->      X 的平均回报
    """

    if config.enable_ucb is False:
        return out[0][0]

    X_prior = []
    """
            T_prior    ->      已经探索的次数
            基于策略网络,假设一定的先验知识
            total是访问的总次数
    """
    T_prior = [config.pre_place_num] * config.search_position_num
    total = config.pre_place_num * config.search_position_num
    """
            循环做5次,具体看config.search_position_num的配置
    
    """
    for i in range(config.search_position_num):
        # 打印策略网络的落子概率
        debug_print(
            util.pos_to_gtppos(util.num_to_pos(out[0][i])) + '\t%.2f%%' %
            (pred[0][out[0][i]] * 100))
        # 复制一份
        gocopy = copy.deepcopy(go)
        # 用复制的一份盘面模拟走子!
        gocopy.place_stone_num(out[0][i])
        # 生成模拟走子后的盘面
        next_state = gocopy.generate()
        # 使用价值网络预测胜率
        iter_ = mx.io.NDArrayIter(data=next_state)
        if first_run_2:
            v_module.bind(data_shapes=iter_.provide_data)
            v_module.set_params(v_arg_params, v_aux_params)
            first_run_2 = False
        # 结果返回到result中
        result = v_module.predict(iter_).asnumpy()[0][0]
        """
            将    策略网络   与   价值网络   相结合!
            
            先验X_prior是
            
            result -> -1 要输  +1 要赢
            盘面判断的是对面的
            所以 (result + 1) / 2    ->    0->对面要输    1->对面要赢
            反过来:
                                              我要赢         我要输
                                    1 - (result + 1) / 2     0  我输了  1 我赢了
            
            
        """
        X_prior.append(config.value_weight * (1 - ((result + 1) / 2)) +
                       POLICY_WEIGHT * pred[0][out[0][i]])
        """
        判断本方是哪一方,然后输出对手的获胜概率
        """
        if gocopy.current_player() == 0:
            side = 'BLACK: '
        else:
            side = 'WHITE: '
        debug_print(side + '%.2f%%' % ((result + 1) / 0.02))

    for i in range(config.search_position_num):
        """
        先输出探索他的 X拔 
        """
        debug_print(util.pos_to_gtppos(util.num_to_pos(out[0][i])))
        debug_print("-> {:.2f}%".format(X_prior[i] * 100))

    # 计个时
    t = time.time()
    # stat_black, stat_white = 0, 0

    # 判断现在是哪一方走棋,然后设置target值。
    """
    target值用来判断谁输谁赢
    """
    if go.current_player() == 0:
        target = 1
        _side = 'BLACK'
    else:
        target = 0
        _side = 'WHITE'
    """
    TO: 要探索多少轮。
    这个值会逐渐递增
    如果有更好的策略,在这里改进          PikachuP
    """
    TO = ROLLOUTS
    end_search_value = TO / 2 + config.pre_place_num
    for i in range(TO):
        # 选择一个位置:
        ucb_max = -1000
        ucb_id = 0
        """
            选择最值得探索的位置
        """
        for j in range(config.search_position_num):
            ucb = X_prior[j] + UCB_C * math.sqrt(math.log(total) / T_prior[j])
            if ucb > ucb_max:
                ucb_max = ucb
                ucb_id = j
        """
                    在最值得探索的位置!位置模拟落子!
        """
        go_copy = copy.deepcopy(go)
        # pre_black, pre_white = go_copy.evaluate_2()
        go_copy.place_stone_num(out[0][ucb_id])
        """
                用蒙特卡洛模拟模拟走子
                返回的是一个模拟走子的胜负结果,0表示白胜利,1表示黑胜利
        """

        res = monte_carlo_simulate(go_copy)
        prompt = ""
        """
        这里的代码算的是chens形势判断领先多少
        被我废弃了
        if _black - _white > pre_black - pre_white > 0 and target == 1:# 本方黑,黑胜利
            X_prior[ucb_id] = (X_prior[ucb_id] * T_prior[ucb_id] + 1) / (T_prior[ucb_id] + 1)
            T_prior[ucb_id] += 1
            prompt = "Win"
            if T_prior[ucb_id] > TO / 2:
                total += 1
                break
        elif _white - _black > pre_white - pre_white and target == 0:    # 本方白,白胜利
            X_prior[ucb_id] = (X_prior[ucb_id] * T_prior[ucb_id] + 1) / (T_prior[ucb_id] + 1)
            T_prior[ucb_id] += 1
            prompt = "Win"
            if T_prior[ucb_id] > TO / 2:
                total += 1
                break
        else:
            X_prior[ucb_id] = (X_prior[ucb_id] * T_prior[ucb_id]) / (T_prior[ucb_id] + 1)
            T_prior[ucb_id] += 1
            prompt = "Loss"
            if T_prior[ucb_id] > TO / 2:
                total += 1
                break
        total += 1
        """

        if res == 1 and target == 1:  # 本方黑,黑胜利
            # 获胜概率增加了!
            X_prior[ucb_id] = (X_prior[ucb_id] * T_prior[ucb_id] +
                               1) / (T_prior[ucb_id] + 1)
            # 被访问次数增加了!
            T_prior[ucb_id] += 1
            # 提示获胜
            prompt = "Win"
            # 提早结束,提高效率
            # 原因:访问节点次数超过二分之一,不可能再有节点比这个更优了
            if T_prior[ucb_id] > end_search_value:
                total += 1
                break
        elif res == 0 and target == 0:  # 本方白,白胜利
            X_prior[ucb_id] = (X_prior[ucb_id] * T_prior[ucb_id] +
                               1) / (T_prior[ucb_id] + 1)
            T_prior[ucb_id] += 1
            prompt = "Win"
            if T_prior[ucb_id] > end_search_value:
                total += 1
                break
        else:
            X_prior[ucb_id] = (X_prior[ucb_id] *
                               T_prior[ucb_id]) / (T_prior[ucb_id] + 1)
            T_prior[ucb_id] += 1
            prompt = "Loss"
            if T_prior[ucb_id] > end_search_value:
                total += 1
                break
        total += 1
        # 提示一下而已
        debug_print("Playout\t" + str(i) + '\t' +
                    util.pos_to_gtppos(util.num_to_pos(out[0][ucb_id])) +
                    "\t" + prompt)
    """
                    max_index       它是我要采取的策略!
    """
    max_index = T_prior.index(max(T_prior))

    debug_print(_side + ":{:.2f}%".format(X_prior[max_index] * 100))

    # UCB完毕,打印一下节点的访问次数
    for i in range(config.search_position_num):
        debug_print("visited: " +
                    util.pos_to_gtppos(util.num_to_pos(out[0][i])) + ":" +
                    str(T_prior[i]))
    # 再打印一下耗时
    debug_print("Time:" + str(time.time() - t))

    # debug_print(str(out))
    # print pred
    # print feature[0][2].reshape(1, 361)
    # return pred.argmax()
    """
    如果最优秀的评估值小于一个阈值,那么认输
    """
    if X_prior[max_index] < 0.12:
        return -1
    """
    
    overall_score_max = - 999999
    overall_score_index = -1
    for i in range(4):
        overall_score = X_prior[i] * 0.4 + pred[0][out[0][i]] * 0.6
        if overall_score > overall_score_max:
            overall_score_max = overall_score
            overall_score_index = i
    """
    return out[0][max_index]
コード例 #6
0
    def place_stone_num(self, pos):
        land_posx, land_posy = util.num_to_pos(pos)
        current_player = self._current_player()
        opposite_player = self._opposite_player()
        num_pos = util.pos_to_num((land_posx, land_posy))
        current_stone, opposite_stone = None, None
        # 如果是停一手,则做如下操作
        """
            mistake
            !!!!
            停一手忘记更新棋盘了!
        """
        if land_posx < 0:
            self.history[current_player].append(pos)
            self.zob_history.append(self.zob_history[-1])
            """
            2019年1月7日01:54:54修补该bug
            """
            """
            
            if current_player == SIDE_BLACK:
                current_stone = BLACK_STONE
                opposite_stone = WHITE_STONE
            else:
                current_stone = WHITE_STONE
                opposite_stone = BLACK_STONE
            """
            self.round += 1

            return
        # 先判断是否合法

        if self.is_valid_move(util.pos_to_sgf((land_posx, land_posy))) is False:
            # print 'Invalid!'
            return False
        # 如果合法,则做这些操作:
        """
        1. 减去对方棋串的气
        2. 将新的子加入本方的棋串中
            2.1 遍历本方所有棋串的气,如果有重合,记录备用
            2.2 将这些有重合的都加入这个新的棋串中去
            2.3 删除那些重合加入的棋串
            2.4 重新计算新串的气
        3. 对对面所有没气了的棋串:如果对面没有没气了的棋串,并且本方的气是0,说明自尽,那么对本方这块棋的周围,
            3.1 对于每个没气了的棋串的每个子,看上下左右(注意边界)
            3.2 上下左右如果有本方的棋子,那么加入一个列表备用
            3.3 删除这个棋串
        4. 重新生成棋盘
        5. 记录的这些黑子,判断属于哪些棋块,对这些棋块重新算气
        """
        # 合法了的话,棋盘更新
        if current_player == SIDE_BLACK:
            self.board[land_posx][land_posy] = BLACK_STONE
            current_stone = BLACK_STONE
            opposite_stone = WHITE_STONE
        else:
            self.board[land_posx][land_posy] = WHITE_STONE
            current_stone = WHITE_STONE
            opposite_stone = BLACK_STONE
        # 1. 减去对方棋串的气,并用dead列表记录哪些死透了的棋子
        dead = []
        for key, value in self.group[opposite_player].items():
            assert isinstance(value, Group)
            value.remove_liberty(num_pos)
            if value.count_liberty() == 0:
                dead.append(key)

        # 遍历本方所有棋串的气,如果有重合,记录备用在merge里面
        merge = []
        for key, value in self.group[current_player].items():
            assert isinstance(value, Group)
            if value.has_liberty(num_pos):
                merge.append(key)
        # 2.2 新建一个棋串,将这些有重合的都加入这个新的棋串中去
        self.group[current_player][self.round] = Group(self.round)
        self.group[current_player][self.round].add_stone(num_pos)
        # 2.3 删除那些重合加入的棋串
        for ids in merge:
            self.group[current_player][self.round].merge_stone(self.group[current_player][ids])
            self.group[current_player].pop(ids)
        # 2.4 重新计算新串的气(有一个不必要的参数side)
        self.group[current_player][self.round].recount_liberty(current_player, self.board)

        # 3 对面所有没气了的棋串,在dead里面,删掉这些子,但是记录一下他们
        record_dead_stone = set()
        for d in dead:
            for st in self.group[opposite_player][d].stone:
                record_dead_stone.add(st)
                posx, posy = util.num_to_pos(st)
                # 在这里清除了对方的死子
                self.board[posx][posy] = EMPTY_STONE
        # 由于记录了死子的位置,所以看一下它的上下左右,有没有本方的子
        # 有的话,记录本方这些子的棋串号
        recount_liberty_group = set()
        for dead_pos in record_dead_stone:
            posx, posy = util.num_to_pos(dead_pos)
            for i in range(4):
                if 0 <= posx + dx[i] < 19 and 0 <= posy + dy[i] < 19:
                    if self.board[posx + dx[i]][posy + dy[i]] == current_stone:
                        for key, value in self.group[current_player].items():
                            if value.has_stone(util.pos_to_num((posx + dx[i], posy + dy[i]))):
                                recount_liberty_group.add(key)
        # 删掉这些棋串
        for del_ids in dead:
            self.group[opposite_player].pop(del_ids)
        # 对需要重新算气的本方棋串重新算气
        for rec in recount_liberty_group:
            self.group[current_player][rec].recount_liberty(current_player, self.board)

        if current_player == SIDE_BLACK:
            c_zb_state = zb.STATE_BLACK
            o_zb_state = zb.STATE_WHITE
        else:
            c_zb_state = zb.STATE_WHITE
            o_zb_state = zb.STATE_BLACK

        hash = self.zob_history[-1]
        # 取消本方落子的那个空点
        hash = zb.get_new_hash(hash, self.zob_arr, zb.STATE_EMPTY, util.pos_to_num((land_posx, land_posy)))
        # 本方落子在那个空点
        hash = zb.get_new_hash(hash, self.zob_arr, c_zb_state, util.pos_to_num((land_posx, land_posy)))

        for ds in record_dead_stone:
            hash = zb.get_new_hash(hash, self.zob_arr, o_zb_state, ds)
            hash = zb.get_new_hash(hash, self.zob_arr, zb.STATE_EMPTY, ds)

        self.zob_history.append(hash)
        self.history[current_player].append(pos)
        # self.print_board()
        self.round += 1
        return True
コード例 #7
0
    def generate_fast(self):
        features = np.zeros((1, 8, 19, 19), dtype=np.int8)
        current_stone = self._current_stone()
        opposite_stone = self._opposite_stone()


        """本方棋子的位置,和对方棋子的位置2/16
        """
        features[0][0] = (self.board == current_stone) + 0
        features[0][1] = (self.board == opposite_stone) + 0
        """5个气位的特征,外加两个征子的特征 7,8,9,10,11,12,13/16
        """
        for key, value in self.group[self._current_player()].items():
            if value.count_liberty() == 1:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][2][x][y] = 1
            elif value.count_liberty() == 2:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][3][x][y] = 1
            elif value.count_liberty() == 3:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][4][x][y] = 1
            elif value.count_liberty() == 4:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][5][x][y] = 1
            elif value.count_liberty() >= 5:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][6][x][y] = 1
        for key, value in self.group[self._opposite_player()].items():
            if value.count_liberty() == 1:

                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][2][x][y] = 1
            elif value.count_liberty() == 2:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][3][x][y] = 1
            elif value.count_liberty() == 3:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][4][x][y] = 1
            elif value.count_liberty() == 4:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][5][x][y] = 1
            elif value.count_liberty() >= 5:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][6][x][y] = 1

        if len(self.history[self._opposite_player()]) > 0 and self.history[self._opposite_player()][-1] >= 0:
            x, y = util.num_to_pos(self.history[self._opposite_player()][-1])
            features[0][7][x][y] = 1

        return features
コード例 #8
0
    def generate(self):
        features = np.zeros((1, 16, 19, 19), dtype=np.int8)
        current_stone = self._current_stone()
        opposite_stone = self._opposite_stone()


        """本方棋子的位置,和对方棋子的位置2/16
        """
        features[0][0] = (self.board == current_stone) + 0
        features[0][1] = (self.board == opposite_stone) + 0
        for i in range(361):
            px, py = util.num_to_pos(i)
            if self.is_valid_move_numpos(i) == 1:
                """空点的位置3/16
                """
                features[0][2][px][py] = 1
            elif self.is_valid_move_numpos(i) == -1:
                """如果是打劫,那么+打劫位置4/16
                """
                features[0][12][px][py] = 1
            eye = self.is_eye(i)
            if eye == 2:
                """对于本方来说,极有可能成为眼位的空点5/16
                """
                features[0][10][px][py] = 1
            elif eye == 3:
                """已经是眼位的点6/16
                """
                features[0][11][px][py] = 1

        """5个气位的特征,外加两个征子的特征 7,8,9,10,11,12,13/16
        """
        for key, value in self.group[self._current_player()].items():
            if value.count_liberty() == 1:
                """1气要做征子判断!对于本方的1气棋子来说,
                先自己走,然后让对方走
                """
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    if self.judge_ladder(key) == 1:
                        features[0][13][x][y] = 1
                    features[0][3][x][y] = 1
            elif value.count_liberty() == 2:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][4][x][y] = 1
            elif value.count_liberty() == 3:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][5][x][y] = 1
            elif value.count_liberty() == 4:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][6][x][y] = 1
            elif value.count_liberty() >= 5:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][7][x][y] = 1
        for key, value in self.group[self._opposite_player()].items():
            if value.count_liberty() == 1:
                """对方的1气也做征子判断,但是本方先让一手,然后看征子情况
                """
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    if self.judge_ladder_oppo(key) == 1:
                        features[0][14][x][y] = 1
                    features[0][3][x][y] = 1
            elif value.count_liberty() == 2:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][4][x][y] = 1
            elif value.count_liberty() == 3:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][5][x][y] = 1
            elif value.count_liberty() == 4:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][6][x][y] = 1
            elif value.count_liberty() >= 5:
                for st in value.stone:
                    x, y = util.num_to_pos(st)
                    features[0][7][x][y] = 1

        if len(self.history[self._opposite_player()]) > 0 and self.history[self._opposite_player()][-1] >= 0:
            x, y = util.num_to_pos(self.history[self._opposite_player()][-1])
            features[0][9][x][y] = 1
            features[0][8][x][y] = 1

        if len(self.history[self._opposite_player()]) > 1 and self.history[self._opposite_player()][-2] >= 0:
            x, y = util.num_to_pos(self.history[self._opposite_player()][-2])
            features[0][8][x][y] = 1

        if len(self.history[self._current_player()]) > 0 and self.history[self._current_player()][-1] >= 0:
            x, y = util.num_to_pos(self.history[self._current_player()][-1])
            features[0][8][x][y] = 1

        if self._current_player() == SIDE_BLACK:
            features[0][15] = np.ones((19, 19), dtype=np.int8)
        return features
コード例 #9
0
    def is_eye(self, pos):
        current_stone = self._current_stone()
        opp_stone = self._opposite_stone()
        # 先判断旁边的四个角
        pos_x, pos_y = util.num_to_pos(pos)
        if self.board[pos_x][pos_y] != EMPTY_STONE:
            return EYE_NOT
        if pos == 0 and self.board[0][1] == self.board[1][0] == self.board[1][1] == current_stone:
            return EYE_MUST
        if pos == 18 and self.board[0][17] == self.board[1][17] == self.board[1][18] == current_stone:
            return EYE_MUST
        if pos == 342 and self.board[17][0] == self.board[17][1] == self.board[18][1] == current_stone:
            return EYE_MUST
        if pos == 360 and self.board[18][17] == self.board[17][17] == self.board[17][18] == current_stone:
            return EYE_MUST

        if pos_x == 0 and 0 < pos_y < 18:
            cnt = 0
            if self.board[pos_x][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x][pos_y - 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x][pos_y + 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y - 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y + 1] == opp_stone:
                cnt -= 1
            if cnt == 5:
                return EYE_MUST
            if cnt == 4:
                return EYE_HIGH_PRO
            """
        if pos_x == 18 and 0 < pos_y < 18:
            if self.board[pos_x][pos_y - 1] == self.board[pos_x][pos_y + 1] == self.board[pos_x - 1][pos_y - 1] \
                    == self.board[pos_x - 1][pos_y] == self.board[pos_x - 1][pos_y + 1] == current_stone:
                return EYE_MUST
            """
        if pos_x == 18 and 0 < pos_y < 18:
            cnt = 0
            if self.board[pos_x][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x][pos_y - 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x][pos_y + 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x - 1][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y - 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x - 1][pos_y] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y] == opp_stone:
                cnt -= 1
            if self.board[pos_x - 1][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y + 1] == opp_stone:
                cnt -= 1
            if cnt == 5:
                return EYE_MUST
            if cnt == 4:
                return EYE_HIGH_PRO
        """

        if pos_y == 0 and 0 < pos_x < 18:
            if self.board[pos_x - 1][pos_y] == self.board[pos_x + 1][pos_y] == self.board[pos_x - 1][pos_y + 1] \
                    == self.board[pos_x][pos_y + 1] == self.board[pos_x + 1][pos_y + 1] == current_stone:
                return EYE_MUST
        """
        if pos_y == 0 and 0 < pos_x < 18:
            cnt = 0
            if self.board[pos_x - 1][pos_y] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y] == opp_stone:
                cnt -= 1
            if self.board[pos_x - 1][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y + 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x][pos_y + 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y + 1] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y + 1] == opp_stone:
                cnt -= 1
            if cnt == 5:
                return EYE_MUST
            if cnt == 4:
                return EYE_HIGH_PRO

        if pos_y == 18 and 0 < pos_x < 18:
            cnt = 0
            if self.board[pos_x - 1][pos_y] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y] == opp_stone:
                cnt -= 1
            if self.board[pos_x - 1][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x - 1][pos_y - 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x][pos_y - 1] == opp_stone:
                cnt -= 1
            if self.board[pos_x + 1][pos_y - 1] == current_stone:
                cnt += 1
            elif self.board[pos_x + 1][pos_y - 1] == opp_stone:
                cnt -= 1
            if cnt == 5:
                return EYE_MUST
            if cnt == 4:
                return EYE_HIGH_PRO



        if 0 < pos_x < 18 and 0 < pos_y < 18:
            cnt_beside = 0
            cnt_not_beside = 0
            score = 0.0
            for i in range(4):
                if self.board[pos_x + dx[i]][pos_y + dy[i]] == current_stone:
                    cnt_beside += 1
                    score += 2.5
                elif self.board[pos_x + dx[i]][pos_y + dy[i]] == opp_stone:
                    score -= 4
            for i in range(4):
                if self.board[pos_x + kdx[i]][pos_y + kdy[i]] == current_stone:
                    cnt_not_beside += 1
                    score += 1
                elif self.board[pos_x + kdx[i]][pos_y + kdy[i]] == opp_stone:
                    score -= 2
            if cnt_beside == 4 and cnt_not_beside >= 3:
                return EYE_MUST
            if score > 8:
                return EYE_HIGH_PRO

        return EYE_NOT