Пример #1
0
    def is_valid_move(self, pos):

        land_posx, land_posy = util.sgf_to_pos(pos)
        board_copy = copy.deepcopy(self.board)
        # 最先判断落子位置是不是空点,如果是不是空点,那么一定是不可以下的。
        if self.board[land_posx][land_posy] != EMPTY_STONE:
            return False
        # 判断它的周围是不是有空点,如果有空点,那么一定是可以下的。
        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 True
        # 判断吃子的话,先算一下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 False
        if has_eat:
            return True

        # 如果没有吃子,那么可能就是往对方里面填子,那么用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 False
        return True
Пример #2
0
    def place_stone(self, pos):
        land_posx, land_posy = util.sgf_to_pos(pos)
        num = util.pos_to_num((land_posx, land_posy))
        self.place_stone_num(num)
        """
        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
        # 如果是停一手,则做如下操作
        if land_posx < 0:
            self.history[current_player].append('tt')
            self.zob_history.append(self.zob_history[-1])
            self.round += 1
            return
        # 先判断是否合法

        if self.is_valid_move(pos) is False:
            # print 'Invalid!'
            return
        # 如果合法,则做这些操作:
        """
        """
        1. 减去对方棋串的气
        2. 将新的子加入本方的棋串中
            2.1 遍历本方所有棋串的气,如果有重合,记录备用
            2.2 将这些有重合的都加入这个新的棋串中去
            2.3 删除那些重合加入的棋串
            2.4 重新计算新串的气
        3. 对对面所有没气了的棋串:如果对面没有没气了的棋串,并且本方的气是0,说明自尽,那么对本方这块棋的周围,
            3.1 对于每个没气了的棋串的每个子,看上下左右(注意边界)
            3.2 上下左右如果有本方的棋子,那么加入一个列表备用
            3.3 删除这个棋串
        4. 重新生成棋盘
        5. 记录的这些黑子,判断属于哪些棋块,对这些棋块重新算气
        """
        """