Skip to content

Commit 9edd676

Browse files
authored
Merge pull request #1030 from FakeNameSE/master
Add a new DynamicTwoTitsForTat strategy
2 parents b43c81c + 1971111 commit 9edd676

File tree

4 files changed

+71
-3
lines changed

4 files changed

+71
-3
lines changed

axelrod/strategies/_strategies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
7777
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
7878
OmegaTFT, Gradual, ContriteTitForTat, SlowTitForTwoTats, AdaptiveTitForTat,
79-
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier)
79+
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier, DynamicTwoTitsForTat)
8080
from .verybad import VeryBad
8181
from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse,
8282
WorseAndWorse2, WorseAndWorse3)
@@ -263,4 +263,5 @@
263263
ZDGen2,
264264
ZDSet2,
265265
e,
266+
DynamicTwoTitsForTat,
266267
]

axelrod/strategies/titfortat.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from axelrod.actions import Actions, Action
22
from axelrod.player import Player
33
from axelrod.strategy_transformers import TrackHistoryTransformer, FinalTransformer
4+
from axelrod.random_ import random_choice
45

56
C, D = Actions.C, Actions.D
67

@@ -92,6 +93,41 @@ class TwoTitsForTat(Player):
9293
def strategy(opponent: Player) -> Action:
9394
return D if D in opponent.history[-2:] else C
9495

96+
class DynamicTwoTitsForTat(Player):
97+
"""
98+
A player starts by cooperating and then punishes its opponent's
99+
defections with defections, but with a dynamic bias towards cooperating
100+
based on the opponent's ratio of cooperations to total moves
101+
(so their current probability of cooperating regardless of the
102+
opponent's move (aka: forgiveness)).
103+
104+
Names:
105+
106+
- Dynamic Two Tits For Tat: Original name by Grant Garrett-Grossman.
107+
"""
108+
109+
name = 'Dynamic Two Tits For Tat'
110+
classifier = {
111+
'memory_depth': 2, # Long memory, memory-2
112+
'stochastic': True,
113+
'makes_use_of': set(),
114+
'long_run_time': False,
115+
'inspects_source': False,
116+
'manipulates_source': False,
117+
'manipulates_state': False
118+
}
119+
120+
@staticmethod
121+
def strategy(opponent):
122+
# First move
123+
if not opponent.history:
124+
# Make sure we cooporate first turn
125+
return C
126+
if D in opponent.history[-2:]:
127+
# Probability of cooperating regardless
128+
return random_choice(opponent.cooperations / len(opponent.history))
129+
else:
130+
return C
95131

96132
class Bully(Player):
97133
"""A player that behaves opposite to Tit For Tat, including first move.

axelrod/tests/strategies/test_titfortat.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,37 @@ def test_strategy(self):
114114
self.versus_test(opponent, expected_actions=actions)
115115

116116

117+
class TestDynamicTwoTitsForTat(TestPlayer):
118+
119+
name = 'Dynamic Two Tits For Tat'
120+
player = axelrod.DynamicTwoTitsForTat
121+
expected_classifier = {
122+
'memory_depth': 2,
123+
'stochastic': True,
124+
'makes_use_of': set(),
125+
'inspects_source': False,
126+
'manipulates_source': False,
127+
'manipulates_state': False
128+
}
129+
130+
def test_strategy(self):
131+
# First move is to cooperate
132+
self.first_play_test(C)
133+
# Test that it is stochastic
134+
opponent = axelrod.MockPlayer(actions=[D, C, D, D, C])
135+
actions = [(C, D), (D, C), (C, D), (D, D), (D, C)]
136+
self.versus_test(opponent, expected_actions=actions, seed=1)
137+
# Should respond differently with a different seed
138+
actions = [(C, D), (D, C), (D, D), (D, D), (C, C)]
139+
self.versus_test(opponent, expected_actions=actions, seed=2)
140+
141+
# Will cooperate if opponent cooperates.
142+
actions = [(C, C), (C, C), (C, C), (C, C), (C, C)]
143+
self.versus_test(axelrod.Cooperator(), expected_actions=actions)
144+
# Test against defector
145+
actions = [(C, D), (D, D), (D, D), (D, D), (D, D)]
146+
self.versus_test(axelrod.Defector(), expected_actions=actions)
147+
117148
class TestBully(TestPlayer):
118149

119150
name = "Bully"

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 2 additions & 2 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-
66
50+
67
5151

5252
Or, to find out how many strategies only use 1 turn worth of memory to
5353
make a decision::
@@ -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-
49
72+
50
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)