示例#1
0
    def get_check(self, board, turn):
        king = turn | Chess.KING
        king = list(np.argwhere(board == (Chess.KING | turn)))
        if not king:
            return None
        king = tuple(king[0])

        chesses = np.argwhere((board & Chess.invert(turn)) != 0)

        for chess in chesses:
            steps = self.generate(board, tuple(chess), Chess.invert(turn))
            valid = [var for var in steps if var == king]
            if valid:
                return tuple(chess)
        return None
示例#2
0
    def generate_cannon(self, board, where, turn):
        alter = [
            [(var, where[1]) for var in range(where[0] - 1, -1, -1)],
            [(var, where[1]) for var in range(where[0] + 1, Chess.W, 1)],
            [(where[0], var) for var in range(where[1] - 1, -1, -1)],
            [(where[0], var) for var in range(where[1] + 1, Chess.H, 1)],
        ]

        result = []

        for wheres in alter:
            barrier = 0
            for pos in wheres:
                if barrier == 0:  # 没有炮架子
                    if not board[pos]:  # 没有架子可以直接移动
                        result.append(pos)
                    else:
                        barrier = 1
                    continue
                # 有炮架子
                if not board[pos]:
                    continue
                if board[pos] & Chess.invert(turn) != 0:
                    result.append(pos)
                    break
                if board[pos]:
                    break
        return result
示例#3
0
    def generate_king(self, board, where, turn):
        offsets = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        where = np.array(where)
        alter = self.filter_valid([where + np.array(var) for var in offsets])
        result = []
        for pos in alter:
            if (board[tuple(pos)] & turn) != 0:  # 不能吃自己的棋子
                continue

            if pos[0] < 3 or pos[0] > 5:  # 不能出宫
                continue
            if turn == Chess.RED and pos[1] < 7:  # 不能出宫
                continue
            if turn == Chess.BLACK and pos[1] > 2:  # 不能出宫
                continue
            result.append(tuple(pos))

        # 单独判断老将见面
        king = list(np.argwhere(board == Chess.invert((Chess.KING | turn))))
        if not king:  # 没找到对方老将,可能局面不合法
            return result
        king = king[0]
        if where[0] != king[0]:  # 不在同一列,一定不见面
            return result

        start = min(where[1], king[1]) + 1
        stop = max(where[1], king[1])

        for var in range(start, stop):
            pos = (where[0], var)
            if board[pos]:  # 有遮挡,一定不见面
                return result
        # 无遮挡
        result.append(tuple(king))
        return result
示例#4
0
    def validateArrange(self, board, turn):
        whereK = np.argwhere(board == Chess.K)
        if len(whereK) == 0:
            raise Exception('布局中不能没有帅')
        wherek = np.argwhere(board == Chess.k)
        if len(wherek) == 0:
            raise Exception('布局中不能没有将')

        k = tuple(wherek[0])

        for idx in range(k[1] + 1, 10):
            pos = (k[0], idx)
            if not board[pos]:
                continue
            if board[pos] != Chess.K:
                break
            raise Exception('将帅不能见面')

        generator = Generator()
        check = generator.get_check(board, Chess.invert(turn))
        logger.debug("get check %s", check)
        if check:
            raise Exception('处于将死的状态')
        if generator.is_checkmate(board, turn):
            raise Exception('处于将死的状态')
示例#5
0
    def parse_fen(self, fen, load=False):
        if fen == 'startpos':
            self.__init__()
            return True

        pattern = r'((?:[RNBAKCP1-9]+/){9}[RNBAKCP1-9]+) ([wb]) - - (\d+) (\d+)(?: moves((?: [a-i]\d[a-i]\d)+))?'
        match = re.match(pattern, fen, re.IGNORECASE)
        if not match:
            logger.warning('invalid fen %s', fen)
            return None

        self.board = np.mat(np.zeros((Chess.W, Chess.H)), dtype=int)

        self.fen = f"{match.group(1)} {match.group(2)} - - {match.group(3)} {match.group(4)}"

        if match.group(2) == 'w':
            self.turn = Chess.RED
        else:
            self.turn = Chess.BLACK

        self.idle = int(match.group(3))
        self.bout = int(match.group(4))

        index = 0
        values = dict(zip(Chess.NAMES.values(), Chess.NAMES.keys()))

        for ch in match.group(1):
            if ch == '/':
                continue
            if ch > '0' and ch <= '9':
                index += int(ch)
                continue

            pos = divmod(index, Chess.WIDTH)[::-1]

            index += 1
            self.board[pos] = values[ch]

        if not match.group(5):
            return True

        self.moves = []

        moves = match.group(5).strip().split()
        for move in moves:
            fpos, tpos = self.parse_move(move)
            self.moves.append((fpos, tpos))
            if not load:
                self.board[tpos] = self.board[fpos]
                self.board[fpos] = 0
                self.turn = Chess.invert(self.turn)

        logger.debug('parse turn %d idle %d bout %d', self.turn, self.idle,
                     self.bout)

        return True
示例#6
0
    def move(self, fpos, tpos):
        if not self.validate_move(self.board, fpos, tpos):
            return False

        logger.info("get method %s", self.get_method(self.board, fpos, tpos))

        board = copy.deepcopy(self.board)
        board[tpos] = board[fpos]
        board[fpos] = Chess.NONE

        check = self.get_check(board, self.turn)
        if check:
            self.check = check
            return Chess.INVALID

        self.check = None

        if self.board[tpos]:
            self.idle = 0
        else:
            self.idle += 1

        if self.board[tpos]:
            result = Chess.CAPTURE
        else:
            result = Chess.MOVE

        self.turn = Chess.invert(self.turn)
        if self.turn == Chess.RED:
            self.bout += 1

        self.board[tpos] = self.board[fpos]
        self.board[fpos] = Chess.NONE
        self.moves.append((fpos, tpos))

        if self.is_checkmate(self.board, self.turn):
            logger.warning("Checkmate ......")
            return Chess.CHECKMATE

        check = self.get_check(self.board, self.turn)
        if check:
            self.check = check
            return Chess.CHECK

        return result