Skip to content

Commit c3433d8

Browse files
ztaylor2drvinceknight
authored andcommitted
Addition of Random TitForTat Strategy (#1136)
* Built rand_titfortat strategy in its own file, added rand_titfortat info to _strategies.py, rand.py, and all_strategies.rst. * Added rand_titfortat info to all_strategies.rst. Yet to build tests. * Passing 12 of 13 tests. Tests need more thought and work. * Added tests for cooperator and p=0, and defector and p=1. Fixed expected classifier stochastic in test file. * Added tests for cooperator and p=0, and defector and p=1. Fixed expected classifier stochastic in test file. * Built test for no p input (dafault 0.5) against defector. * Deleted bipoler from name. Deleted commented out pdb line. Refactored unnecessary else statement. Moved test and strategy into existing titfortat files. Removed automodule for deleted rand_titfortat file. * Deleted bipoler from name. Deleted commented out pdb line. Refactored unnecessary else statement. Moved test and strategy into existing titfortat files. Removed automodule for deleted rand_titfortat file. * Updated classification_of_strategies.rst, passing those doctests. * Extended tests for four more turns. * Deleting accidentally added return before __init__ * Modified strategy to begin with cooporation. * Passing meta test * Updated number of strategies in doctests. * Fixed inline comment.
1 parent febeb9d commit c3433d8

File tree

5 files changed

+111
-5
lines changed

5 files changed

+111
-5
lines changed

axelrod/strategies/_strategies.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@
7777
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
7878
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
7979
OmegaTFT, Gradual, ContriteTitForTat, AdaptiveTitForTat,
80-
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier, DynamicTwoTitsForTat, NTitsForMTats, Michaelos)
80+
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier,
81+
DynamicTwoTitsForTat, NTitsForMTats, Michaelos, RandomTitForTat)
8182
from .verybad import VeryBad
8283
from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse,
8384
WorseAndWorse2, WorseAndWorse3)
@@ -224,6 +225,7 @@
224225
Raider,
225226
Random,
226227
RandomHunter,
228+
RandomTitForTat,
227229
RemorsefulProber,
228230
Resurrection,
229231
Retaliate,

axelrod/strategies/titfortat.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,3 +790,50 @@ def strategy(self, opponent: Player) -> Action:
790790
return D
791791

792792
return opponent.history[-1]
793+
794+
795+
class RandomTitForTat(Player):
796+
"""
797+
A player starts by cooperating and then follows by copying its
798+
opponent (tit for tat style). From then on the player
799+
will switch between copying its opponent and randomly
800+
responding every other iteration.
801+
802+
Name:
803+
804+
- Random TitForTat: Original name by Zachary M. Taylor
805+
"""
806+
807+
# These are various properties for the strategy
808+
name = 'Random Tit for Tat'
809+
classifier = {
810+
'memory_depth': 1,
811+
'stochastic': True,
812+
'makes_use_of': set(),
813+
'long_run_time': False,
814+
'inspects_source': False,
815+
'manipulates_source': False,
816+
'manipulates_state': False
817+
}
818+
819+
820+
def __init__(self, p: float=0.5) -> None:
821+
"""
822+
Parameters
823+
----------
824+
p, float
825+
The probability to cooperate
826+
"""
827+
super().__init__()
828+
self.p = p
829+
if p in [0, 1]:
830+
self.classifier['stochastic'] = False
831+
832+
833+
def strategy(self, opponent: Player) -> Action:
834+
"""This is the actual strategy"""
835+
if not self.history:
836+
return C
837+
if len(opponent.history) % 2 == 0:
838+
return random_choice(self.p)
839+
return opponent.history[-1]

axelrod/tests/strategies/test_meta.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ class TestMetaMajorityMemoryOne(TestMetaPlayer):
294294
}
295295

296296
def test_strategy(self):
297-
actions = [(C, C), (C, D), (C, C), (C, D), (D, C)]
297+
actions = [(C, C), (C, D), (D, C), (C, D), (D, C)]
298298
self.versus_test(opponent=axelrod.Alternator(),
299299
expected_actions=actions)
300300

axelrod/tests/strategies/test_titfortat.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,3 +768,60 @@ def test_strategy(self):
768768
self.versus_test(axelrod.Alternator(), expected_actions=actions,
769769
attrs={"is_defector": True},
770770
match_attributes={"length": float("inf")}, seed=1)
771+
772+
773+
class TestRandomTitForTat(TestPlayer):
774+
"""Tests for random tit for tat strategy."""
775+
776+
name = "Random Tit for Tat: 0.5"
777+
player = axelrod.RandomTitForTat
778+
expected_classifier = {
779+
'memory_depth': 1,
780+
'stochastic': True,
781+
'makes_use_of': set(),
782+
'long_run_time': False,
783+
'inspects_source': False,
784+
'manipulates_source': False,
785+
'manipulates_state': False
786+
}
787+
788+
def test_strategy(self):
789+
"""
790+
Test that strategy reacts to opponent, and controlled by
791+
probability every other iteration. Also reacts randomly if no
792+
probability input.
793+
"""
794+
actions = [(C, C), (C, C), (C, C)]
795+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
796+
init_kwargs={"p": 1})
797+
798+
actions = [(C, D), (D, D), (D, D)]
799+
self.versus_test(axelrod.Defector(), expected_actions=actions,
800+
init_kwargs={"p": 0})
801+
802+
actions = [(C, C), (C, C), (D, C), (C, C)]
803+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
804+
init_kwargs={"p": 0})
805+
806+
actions = [(C, D), (D, D), (C, D), (D, D)]
807+
self.versus_test(axelrod.Defector(), expected_actions=actions,
808+
init_kwargs={"p": 1})
809+
810+
actions = [(C, C), (C, C), (D, C), (C, C), (D, C), (C, C)]
811+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
812+
seed=2)
813+
814+
actions = [(C, D), (D, D), (C, D), (D, D), (D, D), (D, D)]
815+
self.versus_test(axelrod.Defector(), expected_actions=actions,
816+
seed=1)
817+
818+
def test_deterministic_classification(self):
819+
"""
820+
Test classification when probability input is 0 or 1.
821+
Should change stochastic to false, because actions are no
822+
longer random.
823+
824+
"""
825+
for p in [0, 1]:
826+
player = axelrod.RandomTitForTat(p=p)
827+
self.assertFalse(player.classifier['stochastic'])

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ strategies::
4747
... }
4848
>>> strategies = axl.filtered_strategies(filterset)
4949
>>> len(strategies)
50-
75
50+
76
5151

5252
Or, to find out how many strategies only use 1 turn worth of memory to
5353
make a decision::
@@ -57,7 +57,7 @@ make a decision::
5757
... }
5858
>>> strategies = axl.filtered_strategies(filterset)
5959
>>> len(strategies)
60-
31
60+
32
6161

6262
Multiple filters can be specified within the filterset dictionary. To specify a
6363
range of memory_depth values, we can use the 'min_memory_depth' and
@@ -69,7 +69,7 @@ range of memory_depth values, we can use the 'min_memory_depth' and
6969
... }
7070
>>> strategies = axl.filtered_strategies(filterset)
7171
>>> len(strategies)
72-
55
72+
56
7373

7474
We can also identify strategies that make use of particular properties of the
7575
tournament. For example, here is the number of strategies that make use of the

0 commit comments

Comments
 (0)