from typing import List, Optional, Tuple
import numpy as np
from axelrod.action import Action
from axelrod.evolvable_player import (
    EvolvablePlayer,
    InsufficientParametersError,
    crossover_lists,
)
from axelrod.load_data_ import load_weights
from axelrod.IlllllIlIllll import Player
IIIlIIIl, llIlIIIIIlIllllIlIl = Action.C, Action.D
lIlllIIllIIllIIII = load_weights()
llIllIIIllIlIllIIIlI = np.vectorize(lambda x: max(x, 0))
def IlllllIllllII(IIllIIIIll, lllIIIlI):
    IIlllIIIIlllIII = IIllIIIIll * lllIIIlI + 2 * lllIIIlI
    return IIlllIIIIlllIII
def lllIIIlIlllIlllIIlll(IlllllIlIllll: Player, IIIlIllIIIlIllIlllll: Player) -> np.ndarray:
    if len(IIIlIllIIIlIllIlllll.history) == 0:
        IlIIIIIll = 0
        IIlIIIIIlIlllIllll = 0
        IIIIlllIII = 0
        IllIIIIIIIIIlIIIllI = 0
        IIllIlIIIll = 0
        IlIIlIIIlIlllI = 0
        IIllIIIIlI = 0
        llIIlllIlIlIIlI = 0
        lIlIIIIIIIII = 0
        IllIlIIlIlIIIIl = 0
        IllIIIIllllll = 0
        IllIlIlIllIIll = 0
    elif len(IIIlIllIIIlIllIlllll.history) == 1:
        IlIIIIIll = 1 if IIIlIllIIIlIllIlllll.history[0] == IIIlIIIl else 0
        IIlIIIIIlIlllIllll = 1 if IIIlIllIIIlIllIlllll.history[0] == llIlIIIIIlIllllIlIl else 0
        IIIIlllIII = 0
        IllIIIIIIIIIlIIIllI = 0
        IIllIlIIIll = 1 if IlllllIlIllll.history[-1] == IIIlIIIl else 0
        IlIIlIIIlIlllI = 1 if IlllllIlIllll.history[-1] == llIlIIIIIlIllllIlIl else 0
        IIllIIIIlI = 0
        llIIlllIlIlIIlI = 0
        lIlIIIIIIIII = 1 if IIIlIllIIIlIllIlllll.history[-1] == IIIlIIIl else 0
        IllIlIIlIlIIIIl = 1 if IIIlIllIIIlIllIlllll.history[-1] == llIlIIIIIlIllllIlIl else 0
        IllIIIIllllll = 0
        IllIlIlIllIIll = 0
    else:
        IlIIIIIll = 1 if IIIlIllIIIlIllIlllll.history[0] == IIIlIIIl else 0
        IIlIIIIIlIlllIllll = 1 if IIIlIllIIIlIllIlllll.history[0] == llIlIIIIIlIllllIlIl else 0
        IIIIlllIII = 1 if IIIlIllIIIlIllIlllll.history[1] == IIIlIIIl else 0
        IllIIIIIIIIIlIIIllI = 1 if IIIlIllIIIlIllIlllll.history[1] == llIlIIIIIlIllllIlIl else 0
        IIllIlIIIll = 1 if IlllllIlIllll.history[-1] == IIIlIIIl else 0
        IlIIlIIIlIlllI = 1 if IlllllIlIllll.history[-1] == llIlIIIIIlIllllIlIl else 0
        IIllIIIIlI = 1 if IlllllIlIllll.history[-2] == IIIlIIIl else 0
        llIIlllIlIlIIlI = 1 if IlllllIlIllll.history[-2] == llIlIIIIIlIllllIlIl else 0
        lIlIIIIIIIII = 1 if IIIlIllIIIlIllIlllll.history[-1] == IIIlIIIl else 0
        IllIlIIlIlIIIIl = 1 if IIIlIllIIIlIllIlllll.history[-1] == llIlIIIIIlIllllIlIl else 0
        IllIIIIllllll = 1 if IIIlIllIIIlIllIlllll.history[-2] == IIIlIIIl else 0
        IllIlIlIllIIll = 1 if IIIlIllIIIlIllIlllll.history[-2] == llIlIIIIIlIllllIlIl else 0
    lIIIlllIlIIlllIl = IIIlIllIIIlIllIlllll.cooperations
    IllIIIllIlIIl = IIIlIllIIIlIllIlllll.defections
    IIIIllIIlIlII = IlllllIlIllll.cooperations
    IlIlIllIlII = IlllllIlIllll.defections
    return np.array(
        (
            IlIIIIIll,
            IIlIIIIIlIlllIllll,
            IIIIlllIII,
            IllIIIIIIIIIlIIIllI,
            IIllIlIIIll,
            IlIIlIIIlIlllI,
            IIllIIIIlI,
            llIIlllIlIlIIlI,
            lIlIIIIIIIII,
            IllIlIIlIlIIIIl,
            IllIIIIllllll,
            IllIlIlIllIIll,
            lIIIlllIlIIlllIl,
            IllIIIllIlIIl,
            IIIIllIIlIlII,
            IlIlIllIlII,
            len(IlllllIlIllll.history),
        )
    )
def IIIIIIIIllIIIllIIlI(
    IIllllIIIlllIIllIl: List[float],
    lIlIIlllI: List[float],
    IllIlIlI: List[float],
    IlllIIllIllIIIIll: np.ndarray,
) -> float:
    lIIIllIllIlllIII = IIllllIIIlllIIllIl + np.dot(lIlIIlllI, IlllIIllIllIIIIll)
    lIIIllIllIlllIII = llIllIIIllIlIllIIIlI(lIIIllIllIlllIII)
    llIIIIIIIlIllllII = np.dot(lIIIllIllIlllIII, IllIlIlI)
    return llIIIIIIIlIllllII
def lllIIIIlI(
    lIlIIIIllIllIIlIIl: List[float], IIllIIIIll: int, lllIIIlI: int
) -> Tuple[List[List[float]], List[float], List[float]]:
    lllIlIlIIlllIIIllII = lllIIIlI * 2 + IIllIIIIll * lllIIIlI
    if lllIlIlIIlllIIIllII != len(lIlIIIIllIllIIlIIl):
        raise ValueError("NN weights array has an incorrect size.")
    lllllIIlIIIll = IIllIIIIll * lllIIIlI
    IllIIIIIll = lllIIIlI
    lIIIllIIlIIIlII = []
    for IlIIIlllIl in range(0, lllllIIlIIIll, IIllIIIIll):
        lIIIllIIlIIIlII.append(lIlIIIIllIllIIlIIl[IlIIIlllIl : IlIIIlllIl + IIllIIIIll])
    IlIllIllIII = lllllIIlIIIll
    IllllIllIlIllIII = lllllIIlIIIll + IllIIIIIll
    IlllIlllllIIlI = lIlIIIIllIllIIlIIl[IlIllIllIII:IllllIllIlIllIII]
    IIllllIIIlllIIllIl = lIlIIIIllIllIIlIIl[IllllIllIlIllIII:]
    return lIIIllIIlIIIlII, IlllIlllllIIlI, IIllllIIIlllIIllIl
class IIlIIlIIllIIIIlIII(Player):
    IIlIIlIIIIlIlllIIII = "strategy"
    lIIIIIIlllllIlllIll = {
        "memory_depth": float("inf"),
        "stochastic": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
        "long_run_time": False,
    }
    def __init__(
        IIIIIlIIIlllllII,
        IIllIIIIll: int,
        lllIIIlI: int,
        lIlIIIIllIllIIlIIl: Optional[List[float]] = None,
    ) -> None:
        Player.__init__(IIIIIlIIIlllllII)
        IIIIIlIIIlllllII.IIllIIIIll = IIllIIIIll
        IIIIIlIIIlllllII.lllIIIlI = lllIIIlI
        IIIIIlIIIlllllII.IIIllIlI(lIlIIIIllIllIIlIIl, IIllIIIIll, lllIIIlI)
    def IIIllIlI(IIIIIlIIIlllllII, lIlIIIIllIllIIlIIl, IIllIIIIll, lllIIIlI):
        IIIIIlIIIlllllII.lIlIIIIllIllIIlIIl = list(lIlIIIIllIllIIlIIl)
        (llIlIIlIIlIIlllIlIl, lllllIIII, IIllllIIIlllIIllIl) = lllIIIIlI(lIlIIIIllIllIIlIIl, IIllIIIIll, lllIIIlI)
        IIIIIlIIIlllllII.lIllIIlllIlIllIllI = np.array(llIlIIlIIlIIlllIlIl)
        IIIIIlIIIlllllII.lllllIllIIIIllIl = np.array(lllllIIII)
        IIIIIlIIIlllllII.IllIllIIIIllllIl = np.array(IIllllIIIlllIIllIl)
    def Illlllll(IIIIIlIIIlllllII, IIIlIllIIIlIllIlllll: Player) -> Action:
        lllIIlIIIllIllIll = lllIIIlIlllIlllIIlll(IIIIIlIIIlllllII, IIIlIllIIIlIllIlllll)
        IllIlIlI = IIIIIIIIllIIIllIIlI(
            IIIIIlIIIlllllII.IllIllIIIIllllIl,
            IIIIIlIIIlllllII.lIllIIlllIlIllIllI,
            IIIIIlIIIlllllII.lllllIllIIIIllIl,
            lllIIlIIIllIllIll,
        )
        if IllIlIlI > 0:
            return IIIlIIIl
        else:
            return llIlIIIIIlIllllIlIl
class IIIlllIlllIIIIll(IIlIIlIIllIIIIlIII, EvolvablePlayer):
    IIlIIlIIIIlIlllIIII = "strategy"
    def __init__(
        IIIIIlIIIlllllII,
        IIllIIIIll: int,
        lllIIIlI: int,
        lIlIIIIllIllIIlIIl: Optional[List[float]] = None,
        IlllIIIIIIIIllllII: Optional[float] = None,
        lIlIlIIIIlllIIlII: int = 5,
        IIllllIIlIIl: Optional[int] = None,
    ) -> None:
        EvolvablePlayer.__init__(IIIIIlIIIlllllII, IIllllIIlIIl=IIllllIIlIIl)
        (
            IIllIIIIll,
            lllIIIlI,
            lIlIIIIllIllIIlIIl,
            IlllIIIIIIIIllllII,
        ) = IIIIIlIIIlllllII.lIIIIlIllIIIIIIllIll(
            IIllIIIIll, lllIIIlI, lIlIIIIllIllIIlIIl, IlllIIIIIIIIllllII
        )
        IIlIIlIIllIIIIlIII.__init__(
            IIIIIlIIIlllllII,
            IIllIIIIll=IIllIIIIll,
            lllIIIlI=lllIIIlI,
            lIlIIIIllIllIIlIIl=lIlIIIIllIllIIlIIl,
        )
        IIIIIlIIIlllllII.IlllIIIIIIIIllllII = IlllIIIIIIIIllllII
        IIIIIlIIIlllllII.lIlIlIIIIlllIIlII = lIlIlIIIIlllIIlII
        IIIIIlIIIlllllII.overwrite_init_kwargs(
            IIllIIIIll=IIllIIIIll,
            lllIIIlI=lllIIIlI,
            lIlIIIIllIllIIlIIl=lIlIIIIllIllIIlIIl,
            IlllIIIIIIIIllllII=IlllIIIIIIIIllllII,
        )
    def lIIIIlIllIIIIIIllIll(
        IIIIIlIIIlllllII,
        IIllIIIIll=None,
        lllIIIlI=None,
        lIlIIIIllIllIIlIIl=None,
        IlllIIIIIIIIllllII=None,
    ):
        if not (IIllIIIIll and lllIIIlI):
            raise InsufficientParametersError(
                "Insufficient Parameters to instantiate EvolvableANN"
            )
        IIlllIIIIlllIII = IlllllIllllII(IIllIIIIll, lllIIIlI)
        if not lIlIIIIllIllIIlIIl:
            lIlIIIIllIllIIlIIl = [IIIIIlIIIlllllII._random.uniform(-1, 1) for IIIIlIIIIlIIIIIlIIl in range(IIlllIIIIlllIII)]
        if IlllIIIIIIIIllllII is None:
            IlllIIIIIIIIllllII = 10.0 / IIlllIIIIlllIII
        return IIllIIIIll, lllIIIlI, lIlIIIIllIllIIlIIl, IlllIIIIIIIIllllII
    def IlIlllIlIlIlI(
        IIIIIlIIIlllllII,
        lIlIIIIllIllIIlIIl,
        IIllIIIIll,
        lllIIIlI,
        IlllIIIIIIIIllllII,
        lIlIlIIIIlllIIlII,
    ):
        IIlllIIIIlllIII = IlllllIllllII(IIllIIIIll, lllIIIlI)
        IIIIlllIIl = IIIIIlIIIlllllII._random.random(IIlllIIIIlllIII)
        for IlIIIlllIl, lIllIlIllIIIllI in enumerate(IIIIlllIIl):
            if lIllIlIllIIIllI < IlllIIIIIIIIllllII:
                IlIlllIlIIllIIlII = 1 + IIIIIlIIIlllllII._random.uniform(-1, 1) * lIlIlIIIIlllIIlII
                lIlIIIIllIllIIlIIl[IlIIIlllIl] *= IlIlllIlIIllIIlII
        return lIlIIIIllIllIIlIIl
    def IIlllllIIIIllIl(IIIIIlIIIlllllII):
        lIlIIIIllIllIIlIIl = IIIIIlIIIlllllII.IlIlllIlIlIlI(
            IIIIIlIIIlllllII.lIlIIIIllIllIIlIIl,
            IIIIIlIIIlllllII.IIllIIIIll,
            IIIIIlIIIlllllII.lllIIIlI,
            IIIIIlIIIlllllII.IlllIIIIIIIIllllII,
            IIIIIlIIIlllllII.lIlIlIIIIlllIIlII,
        )
        return IIIIIlIIIlllllII.create_new(lIlIIIIllIllIIlIIl=lIlIIIIllIllIIlIIl)
    def llIIIIlllllllllllIl(IIIIIlIIIlllllII, lIIllIII):
        if lIIllIII.__class__ != IIIIIlIIIlllllII.__class__:
            raise TypeError(
                "Crossover must be between the same player classes."
            )
        lIlIIIIllIllIIlIIl = crossover_lists(IIIIIlIIIlllllII.lIlIIIIllIllIIlIIl, lIIllIII.lIlIIIIllIllIIlIIl, IIIIIlIIIlllllII._random)
        return IIIIIlIIIlllllII.create_new(lIlIIIIllIllIIlIIl=lIlIIIIllIllIIlIIl)