from typing import List
import numpy as np
from axelrod.action import Action
from axelrod.interaction_utils import compute_final_score
from axelrod.player import Player
from axelrod.strategies.finite_state_machines import FSMPlayer
IIIIllIllIlIIlIIlI, IIlIlIIlIllllIII = Action.C, Action.D
class lIlIllIIlIllllll(Player):
    IlIlIllIl = "strategy"
    IlIlIllIlllllIIll = {
        "memory_depth": float("inf"),
        "stochastic": True,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }
    def __init__(IIllllllIllIIIlIIll):
        super().__init__()
        IIllllllIllIIIlIIll.lIIIlIlIIlIII = "Normal"
        IIllllllIllIIIlIIll.IIIIllllIllIlllllIlI = 0  
        IIllllllIllIIIlIIll.lIIIIIlIlI = 0  
        IIllllllIllIIIlIIll.llIIIIll = (
            None  
        )
        IIllllllIllIIIlIIll.IIllIIllIIIIIlllIlI = False  
        IIllllllIllIIIlIIll.llIlllllllIIIl = 0.25  
        IIllllllIllIIIlIIll.IlIIllIIIIIIllIIIIII = np.zeros([4, 2])
        IIllllllIllIIIlIIll.lIIIlllllIIIIllllll = 0  
        IIllllllIllIIIlIIll.lllIlIIIIlIlIIIIll = (
            3  
        )
        IIllllllIllIIIlIIll.llIIllIIllllIIIlllI = False
        IIllllllIllIIIlIIll.IlIlIIllIIIIIll = 0
        IIllllllIllIIIlIIll.IlIlIllIIlIl = [
            0,
            0,
        ]  
        IIllllllIllIIIlIIll.lIIlIIIIIIlllIl = 0  
        IIllllllIllIIIlIIll.IIIIlIIlIIIIIlllllII = (
            5  
        )
        IIllllllIllIIIlIIll.lIIIlIIll = 0  
    def lIIlIllllIIIlll(IIllllllIllIIIlIIll, IIIIIllIIIllIIIlIl, IllIlllllllIlIlIlI=True, IIIlIlIlIl=False):
        if IllIlllllllIlIlIlI and IIIIIllIIIllIIIlIl == IIIIllIllIlIIlIIlI:
            IIllllllIllIIIlIIll.lIIIlllllIIIIllllll -= 1
            IIllllllIllIIIlIIll.lllIlIIIIlIlIIIIll += 1
        if IIIlIlIlIl and IIIIIllIIIllIIIlIl == IIlIlIIlIllllIII:
            IIllllllIllIIIlIIll.IlIlIllIIlIl[IIllllllIllIIIlIIll.lIIlIIIIIIlllIl] += 1
        return IIIIIllIIIllIIIlIl
    def lIIlIIlIlIIIlIIIl(IIllllllIllIIIlIIll, IIllIIllIIIIl):
        lIIlIIIlIlIlll = IIllIIllIIIIl - 2
        lllIlIIIllll = (
            np.outer(
                IIllllllIllIIIlIIll.IlIIllIIIIIIllIIIIII.sum(axis=1), IIllllllIllIIIlIIll.IlIIllIIIIIIllIIIIII.sum(axis=0)
            )
            / lIIlIIIlIlIlll
        )
        lIlllIIIlIIIllIIIII = 0.0
        for lIIllIIlIl in range(4):
            for llIIIIIlIlI in range(2):
                lllIlIIIIIIlIlIlIII = lllIlIIIllll[lIIllIIlIl, llIIIIIlIlI]
                if lllIlIIIIIIlIlIlIII > 1.0:
                    lIlllIIIlIIIllIIIII += (
                        lllIlIIIIIIlIlIlIII - IIllllllIllIIIlIIll.IlIIllIIIIIIllIIIIII[lIIllIIlIl, llIIIIIlIlI]
                    ) ** 2 / lllIlIIIIIIlIlIlIII
        return lIlllIIIlIIIllIIIII
    def lIIIIIlIl(IIllllllIllIIIlIIll, IIllIIllIIIIl):
        lIIlIIIlIlIlll = IIllIIllIIIIl - 2
        if IIllllllIllIIIlIIll.IlIIllIIIIIIllIIIIII[0, 0] / lIIlIIIlIlIlll >= 0.8:
            return False
        if (
            IIllllllIllIIIlIIll.IIIIllllIllIlllllIlI / lIIlIIIlIlIlll < 0.25
            or IIllllllIllIIIlIIll.IIIIllllIllIlllllIlI / lIIlIIIlIlIlll > 0.75
        ):
            return False
        if IIllllllIllIIIlIIll.lIIlIIlIlIIIlIIIl(IIllIIllIIIIl) > 3:
            return False
        return True
    def lllIllIllIllIIlIll(IIllllllIllIIIlIIll, lIlIllIIIIllllIlll):
        if lIlIllIIIIllllIlll == IIlIlIIlIllllIII:
            IIllllllIllIIIlIIll.IlIlIIllIIIIIll += 1
        else:
            IIllllllIllIIIlIIll.IlIlIIllIIIIIll = 0
        if IIllllllIllIIIlIIll.IlIlIIllIIIIIll >= 20:
            return True
        return False
    def lIlllIIIl(IIllllllIllIIIlIIll, lIlIllIIIIllllIlll):
        IIllllllIllIIIlIIll.lIIlIIIIIIlllIl = 1 - IIllllllIllIIIlIIll.lIIlIIIIIIlllIl  
        if lIlIllIIIIllllIlll == IIlIlIIlIllllIII:
            IIllllllIllIIIlIIll.IlIlIllIIlIl[IIllllllIllIIIlIIll.lIIlIIIIIIlllIl] += 1
        else:
            IIllllllIllIIIlIIll.IlIlIllIIlIl[IIllllllIllIIIlIIll.lIIlIIIIIIlllIl] = 0
        if IIllllllIllIIIlIIll.IlIlIllIIlIl[IIllllllIllIIIlIIll.lIIlIIIIIIlllIl] >= IIllllllIllIIIlIIll.IIIIlIIlIIIIIlllllII:
            return True
    def IIlIIlIIIIIllllIlIlI(IIllllllIllIIIlIIll, IIllIIllIIllII: Player) -> Action:
        IIllIIllIIIIl = len(IIllllllIllIIIlIIll.history) + 1
        if IIllIIllIIIIl == 1:
            return IIIIllIllIlIIlIIlI
        if IIllllllIllIIIlIIll.lIIIlIlIIlIII == "Defect":
            if IIllIIllIIllII.history[-1] == IIlIlIIlIllllIII:
                IIllllllIllIIIlIIll.lIIIIIlIlI += 1
            else:
                IIllllllIllIIIlIIll.lIIIIIlIlI -= 3
            if IIllllllIllIIIlIIll.lIIIIIlIlI >= 11:
                IIllllllIllIIIlIIll.lIIIlIlIIlIII = "Normal"
                IIllllllIllIIIlIIll.IIllIIllIIIIIlllIlI = True
                IIllllllIllIIIlIIll.lIIIlllllIIIIllllll = 2
                return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIIIIllIIIllIIIlIl=IIIIllIllIlIIlIIlI, IllIlllllllIlIlIlI=False)
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIlIlIIlIllllIII)
        if not IIllllllIllIIIlIIll.IIllIIllIIIIIlllIlI:
            if IIllIIllIIIIl > 2:
                if IIllIIllIIllII.history[-1] == IIlIlIIlIllllIII:
                    IIllllllIllIIIlIIll.IIIIllllIllIlllllIlI += 1
                IIIlIlllIIlIllIllI = 1 if IIllIIllIIllII.history[-1] == IIlIlIIlIllllIII else 0
                lIlllIIIIIlII = 1 if IIllIIllIIllII.history[-2] == IIlIlIIlIllllIII else 0
                if IIllllllIllIIIlIIll.history[-2] == IIlIlIIlIllllIII:
                    lIlllIIIIIlII += 2
                IIllllllIllIIIlIIll.IlIIllIIIIIIllIIIIII[lIlllIIIIIlII, IIIlIlllIIlIllIllI] += 1
            if IIllIIllIIIIl % 15 == 0 and IIllIIllIIIIl > 15:
                if IIllllllIllIIIlIIll.lIIIIIlIl(IIllIIllIIIIl):
                    IIllllllIllIIIlIIll.lIIIlIlIIlIII = "Defect"
                    return IIllllllIllIIIlIIll.lIIlIllllIIIlll(
                        IIlIlIIlIllllIII, IllIlllllllIlIlIlI=False
                    )  
        if IIllllllIllIIIlIIll.lllIlIIIIlIlIIIIll == 2 and IIllIIllIIllII.history[-1] == IIlIlIIlIllllIII:
            IIllllllIllIIIlIIll.llIIllIIllllIIIlllI = True
        if (
            IIllIIllIIIIl == 38
            and IIllIIllIIllII.history[-1] == IIlIlIIlIllllIII
            and IIllIIllIIllII.cooperations == 36
        ):
            IIllllllIllIIIlIIll.lIIIlIlIIlIII = "Fair-weather"
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIIIIllIIIllIIIlIl=IIIIllIllIlIIlIIlI, IllIlllllllIlIlIlI=False)
        if IIllllllIllIIIlIIll.lIIIlIlIIlIII == "Fair-weather":
            if IIllIIllIIllII.history[-1] == IIlIlIIlIllllIII:
                IIllllllIllIIIlIIll.lIIIlIlIIlIII = "Normal"  
            else:
                return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIIIllIllIlIIlIIlI)
        if IIllllllIllIIIlIIll.lllIllIllIllIIlIll(IIllIIllIIllII.history[-1]):
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIlIlIIlIllllIII, IIIlIlIlIl=True)
        if IIllllllIllIIIlIIll.lIlllIIIl(IIllIIllIIllII.history[-1]):
            IIllllllIllIIIlIIll.IlIlIllIIlIl[IIllllllIllIIIlIIll.lIIlIIIIIIlllIl] = (
                0  
            )
            IIllllllIllIIIlIIll.lIIIlIIll += (
                1  
            )
            if IIllllllIllIIIlIIll.lIIIlIIll >= 8:  
                IIllllllIllIIIlIIll.IIIIlIIlIIIIIlllllII = 3
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(
                IIIIllIllIlIIlIIlI, IIIlIlIlIl=True
            )  
        if IIllllllIllIIIlIIll.lIIIlllllIIIIllllll >= 1:
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIIIllIllIlIIlIIlI, IllIlllllllIlIlIlI=True, IIIlIlIlIl=True)
        if IIllIIllIIIIl < 37:
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIllIIllIIllII.history[-1], IIIlIlIlIl=True)
        if IIllIIllIIIIl == 37:
            IIllllllIllIIIlIIll.lIIIlllllIIIIllllll, IIllllllIllIIIlIIll.lllIlIIIIlIlIIIIll = 2, 1
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIlIlIIlIllllIII, IllIlllllllIlIlIlI=False)
        if IIllllllIllIIIlIIll.llIIllIIllllIIIlllI or IIllllllIllIIIlIIll._random.random() > IIllllllIllIIIlIIll.llIlllllllIIIl:
            return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIllIIllIIllII.history[-1], IIIlIlIlIl=True)
        IIllllllIllIIIlIIll.llIlllllllIIIl += 0.05
        IIllllllIllIIIlIIll.lIIIlllllIIIIllllll, IIllllllIllIIIlIIll.lllIlIIIIlIlIIIIll = 2, 1
        return IIllllllIllIIIlIIll.lIIlIllllIIIlll(IIlIlIIlIllllIII, IllIlllllllIlIlIlI=False)