示例#1
0
    def __init__(self, size):
        """Crea dos matrices de tamaño pasado por parámetro, una para
        estadísticas y otra para guardar el estado de las piedras. Creamos un
        set de piedras para ir guardando las piedras que estemos comprobando.
        También inicializa un kifu para guardar la partida y un el objetos igs
        que se encargará de conectarse con el servidor que subirá la partida.

        :Param size: tamaño del tablero
        :Type size: int """
        self.size = size
        # El valor 0 es para ir sumando(hay piedra) o restando(no hay)
        # El valor 8 es el nº de veces a buscar antes de hacer la estadística
        self.goban = [[None] * size for i in range(size)]
        self.moves = []
        self.statistical = [[10] * size for i in range(size)]
        self.stones = set()
        self.kifu = Kifu()
示例#2
0
class Goban:
    """Clase tablero, contiene la matriz de estadíticas y funciones para
    rellenar el tablero. """

    def __init__(self, size):
        """Crea dos matrices de tamaño pasado por parámetro, una para
        estadísticas y otra para guardar el estado de las piedras. Creamos un
        set de piedras para ir guardando las piedras que estemos comprobando.
        También inicializa un kifu para guardar la partida y un el objetos igs
        que se encargará de conectarse con el servidor que subirá la partida.

        :Param size: tamaño del tablero
        :Type size: int """
        self.size = size
        # El valor 0 es para ir sumando(hay piedra) o restando(no hay)
        # El valor 8 es el nº de veces a buscar antes de hacer la estadística
        self.goban = [[None] * size for i in range(size)]
        self.moves = []
        self.statistical = [[10] * size for i in range(size)]
        self.stones = set()
        self.kifu = Kifu()

    def invalid_move(self, move):
        return self.invalid_ko_move(move)

    def get_group(self, pos, color, group=set()):
        """ Funcion recursiva que busca, a partir de una posición, el grupo
        correspondiente a esa posición.
        :Param pos: Posición perteneciente al grupo en la buscaremos si sus
        vecinos pertenecen o no al grupo.
        :Type pos: tuple.
        :Param group: grupo de posiciones que se encuentran dentro del grupo.
        :Type group: set. """

        # Out of range
        if pos[0] in (-1, GOBAN_SIZE) or pos[1] in (-1, GOBAN_SIZE):
            return group
        if self.goban[pos[0]][pos[1]] != color:
            return group
        group.add(pos)
        neighbour = ((0, -1), (0, 1), (1, 0), (-1, 0))
        for n in neighbour:
            pos_neig = (pos[0] + n[0], pos[1] + n[1])
            if not pos_neig in group:
                group = self.get_group(pos_neig, color, group)
        return group

    def get_liberties(self, pos, color):
        """ Función que comprueba las libertades que tiene el grupo al que
        pertenece la posición pasada por parámetro.
        :Param pos: Posición perteneciente al grupo en la buscaremos si sus
        vecinos pertenecen o no al grupo.
        :Type pos: tuple.
        :Param group: grupo de posiciones que se encuentran dentro del grupo.
        :Type group: set. """

        liberties = set()
        group = self.get_group(pos, color)
        neighbour = ((0, -1), (0, 1), (1, 0), (-1, 0))
        for pos in group:
            for n in neighbour:
                pos_neig = (pos[0] - n[0], pos[1] - n[1])
                if not self.goban[pos_neig[0]][pos_neig[1]]:
                    liberties.add(pos_neig)
        return liberties

    def is_last_liberty(self, pos, color):
        """ Comprobamos que la posición dada sea la última libertad del
        grupo.
        :Param pos: Posición perteneciente al grupo en la buscaremos si sus
        vecinos pertenecen o no al grupo.
        :Type pos: tuple.
        :Param group: grupo de posiciones que se encuentran dentro del grupo.
        :Type group: set. """

        neighbour = ((0, -1), (0, 1), (1, 0), (-1, 0))
        for n in neighbour:
            pos_neig = (pos[0] - n[0], pos[1] - n[1])
            if len(self.get_liberties(pos_neig, color)) == 1:
                return True
        return False

    def is_move_kill(self, pos, color):
        """ Comprobamos que un movimiento capture un grupo.
        :Param pos: Posición perteneciente al grupo en la buscaremos si sus
        vecinos pertenecen o no al grupo.
        :Type pos: tuple.
        :Param group: grupo de posiciones que se encuentran dentro del grupo.
        :Type group: set. """
        if color == BLACK:
            return self.is_last_liberty(pos, WHITE)
        elif color == WHITE:
            return self.is_last_liberty(pos, BLACK)

    def invalid_ko_move(self, move):
        """ Comprueba si el movimiento es un movimiento inválido de ko.
        :Param move: Movimiento a comprobar.
        :Type move: Move. """
        if not self.moves:
            return False
        prev_move = self.moves[-1]
        around_pos = ((-1, 0), (1, 0), (0, -1), (0, 1))
        if not (prev_move.x - move.x, prev_move.y - move.y) in around_pos:
            return False
        elif self.is_last_liberty(move.pt, move.color) and \
                self.get_liberties(prev_move.pt, prev_move.color) == [move]:
            return True
        else:
            return False

    def add_move(self, move):
        """ Agregamos movimiento al tablero y a la lista de movimientos.
        Comprobando anteriormente si ese movimiento es válido. """
        invalid = self.invalid_move(move)
        if not invalid:
            self.kifu.add_stone(move)
            self.goban[move.x][move.y] = move.color
            self.moves.append(move)
        return invalid

    def add_stones_to_statistical(self, stones):
        """Recorremos la lista de piedras pasadas por parámetros para
        hacer comprobaciones estadísticas en esas piedras, luego recorremos la
        lista de piedras guardada y la actualizamos. Actualiza kifu y el
        tablero donde guardamos el estado de las piedras cuando detecta
        estadísticamente que una piedra se ha puesto.

        :Param stones: lista de piedras
        :Type stones: list """
        for st in stones:
            if self.goban[st.x][st.y] or st not in self.stones:
                continue
            self.statistical[st.x][st.y] -= 1
            if self.statistical[st.x][st.y] <= 0:
                self.statistical[st.x][st.y] = 10
                self.add_move(st)
        self.stones = set(stones)

    def print_st(self):
        string = ""
        for x in range(self.size):
            for y in range(self.size):
                string += '%s' % str(self.statistical[y][x])
            string += "   " + str(x + 1) + "\n"
        return string

    def __str__(self):
        string = ""
        for x in range(self.size):
            for y in range(self.size):
                if self.goban[y][x] == BLACK:
                    string += " x "
                elif self.goban[y][x] == WHITE:
                    string += " o "
                elif not self.goban[y][x]:
                    string += " · "
            string += "   " + str(x + 1) + "\n"
        return string