"""
Strategies submitted to Axelrod's first tournament. All strategies in this
module are prefixed by `FirstBy` to indicate that they were submitted in
Axelrod's First tournament by the given author.

Note that these strategies are implemented from the descriptions presented
in:

Axelrod, R. (1980). Effective Choice in the Prisoner’s Dilemma.
Journal of Conflict Resolution, 24(1), 3–25.

These descriptions are not always clear and/or precise and when assumptions have
been made they are explained in the strategy docstrings.
"""

from typing import Dict, List, Optional, Tuple

from scipy.stats import chisquare

from axelrod.action import Action

from axelrod.player import Player

from axelrod.strategy_transformers import FinalTransformer

from .memoryone import MemoryOnePlayer

C, D = Action.C, Action.D

class FirstByTullock(Player):
    """
    Submitted to Axelrod's first tournament by Gordon Tullock.

    The description written in [Axelrod1980]_ is:

    > "This rule cooperates on the first eleven moves. It then cooperates 10%
    > less than the other player has cooperated on the preceding ten moves. This
    > rule is based on an idea developed in Overcast and Tullock (1971). Professor
    > Tullock was invited to specify how the idea could be implemented, and he did
    > so out of scientific interest rather than an expectation that it would be a
    > likely winner."

    This is interpreted as:

    Cooperates for the first 11 rounds then randomly cooperates 10% less often
    than the opponent has in the previous 10 rounds.

    This strategy came 13th in Axelrod's original tournament.

    Names:

    - Tullock: [Axelrod1980]_
    """

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

    def __init__(self) -> None:
        super().__init__()
        self._rounds_to_cooperate = 11

    def strategy(self, opponent: Player) -> Action:
        """Actual strategy definition that determines player's action."""
        if len(self.history) < self._rounds_to_cooperate:
            return C
        rounds = self._rounds_to_cooperate - 1
        cooperate_count = opponent.history[-rounds:].count(C)
        prop_cooperate = cooperate_count / rounds
        prob_cooperate = max(0, prop_cooperate - 0.10)
        return self._random.random_choice(prob_cooperate)