"""
Strategies from Axelrod's second tournament. All strategies in this module are
prefixed by `SecondBy` to indicate that they were submitted in Axelrod's Second
tournament by the given author.
"""

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

C, D = Action.C, Action.D

class SecondByCave(Player):
    """
    Strategy submitted to Axelrod's second tournament by Rob Cave (K49R), and
    came in fourth in that tournament.

    First look for overly-defective or apparently random opponents, and defect
    if found.  That is any opponent meeting one of:

    - turn > 39 and percent defects > 0.39
    - turn > 29 and percent defects > 0.65
    - turn > 19 and percent defects > 0.79

    Otherwise, respond to cooperation with cooperation.  And respond to defections
    with either a defection (if opponent has defected at least 18 times) or with
    a random (50/50) choice.  [Cooperate on first.]

    Names:

    - Cave: [Axelrod1980b]_
    """

    name = "Second by Cave"
    classifier = {
        "memory_depth": float("inf"),
        "stochastic": True,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    def strategy(self, opponent: Player) -> Action:
        """Actual strategy definition that determines player's action."""
        turn = len(self.history) + 1
        if turn == 1:
            return C

        number_defects = opponent.defections
        perc_defects = number_defects / turn

        # Defect if the opponent has defected often or appears random.
        if turn > 39 and perc_defects > 0.39:
            return D
        if turn > 29 and perc_defects > 0.65:
            return D
        if turn > 19 and perc_defects > 0.79:
            return D

        if opponent.history[-1] == D:
            if number_defects > 17:
                return D
            else:
                return self._random.random_choice(0.5)
        else:
            return C