def get_all(cls): '''Yield all moves combinations that do not have promotion.''' #FIXME add in promotion for source in Square.get_all(): for target in Square.get_all(): if source != target: move = cls(Square.from_x88(source.x88), Square.from_x88(target.x88)) yield(move)
def get_king(self, color): """Gets the square of the king. :param color: `"w"` for the white players king. `"b"` for the black players king. :return: The first square with a matching king or `None` if that player has no king. """ #if not color in ["w", "b"]: # raise KeyError("Invalid color: %s." % repr(color)) for square, piece in [(s, self._pieces[s._x88]) for s in Square.get_all() if self._pieces[s._x88]]: if Piece.is_klass_and_color(piece, KING, color): return square
def is_insufficient_material(self): """Checks if there is sufficient material to mate. Mating is impossible in: * A king versus king endgame. * A king with bishop versus king endgame. * A king with knight versus king endgame. * A king with bishop versus king with bishop endgame, where both bishops are on the same color. Same goes for additional bishops on the same color. Assumes that the position is valid and each player has exactly one king. :return: Whether there is insufficient material to mate. """ piece_counts = self.get_piece_counts() # King versus king. if sum(piece_counts.values()) == 2: return True # King and knight or bishop versus king. elif sum(piece_counts.values()) == 3: if piece_counts["b"] == 1 or piece_counts["n"] == 1: return True # Each player with only king and any number of bishops, # where all bishops are on the same color. elif sum(piece_counts.values()) == 2 + piece_counts[BISHOP]: white_has_bishop = self.get_piece_counts([WHITE])[BISHOP] != 0 black_has_bishop = self.get_piece_counts([BLACK])[BISHOP] != 0 if white_has_bishop and black_has_bishop: color = None for square in Square.get_all(): p = self._pieces[square._x88] if p and Piece.klass(p) == BISHOP: if color and color != square.is_light(): return False color = square.is_light() return True return False
def hash_position(self, position): """Computes the Zobrist hash of a position. :param position: The position to hash. :return: The hash as an integer. """ key = 0 # Hash in the board setup. for square in Square.get_all(): piece = position[square] if piece: i = "pPnNbBrRqQkK".index(piece.symbol) key ^= self.__random_array[64 * i + 8 * square.y + square.x] # Hash in the castling flags. if position.get_castling_right("K"): key ^= self.__random_array[768] if position.get_castling_right("Q"): key ^= self.__random_array[768 + 1] if position.get_castling_right("k"): key ^= self.__random_array[768 + 2] if position.get_castling_right("q"): key ^= self.__random_array[768 + 3] # Hash in the en-passant file. if (position.ep_file and position.get_theoretical_ep_right(position.ep_file)): i = ord(position.ep_file) - ord("a") key ^= self.__random_array[772 + i] # Hash in the turn. if position.turn == "w": key ^= self.__random_array[780] return key
def gen_moves(): for source in Square.get_all(): for target in Square.get_all(): if target != source: yield (Move(source, target))
def test_get_all(self): for idx, square in enumerate(Square.get_all()): pass total = len(Square.ranks) * len(Square.files) self.assertEqual(total - 1, idx)
def test___hash__(self): d = {} for square in Square.get_all(): d[hash(square)] = None total = len(Square.ranks) * len(Square.files) self.assertEqual(total, len(d))
def gen_moves(): for source in Square.get_all(): for target in Square.get_all(): if target != source: yield(Move(source, target))