diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 585df6c3b..2bc1646e0 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -163,6 +163,7 @@ from .oncebitten import FoolMeForever, FoolMeOnce, ForgetfulFoolMeOnce, OnceBitten from .prober import ( CollectiveStrategy, + Detective, HardProber, NaiveProber, Prober, @@ -285,6 +286,7 @@ DefectorHunter, Desperate, DelayedAON1, + Detective, DoubleCrosser, Doubler, DoubleResurrection, diff --git a/axelrod/strategies/prober.py b/axelrod/strategies/prober.py index 5a4b3ace9..96940a1fc 100644 --- a/axelrod/strategies/prober.py +++ b/axelrod/strategies/prober.py @@ -48,6 +48,45 @@ def strategy(self, opponent: Player) -> Action: return D +class Detective(Player): + """ + Starts with C, D, C, C, or with the given sequence of actions. + If the opponent defects at least once in the first fixed rounds, + play as TFT forever, else defect forever. + + Names: + + - Detective: [NC2019]_ + """ + + name = "Detective" + classifier = { + "memory_depth": float("inf"), + "stochastic": False, + "makes_use_of": set(), + "long_run_time": False, + "inspects_source": False, + "manipulates_source": False, + "manipulates_state": False, + } + + def __init__(self, initial_actions: List[Action] = None) -> None: + super().__init__() + if initial_actions is None: + self.initial_actions = [C, D, C, C] + else: + self.initial_actions = initial_actions + + def strategy(self, opponent: Player) -> Action: + hist_size = len(self.history) + init_size = len(self.initial_actions) + if hist_size < init_size: + return self.initial_actions[hist_size] + if D not in opponent.history[:init_size]: + return D + return opponent.history[-1] # TFT + + class Prober(Player): """ Plays D, C, C initially. Defects forever if opponent cooperated in moves 2 diff --git a/axelrod/tests/strategies/test_prober.py b/axelrod/tests/strategies/test_prober.py index c992c1958..85693309d 100644 --- a/axelrod/tests/strategies/test_prober.py +++ b/axelrod/tests/strategies/test_prober.py @@ -36,6 +36,51 @@ def test_strategy(self): self.versus_test(opponent=axelrod.Defector(), expected_actions=actions) +class TestDetective(TestPlayer): + + name = "Detective" + player = axelrod.Detective + expected_classifier = { + "memory_depth": float("inf"), + "stochastic": False, + "makes_use_of": set(), + "long_run_time": False, + "inspects_source": False, + "manipulates_source": False, + "manipulates_state": False, + } + + def test_strategy(self): + self.versus_test( + opponent=axelrod.TitForTat(), + expected_actions=[(C, C), (D, C), (C, D)] + [(C, C)] * 15, + ) + + self.versus_test( + opponent=axelrod.Cooperator(), + expected_actions=[(C, C), (D, C), (C, C), (C, C)] + [(D, C)] * 15, + ) + + self.versus_test( + opponent=axelrod.Defector(), + expected_actions=[(C, D), (D, D), (C, D), (C, D)] + [(D, D)] * 15, + ) + + def test_other_initial_actions(self): + self.versus_test( + opponent=axelrod.TitForTat(), + expected_actions=[(C, C), (C, C), (D, C)] + [(D, D)] * 15, + init_kwargs={"initial_actions": [C, C]}, + ) + + # Extreme case: no memory at all, it's simply a defector + self.versus_test( + opponent=axelrod.TitForTat(), + expected_actions=[(D, C)] + [(D, D)] * 15, + init_kwargs={"initial_actions": []}, + ) + + class TestProber(TestPlayer): name = "Prober" diff --git a/docs/reference/bibliography.rst b/docs/reference/bibliography.rst index 22927fade..5ffa3ad14 100644 --- a/docs/reference/bibliography.rst +++ b/docs/reference/bibliography.rst @@ -45,6 +45,7 @@ documentation. International Conference on Autonomous Agents and Multiagent Systems. .. [Mittal2009] Mittal, S., & Deb, K. (2009). Optimal strategies of the iterated prisoner’s dilemma problem for multiple conflicting objectives. IEEE Transactions on Evolutionary Computation, 13(3), 554–565. https://doi.org/10.1109/TEVC.2008.2009459 .. [Nachbar1992] Nachbar J., Evolution in the finitely repeated prisoner’s dilemma, Journal of Economic Behavior & Organization, 19(3): 307-326, 1992. +.. [NC2019] https://github.com/ncase/trust (Accessed: 30 October 2019) .. [Nowak1989] Nowak, Martin, and Karl Sigmund. "Game-dynamical aspects of the prisoner's dilemma." Applied Mathematics and Computation 30.3 (1989): 191-213. .. [Nowak1990] Nowak, M., & Sigmund, K. (1990). The evolution of stochastic strategies in the Prisoner's Dilemma. Acta Applicandae Mathematica. https://link.springer.com/article/10.1007/BF00049570 .. [Nowak1992] Nowak, M.., & May, R. M. (1992). Evolutionary games and spatial chaos. Nature. http://doi.org/10.1038/359826a0