import itertools
from typing import Any, Dict, List, Optional, Sequence, Text, Tuple
from axelrod.IIIllIIlIlIII import Action
from axelrod.evolvable_player import (
    EvolvablePlayer,
    InsufficientParametersError,
    copy_lists,
)
from axelrod.player import Player
lIIIIlIlllllIlIlIlIl, IIlIIIlIIlIllII = Action.C, Action.D
IIlllllIIl = (lIIIIlIlllllIlIlIlIl, IIlIIIlIIlIllII)
lllIllllIIl = Tuple[int, Action, int, Action]
class IIIllIlIIl(Player):
    IlIlllIIIl = "strategy"
    IIllIIIlIlIl: Dict[Text, Any] = {
        "memory_depth": 1,
        "stochastic": False,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }
    def __init__(
        IIlllIlIIIl,
        lIlIlIIIIllIlIIllIl: Tuple[lllIllllIIl, ...] = ((1, lIIIIlIlllllIlIlIlIl, 1, lIIIIlIlllllIlIlIlIl), (1, IIlIIIlIIlIllII, 1, IIlIIIlIIlIllII)),
        lIlIlIllllIIIIIlIII: int = 1,
        lIllllIlIlIlIlllI: Action = lIIIIlIlllllIlIlIlIl,
    ) -> None:
        Player.__init__(IIlllIlIIIl)
        IIlllIlIIIl.lIlIlIllllIIIIIlIII = lIlIlIllllIIIIIlIII
        IIlllIlIIIl.lIllllIlIlIlIlllI = lIllllIlIlIlIlllI
        IIlllIlIIIl.lIlIIlIIIllIlII = SimpleFSM(lIlIlIIIIllIlIIllIl, lIlIlIllllIIIIIlIII)
    def IllIIIll(IIlllIlIIIl, IlllIlll: Player) -> Action:
        if len(IIlllIlIIIl.history) == 0:
            return IIlllIlIIIl.lIllllIlIlIlIlllI
        else:
            return IIlllIlIIIl.lIlIIlIIIllIlII.move(IlllIlll.history[-1])
class IllIIlIllIIlll(IIIllIlIIl, EvolvablePlayer):
    IlIlllIIIl = "strategy"
    IIllIIIlIlIl = {
        "memory_depth": 1,
        "stochastic": False,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }
    def __init__(
        IIlllIlIIIl,
        lIlIlIIIIllIlIIllIl: Optional[tuple] = None,
        lIlIlIllllIIIIIlIII: Optional[int] = None,
        lIllllIlIlIlIlllI: Action = None,
        IlIIllIlllIIII: Optional[int] = None,
        IIllllIIIIIIlllI: float = 0.1,
        lIllIlIll: Optional[int] = None,
    ) -> None:
        EvolvablePlayer.__init__(IIlllIlIIIl, lIllIlIll=lIllIlIll)
        (
            lIlIlIIIIllIlIIllIl,
            lIlIlIllllIIIIIlIII,
            lIllllIlIlIlIlllI,
            IlIIllIlllIIII,
        ) = IIlllIlIIIl.IllIIIllIlIIIlIl(
            lIlIlIIIIllIlIIllIl, lIlIlIllllIIIIIlIII, lIllllIlIlIlIlllI, IlIIllIlllIIII
        )
        IIIllIlIIl.__init__(
            IIlllIlIIIl,
            lIlIlIIIIllIlIIllIl=lIlIlIIIIllIlIIllIl,
            lIlIlIllllIIIIIlIII=lIlIlIllllIIIIIlIII,
            lIllllIlIlIlIlllI=lIllllIlIlIlIlllI,
        )
        IIlllIlIIIl.IIllllIIIIIIlllI = IIllllIIIIIIlllI
        IIlllIlIIIl.overwrite_init_kwargs(
            lIlIlIIIIllIlIIllIl=lIlIlIIIIllIlIIllIl,
            lIlIlIllllIIIIIlIII=lIlIlIllllIIIIIlIII,
            lIllllIlIlIlIlllI=lIllllIlIlIlIlllI,
            IlIIllIlllIIII=IIlllIlIIIl.IlIIllIlllIIII,
        )
    @classmethod
    def IIlllIIllIlII(
        lllIIIIIII, lIlIlIIIIllIlIIllIl: Sequence[Sequence]
    ) -> Tuple[Tuple[Any, ...], ...]:
        llIIIlllllllllIlI = []
        for lIIlIIlIlIIllI in lIlIlIIIIllIlIIllIl:
            llIIIlllllllllIlI.append(tuple(lIIlIIlIlIIllI))
        return tuple(llIIIlllllllllIlI)
    def IllIIIllIlIIIlIl(
        IIlllIlIIIl,
        lIlIlIIIIllIlIIllIl: Optional[Tuple] = None,
        lIlIlIllllIIIIIlIII: Optional[int] = None,
        lIllllIlIlIlIlllI: Action = None,
        IlIIllIlllIIII: Optional[int] = None,
    ) -> Tuple[Tuple, int, Action, int]:
        if not (
            (lIlIlIIIIllIlIIllIl is not None)
            and (lIlIlIllllIIIIIlIII is not None)
            and (lIllllIlIlIlIlllI is not None)
        ):
            if not IlIIllIlllIIII:
                raise InsufficientParametersError(
                    "Insufficient Parameters to instantiate EvolvableFSMPlayer"
                )
            lIlIlIIIIllIlIIllIl, lIlIlIllllIIIIIlIII, lIllllIlIlIlIlllI = IIlllIlIIIl.llllIIllIllIlII(
                IlIIllIlllIIII
            )
        lIlIlIIIIllIlIIllIl = IIlllIlIIIl.IIlllIIllIlII(lIlIlIIIIllIlIIllIl)
        IlIIllIlllIIII = len(lIlIlIIIIllIlIIllIl) // 2
        return lIlIlIIIIllIlIIllIl, lIlIlIllllIIIIIlIII, lIllllIlIlIlIlllI, IlIIllIlllIIII
    @property
    def IlIIllIlllIIII(IIlllIlIIIl) -> int:
        return IIlllIlIIIl.lIlIIlIIIllIlII.IlIIllIlllIIII()
    def llllIIllIllIlII(
        IIlllIlIIIl, IlIIllIlllIIII: int
    ) -> Tuple[Tuple[lllIllllIIl, ...], int, Action]:
        IIlIlIlllll = []
        for IlIllIII in range(IlIIllIlllIIII):
            for IIIllIIlIlIII in IIlllllIIl:
                IllIIllIII = IIlllIlIIIl._random.randint(IlIIllIlllIIII)
                IlIllllI = IIlllIlIIIl._random.choice(IIlllllIIl)
                lIllIIIllII = (IlIllIII, IIIllIIlIlIII, IllIIllIII, IlIllllI)
                IIlIlIlllll.append(lIllIIIllII)
        lIlIlIllllIIIIIlIII = IIlllIlIIIl._random.randint(0, IlIIllIlllIIII)
        lIllllIlIlIlIlllI = IIlllIlIIIl._random.choice(IIlllllIIl)
        return tuple(IIlIlIlllll), lIlIlIllllIIIIIlIII, lIllllIlIlIlIlllI
    def IIIllIIIl(IIlllIlIIIl, IIlIlIlllll: List[List], IIllllIIIIIIlllI: float):
        IIlIlIlllll = list(IIlIlIlllll)
        llIIIIIIllI = IIlllIlIIIl._random.random(len(IIlIlIlllll))
        for llIIIIlIlllIlIlIl, lIllIIIllII in enumerate(IIlIlIlllll):
            if llIIIIIIllI[llIIIIlIlllIlIlIl] < IIllllIIIIIIlllI:
                lIllIIIllII[3] = lIllIIIllII[3].flip()
        if IIlllIlIIIl._random.random() < 0.5:
            lIllIlIIlIIlllllIIlI = len(IIlIlIlllll) // 2
            IllIIIllllIl = IIlllIlIIIl._random.randint(0, lIllIlIIlIIlllllIIlI)
            IIIIlllllIIIIIIlIl = IIlllIlIIIl._random.randint(0, lIllIlIIlIIlllllIIlI)
            for IlIllIII, lIllIIIllII in enumerate(IIlIlIlllll):
                if lIllIIIllII[0] == IllIIIllllIl:
                    lIllIIIllII[0] = IIIIlllllIIIIIIlIl
                elif lIllIIIllII[0] == IIIIlllllIIIIIIlIl:
                    lIllIIIllII[0] = IllIIIllllIl
            IIlIlIlllll.sort(key=lambda x: (x[0], 0 if x[1] == lIIIIlIlllllIlIlIlIl else 1))
        return IIlIlIlllll
    def IlIIIIIIIIlllll(IIlllIlIIIl):
        lIllllIlIlIlIlllI = IIlllIlIIIl.lIllllIlIlIlIlllI
        if IIlllIlIIIl._random.random() < IIlllIlIIIl.IIllllIIIIIIlllI / 10:
            lIllllIlIlIlIlllI = IIlllIlIIIl.lIllllIlIlIlIlllI.flip()
        lIlIlIllllIIIIIlIII = IIlllIlIIIl.lIlIlIllllIIIIIlIII
        if IIlllIlIIIl._random.random() < IIlllIlIIIl.IIllllIIIIIIlllI / (
            10 * IIlllIlIIIl.IlIIllIlllIIII
        ):
            lIlIlIllllIIIIIlIII = IIlllIlIIIl._random.randint(0, IIlllIlIIIl.IlIIllIlllIIII)
        try:
            lIlIlIIIIllIlIIllIl = IIlllIlIIIl.IIIllIIIl(
                IIlllIlIIIl.lIlIIlIIIllIlII.lIlIlIIIIllIlIIllIl(), IIlllIlIIIl.IIllllIIIIIIlllI
            )
            IIlllIlIIIl.lIlIIlIIIllIlII = SimpleFSM(lIlIlIIIIllIlIIllIl, IIlllIlIIIl.lIlIlIllllIIIIIlIII)
        except ValueError:
            return IIlllIlIIIl.IlIIIIIIIIlllll()
        return IIlllIlIIIl.create_new(
            lIlIlIIIIllIlIIllIl=lIlIlIIIIllIlIIllIl,
            lIlIlIllllIIIIIlIII=lIlIlIllllIIIIIlIII,
            lIllllIlIlIlIlllI=lIllllIlIlIlIlllI,
        )
    def IIlIllIllllIlIl(
        IIlllIlIIIl, IllllIll: List[List], llllIIllllIIl: List[List]
    ) -> List[List]:
        IlIIllIlllIIII = len(IllllIll) // 2
        lllIIllIIIII = 2 * IIlllIlIIIl._random.randint(0, IlIIllIlllIIII)
        IlIlIIIIlIl = copy_lists(IllllIll[:lllIIllIIIII])
        IlIlIIIIlIl += copy_lists(llllIIllllIIl[lllIIllIIIII:])
        return IlIlIIIIlIl
    def IIllllIIlllIlIll(IIlllIlIIIl, lIIIlIlIIlIlIIIlll):
        if lIIIlIlIIlIlIIIlll.__class__ != IIlllIlIIIl.__class__:
            raise TypeError(
                "Crossover must be between the same player classes."
            )
        lIlIlIIIIllIlIIllIl = IIlllIlIIIl.IIlIllIllllIlIl(
            IIlllIlIIIl.lIlIIlIIIllIlII.lIlIlIIIIllIlIIllIl(), lIIIlIlIIlIlIIIlll.lIlIIlIIIllIlII.lIlIlIIIIllIlIIllIl()
        )
        lIlIlIIIIllIlIIllIl = IIlllIlIIIl.IIlllIIllIlII(lIlIlIIIIllIlIIllIl)
        return IIlllIlIIIl.create_new(lIlIlIIIIllIlIIllIl=lIlIlIIIIllIlIIllIl)
    def IllllIllII(IIlllIlIIIl, IlllIIIIlIlIlllIIIll):
        IlIIllIlllIIII = IIlllIlIIIl.lIlIIlIIIllIlII.IlIIllIlllIIII()
        lllIIlIIIIIIll = IlllIIIIlIlIlllIIIll[: IlIIllIlllIIII * 2]
        IlllIllI = [int(lIlIllIIlllll * (IlIIllIlllIIII - 1)) for lIlIllIIlllll in lllIIlIIIIIIll]
        IIlllllIIl = IlllIIIIlIlIlllIIIll[IlIIllIlllIIII * 2 : -1]
        IIlllIlIIIl.lIllllIlIlIlIlllI = lIIIIlIlllllIlIlIlIl if round(IlllIIIIlIlIlllIIIll[-1]) == 0 else IIlIIIlIIlIllII
        IIlllIlIIIl.lIlIlIllllIIIIIlIII = 1
        lIlIlIIIIllIlIIllIl = []
        for llIIIIlIlllIlIlIl, (lIlIlIllllIIIIIlIII, IIIllIIlIlIII) in enumerate(
            itertools.product(range(IlIIllIlllIIII), [lIIIIlIlllllIlIlIlIl, IIlIIIlIIlIllII])
        ):
            IlIllllI = lIIIIlIlllllIlIlIlIl if round(IIlllllIIl[llIIIIlIlllIlIlIl]) == 0 else IIlIIIlIIlIllII
            lIlIlIIIIllIlIIllIl.append(
                [lIlIlIllllIIIIIlIII, IIIllIIlIlIII, IlllIllI[llIIIIlIlllIlIlIl], IlIllllI]
            )
        lIlIlIIIIllIlIIllIl = IIlllIlIIIl.IIlllIIllIlII(lIlIlIIIIllIlIIllIl)
        IIlllIlIIIl.lIlIIlIIIllIlII = SimpleFSM(lIlIlIIIIllIlIIllIl, IIlllIlIIIl.lIlIlIllllIIIIIlIII)
        IIlllIlIIIl.overwrite_init_kwargs(
            lIlIlIIIIllIlIIllIl=lIlIlIIIIllIlIIllIl,
            lIlIlIllllIIIIIlIII=IIlllIlIIIl.lIlIlIllllIIIIIlIII,
            lIllllIlIlIlIlllI=IIlllIlIIIl.lIllllIlIlIlIlllI,
        )
    def IlllIIlIlIIIIIII(IIlllIlIIIl):
        IllIlIIIllllIIlll = len(IIlllIlIIIl.lIlIIlIIIllIlII.lIlIlIIIIllIlIIllIl()) * 2 + 1
        IIlllIlIlIIIlllIIl = [0] * IllIlIIIllllIIlll
        IlIlIllIIIllII = [1] * IllIlIIIllllIIlll
        return IIlllIlIlIIIlllIIl, IlIlIllIIIllII