code: def epd(self, *, shredder: bool = False, en_passant: str = "legal", promoted: Optional[bool] = None, **operations: Union[None, str, int, float, Move, Iterable[Move]]) -> str:
          
          if en_passant == "fen":
              ep_square = self.ep_square
          elif en_passant == "xfen":
              ep_square = self.ep_square if self.has_pseudo_legal_en_passant() else None
          else:
              ep_square = self.ep_square if self.has_legal_en_passant() else None
  
          epd = [self.board_fen(promoted=promoted),
                 "w" if self.turn == WHITE else "b",
                 self.castling_shredder_fen() if shredder else self.castling_xfen(),
                 SQUARE_NAMES[ep_square] if ep_square is not None else "-"]
  
          if operations:
              epd.append(self._epd_operations(operations))
  
          return " ".join(epd)
docs: Gets an EPD representation of the current position.
  
          See :func:`~chess.Board.fen()` for FEN formatting options (*shredder*,
          *ep_square* and *promoted*).
  
          EPD operations can be given as keyword arguments. Supported operands
          are strings, integers, floats, moves, lists of moves and ``None``.
          All other operands are converted to strings.
  
          A list of moves for *pv* will be interpreted as a variation. All other
          move lists are interpreted as a set of moves in the current position.
  
          *hmvc* and *fmvc* are not included by default. You can use:
  
          >>> import chess
          >>>
          >>> board = chess.Board()
          >>> board.epd(hmvc=board.halfmove_clock, fmvc=board.fullmove_number)
          'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - hmvc 0; fmvc 1;'