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
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
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
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('处于将死的状态')
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
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