
    hi.                        S r SSKJr  SSKJrJrJr  SSKJr  SSK	r
SSKJr  SSKrSSKJr  SSKJrJr   " S	 S
\\\
R(                        5      rg)zUImplementation of a space that represents the cartesian product of `Discrete` spaces.    )annotations)IterableMappingSequence)AnyN)NDArray)Discrete)MaskNDArraySpacec                    ^  \ rS rSrSr\R                  SS4       SU 4S jjjr\SS j5       r	\S 5       r
  S     SS jjr          SS jrSS	 jr    SS
 jr    SS jrS rSS jrS rSS jrSU 4S jjrSrU =r$ )MultiDiscrete   aE  This represents the cartesian product of arbitrary :class:`Discrete` spaces.

It is useful to represent game controllers or keyboards where each key can be represented as a discrete action space.

Note:
    Some environment wrappers assume a value of 0 always represents the NOOP action.

e.g. Nintendo Game Controller - Can be conceptualized as 3 discrete action spaces:

1. Arrow Keys: Discrete 5  - NOOP[0], UP[1], RIGHT[2], DOWN[3], LEFT[4]  - params: min: 0, max: 4
2. Button A:   Discrete 2  - NOOP[0], Pressed[1] - params: min: 0, max: 1
3. Button B:   Discrete 2  - NOOP[0], Pressed[1] - params: min: 0, max: 1

It can be initialized as ``MultiDiscrete([ 5, 2, 2 ])`` such that a sample might be ``array([3, 1, 0])``.

Although this feature is rarely used, :class:`MultiDiscrete` spaces may also have several axes
if ``nvec`` has several axes:

Example:
    >>> from gymnasium.spaces import MultiDiscrete
    >>> import numpy as np
    >>> observation_space = MultiDiscrete(np.array([[1, 2], [3, 4]]), seed=42)
    >>> observation_space.sample()
    array([[0, 0],
           [2, 2]])
Nc                  > Uc  [        S5      e[        R                  " U5      U l        [        R                  " U R                  [        R                  5      (       d  [        SU R                   S35      e[        R
                  " XSS9U l        Ub  [        R
                  " XBSS9U l        O.[        R                  " U R                  R                  US9U l        U R                  R                  U R                  R                  :X  d   S5       eU R                  S	:  R                  5       (       d   S
5       e[        TU ]1  U R                  R                  U R                  U5        g)a  Constructor of :class:`MultiDiscrete` space.

The argument ``nvec`` will determine the number of values each categorical variable can take. If
``start`` is provided, it will define the minimal values corresponding to each categorical variable.

Args:
    nvec: vector of counts of each categorical variable. This will usually be a list of integers. However,
        you may also pass a more complicated numpy array if you'd like the space to have several axes.
    dtype: This should be some kind of integer type.
    seed: Optionally, you can use this argument to seed the RNG that is used to sample from the space.
    start: Optionally, the starting value the element of each class will take (defaults to 0).
Nz@MultiDiscrete dtype must be explicitly provided, cannot be None.zInvalid MultiDiscrete dtype (z), must be an integer dtypeT)dtypecopyr   z2start and nvec (counts) should have the same shaper   z!nvec (counts) have to be positive)
ValueErrornpr   
issubdtypeintegerarraynvecstartzerosshapeallsuper__init__)selfr   r   seedr   	__class__s        Y/home/james-whalen/.local/lib/python3.13/site-packages/gymnasium/spaces/multi_discrete.pyr   MultiDiscrete.__init__,   s   ( =R  XXe_
 djj"**55/

|;VW  HHTT:	%4@DJ$))//?DJ JJ		/	@?	@/		A""$$I&II$$**d;    c                    U R                   $ )z7Has stricter type than :class:`gym.Space` - never None.)_shaper   s    r"   r   MultiDiscrete.shapeY   s     {{r$   c                    g)zDChecks whether this space can be flattened to a :class:`spaces.Box`.T r'   s    r"   is_np_flattenableMultiDiscrete.is_np_flattenable^   s     r$   c                   Ub  Ub  [        SU SU 35      eUbD  [        R                  " U R                  XR                  U R
                  S5      U R                  S9$ UbD  [        R                  " U R                  X R                  U R
                  S5      U R                  S9$ U R                  R                  U R                  R                  5      U R                  -  R                  U R                  5      U R
                  -   $ )a\  Generates a single random sample from this space.

Args:
    mask: An optional mask for multi-discrete, expects tuples with a ``np.ndarray`` mask in the position of each
        action with shape ``(n,)`` where ``n`` is the number of actions and ``dtype=np.int8``.
        Only ``mask values == 1`` are possible to sample unless all mask values for an action are ``0`` then the default action ``self.start`` (the smallest element) is sampled.
    probability: An optional probability mask for multi-discrete, expects tuples with a ``np.ndarray`` probability mask in the position of each
        action with shape ``(n,)`` where ``n`` is the number of actions and ``dtype=np.float64``.
        Only probability mask values within ``[0,1]`` are possible to sample as long as the sum of all values is ``1``.

Returns:
    An ``np.ndarray`` of :meth:`Space.shape`
zIOnly one of `mask` or `probability` can be provided, actual values: mask=z, probability=maskr   probability)r   r   r   _apply_maskr   r   r   	np_randomrandomr   astype)r   r.   r/   s      r"   sampleMultiDiscrete.samplec   s    $  7[\`[aaop{o|}  88  yy$**fEjj  $88  ii]Sjj 
 NN))$))//:TYYFNN



 r$   c                   [        U[        R                  5      (       a  [        U[        5      (       d   SU S[	        U5       35       e[        U5      [        U5      :X  d   S[        U5       S[        U5       35       e[        XU5       VVVs/ s H  u  pVnU R                  XVXt5      PM     snnn$ [        R                  " [	        U5      [        R                  5      (       d   SU S[	        U5       35       e[        U[        R                  5      (       d   S[	        U5       35       e[        U5      U:X  d   S[        U5       SU 35       eUS	:X  a  UR                  [        R                  :X  d   S
UR                   35       eUS:H  n[        R                  " [        R                  " US:H  U5      5      (       d
   SU 35       e[        R                  " U5      (       a5  U R                  R!                  [        R"                  " U5      S   5      U-   $ U$ US:X  Ga)  UR                  [        R$                  :X  d   SUR                   35       e[        R&                  " US:  US:*  5      n[        R                  " [        R                  " US:H  U5      5      (       d
   SU 35       e[        R(                  " [        R*                  " U5      S5      (       d   S[        R*                  " U5       35       eU[        R*                  " U5      -  n	U R                  R!                  [        R"                  " U5      S   X   S9U-   $ [-        SU 35      es  snnnf )z=Returns a sample using the provided mask or probability mask.z-Expects the mask to be a tuple for sub_nvec (z), actual type: zKExpects the mask length to be equal to the number of actions, mask length: z, nvec length: z0Expects the sub_nvec to be an action, actually: z, z4Expects the sub mask to be np.ndarray, actual type: z
, action: r.   z4Expects the mask dtype to be np.int8, actual dtype:    r   z3Expects all masks values to 0 or 1, actual values: r/   z7Expects the mask dtype to be np.float64, actual dtype: z?Expects all masks values to be between 0 and 1, actual values: z8Expects the sum of all mask values to be 1, actual sum: )pzUnsupported mask type: )
isinstancer   ndarraytupletypelenzipr0   r   r   r   int8r   
logical_oranyr1   choicewherefloat64logical_andisclosesumr   )
r   sub_masksub_nvec	sub_start	mask_typenew_masknew_nvec	new_startvalid_action_masknormalized_sub_masks
             r"   r0   MultiDiscrete._apply_mask   s    h

++%  j>xjHXY]^fYgXhij  x=C%  K\]`ai]j\kkz{~  @H  |I  {J  KK 
 69Y5W5W1H	   YJ5W 
 }}NBJJ
 
 	[=hZr$x.IYZ	[ 
 bjj
 
 	SA$x.AQR	S 
 MX%	}XY\]eYfXggqrzq{|	}% "'')WEhnnEUVW) !)A66h!m->?  PDXJOP  vv'((~~,,RXX6G-H-KLyXX  -'"**,ZHHXYZ, "x!|X] K66h!m->?  \PQYPZ[\  ::x !  ]I"&&QYJZI[\]  #+RVVH-="=%%HH./2)< &  	 29+>??cs   M c                   [        U[        5      (       a  [        R                  " U5      n[	        [        U[        R
                  5      =(       a    UR                  U R                  :H  =(       as    UR                  [        :g  =(       aY    [        R                  " U R                  U:*  5      =(       a/    [        R                  " XR                  -
  U R                  :  5      5      $ )z?Return boolean specifying if x is a valid member of this space.)r9   r   r   r   boolr:   r   r   objectr   r   r   )r   xs     r"   containsMultiDiscrete.contains   s    a""A q"**% 34::%36!3 tzzQ'3 q::~		12
 	
r$   c                L    U Vs/ s H  o"R                  5       PM     sn$ s  snf )zCConvert a batch of samples from this space to a JSONable data type.)tolistr   sample_nr4   s      r"   to_jsonableMultiDiscrete.to_jsonable   s      /77hFh777s   !c                t    U Vs/ s H&  n[         R                  " U[         R                  S9PM(     sn$ s  snf )zCConvert a JSONable data type to a batch of samples from this space.r   )r   r   int64rZ   s      r"   from_jsonableMultiDiscrete.from_jsonable   s-     @HHxVrxx0xHHHs   -5c                    [         R                  " U R                  S:g  5      (       a  SU R                   SU R                   S3$ SU R                   S3$ )z,Gives a string representation of this space.r   zMultiDiscrete(z, start=))r   rA   r   r   r'   s    r"   __repr__MultiDiscrete.__repr__   sI    66$**/""#DII;htzzl!DD		{!,,r$   c                   U R                   U   nU R                  U   nUR                  S:X  a
  [        X#S9nO[	        X R
                  US9nU R                  R                  R                  UR                  R                  l        U$ )z5Extract a subspace from this ``MultiDiscrete`` space.r   )r   )	r   r   ndimr	   r   r   r1   bit_generatorstate)r   indexr   r   subspaces        r"   __getitem__MultiDiscrete.__getitem__   sn    yy

5!99>2H$T::UCH 261M1M1S1S((.r$   c                    U R                   R                  S:  a  [        R                  R	                  S5        [        U R                   5      $ )z-Gives the ``len`` of samples from this space.   z>Getting the length of a multi-dimensional MultiDiscrete space.)r   rg   gymloggerwarnr=   r'   s    r"   __len__MultiDiscrete.__len__   s5    99>>QJJOOP 499~r$   c                   [        [        U[        5      =(       a    U R                  UR                  :H  =(       a    U R                  UR                  :H  =(       aa    [
        R                  " U R                  UR                  :H  5      =(       a-    [
        R                  " U R                  UR                  :H  5      5      $ )z7Check whether ``other`` is equivalent to this instance.)	rS   r9   r   r   r   r   r   r   r   )r   others     r"   __eq__MultiDiscrete.__eq__  s    um, 2

ekk)2

ekk)2 tyyEJJ./2 tzzU[[01
 	
r$   c                   > [        U5      nSU;  a  [        R                  " US   US   S9US'   [        TU ]  U5        g)zUsed when loading a pickled space.

This method has to be implemented explicitly to allow for loading of legacy states.

Args:
    state: The new state
r   r&   r   r   N)dictr   r   r   __setstate__)r   ri   r!   s     r"   r{   MultiDiscrete.__setstate__  s?     U%XXeHoU7^LE'NU#r$   )r   r   r   )r   z$NDArray[np.integer[Any]] | list[int]r   zstr | type[np.integer[Any]]r    z int | np.random.Generator | Noner   z+NDArray[np.integer[Any]] | list[int] | None)returnztuple[int, ...])NN)r.   tuple[MaskNDArray, ...] | Noner/   r~   r}   zNDArray[np.integer[Any]])
rH   z%MaskNDArray | tuple[MaskNDArray, ...]rI   MaskNDArray | np.integer[Any]rJ   r   rK   strr}   zint | list[Any])rU   r   r}   rS   )r[   z"Sequence[NDArray[np.integer[Any]]]r}   list[Sequence[int]])r[   r   r}   zlist[NDArray[np.integer[Any]]])rj   zint | tuple[int, ...])rv   r   r}   rS   )ri   z-Iterable[tuple[str, Any]] | Mapping[str, Any])__name__
__module____qualname____firstlineno____doc__r   r_   r   propertyr   r+   r4   r0   rV   r\   r`   rd   rl   rs   rw   r{   __static_attributes____classcell__)r!   s   @r"   r   r      s,   < .0XX15=A+<2+< ++< /	+<
 ;+< +<Z     046:#,# 4# 
"	#J@@7@@ 0@@ 1	@@
 @@ 
@@D
8:8	8I+I	'I-
$ $r$   r   )r   
__future__r   collections.abcr   r   r   typingr   numpyr   numpy.typingr   	gymnasiumrp   gymnasium.spaces.discreter	   gymnasium.spaces.spacer
   r   r   r   r*   r$   r"   <module>r      s?    [ " 7 7      . 5H$E'"**-. H$r$   