Skip to content

Commit 419ca25

Browse files
Merge pull request #715 from geraintpalmer/3newstrategies
3 New Strategies From the PRISON (http://www.lifl.fr/IPD/ipd.frame.html)
2 parents 4de9c7a + 074b537 commit 419ca25

File tree

8 files changed

+291
-1
lines changed

8 files changed

+291
-1
lines changed

axelrod/strategies/_strategies.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
GoByMajority5,
2828
HardGoByMajority, HardGoByMajority10, HardGoByMajority20, HardGoByMajority40,
2929
HardGoByMajority5)
30+
from .gradualkiller import GradualKiller
3031
from .grudger import (Grudger, ForgetfulGrudger, OppositeGrudger, Aggravater,
31-
SoftGrudger)
32+
SoftGrudger, GrudgerAlternator, EasyGo)
3233
from .grumpy import Grumpy
3334
from .handshake import Handshake
3435
from .hunter import (
@@ -96,6 +97,7 @@
9697
DefectorHunter,
9798
Desperate,
9899
DoubleCrosser,
100+
EasyGo,
99101
Eatherley,
100102
EventualCycleHunter,
101103
Feld,
@@ -120,8 +122,10 @@
120122
GoByMajority5,
121123
Golden,
122124
Gradual,
125+
GradualKiller,
123126
Grofman,
124127
Grudger,
128+
GrudgerAlternator,
125129
Grumpy,
126130
Handshake,
127131
HardGoByMajority,

axelrod/strategies/gradualkiller.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from axelrod import Actions, Player, init_args
2+
from axelrod.strategy_transformers import InitialTransformer
3+
4+
C, D = Actions.C, Actions.D
5+
6+
@InitialTransformer((D, D, D, D, D, C, C), name_prefix=None)
7+
class GradualKiller(Player):
8+
"""
9+
It begins by defecting in the first five moves, then cooperates two times.
10+
It then defects all the time if the opponent has defected in move 6 and 7,
11+
else cooperates all the time.
12+
Initially designed to stop Gradual from defeating TitForTat in a 3 Player
13+
tournament.
14+
15+
Names
16+
17+
- Gradual Killer: [PRISON1998]_
18+
"""
19+
20+
# These are various properties for the strategy
21+
name = 'Gradual Killer'
22+
classifier = {
23+
'memory_depth': float('Inf'),
24+
'stochastic': False,
25+
'makes_use_of': set(),
26+
'long_run_time': False,
27+
'inspects_source': False,
28+
'manipulates_source': False,
29+
'manipulates_state': False
30+
}
31+
32+
def strategy(self, opponent):
33+
if opponent.history[5:7] == [D, D]:
34+
return D
35+
return C

axelrod/strategies/grudger.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,63 @@ def reset(self):
171171
Player.reset(self)
172172
self.grudged = False
173173
self.grudge_memory = 0
174+
175+
176+
177+
class GrudgerAlternator(Player):
178+
"""
179+
A player starts by cooperating until the first opponents defection,
180+
then alternates D-C.
181+
182+
Names:
183+
184+
- c_then_per_dc: [PRISON1998]_
185+
- Grudger Alternator: Original name by Geraint Palmer
186+
"""
187+
188+
name = 'GrudgerAlternator'
189+
classifier = {
190+
'memory_depth': float('inf'), # Long memory
191+
'stochastic': False,
192+
'makes_use_of': set(),
193+
'long_run_time': False,
194+
'inspects_source': False,
195+
'manipulates_source': False,
196+
'manipulates_state': False
197+
}
198+
199+
def strategy(self, opponent):
200+
"""Begins by playing C, then plays Alternator for the remaining rounds if the opponent ever plays D."""
201+
if opponent.defections:
202+
if self.history[-1] == Actions.C:
203+
return Actions.D
204+
return Actions.C
205+
206+
207+
208+
class EasyGo(Player):
209+
"""
210+
A player starts by defecting however will cooperate if at any point the opponent has defected.
211+
212+
Names:
213+
214+
- Easy Go [PRISON1998]_
215+
"""
216+
217+
name = 'EasyGo'
218+
classifier = {
219+
'memory_depth': float('inf'), # Long memory
220+
'stochastic': False,
221+
'makes_use_of': set(),
222+
'long_run_time': False,
223+
'inspects_source': False,
224+
'manipulates_source': False,
225+
'manipulates_state': False
226+
}
227+
228+
@staticmethod
229+
def strategy(opponent):
230+
"""Begins by playing D, then plays C for the remaining rounds if the opponent ever plays D."""
231+
if opponent.defections:
232+
return C
233+
return D
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Test for the gradual killer strategy."""
2+
3+
import axelrod
4+
from .test_player import TestHeadsUp, TestPlayer
5+
6+
from hypothesis import given
7+
from hypothesis.strategies import integers
8+
from axelrod.tests.property import strategy_lists
9+
10+
import random
11+
12+
C, D = axelrod.Actions.C, axelrod.Actions.D
13+
14+
15+
class TestGradualKiller(TestPlayer):
16+
17+
name = "Gradual Killer"
18+
player = axelrod.GradualKiller
19+
expected_classifier = {
20+
'memory_depth': float('Inf'),
21+
'stochastic': False,
22+
'makes_use_of': set(),
23+
'inspects_source': False,
24+
'manipulates_source': False,
25+
'manipulates_state': False
26+
}
27+
28+
def test_strategy(self):
29+
"""Starts by Defecting."""
30+
self.first_play_test(D)
31+
32+
def test_effect_of_strategy(self):
33+
"""Fist seven moves."""
34+
self.markov_test([D, D, D, D])
35+
self.responses_test([], [], [D, D, D, D, D, C, C])
36+
37+
def test_effect_of_strategy_with_history_CC(self):
38+
"""Continues with C if opponent played CC on 6 and 7."""
39+
P1 = axelrod.GradualKiller()
40+
P2 = axelrod.Player()
41+
P1.history = [D, D, D, D, D, C, C]
42+
P2.history = [C, C, C, C, C, C, C]
43+
self.assertEqual(P1.strategy(P2), 'C')
44+
P1.history = [D, D, D, D, D, C, C, C]
45+
P2.history = [C, C, C, C, C, C, C, C]
46+
self.assertEqual(P1.strategy(P2), 'C')
47+
P1.history = [D, D, D, D, D, C, C, C, C]
48+
P2.history = [C, C, C, C, C, C, C, C, C]
49+
self.assertEqual(P1.strategy(P2), 'C')
50+
P1.history = [D, D, D, D, D, C, C, C, C, C]
51+
P2.history = [C, C, C, C, C, C, C, C, C, C]
52+
self.assertEqual(P1.strategy(P2), 'C')
53+
54+
def test_effect_of_strategy_with_history_CD(self):
55+
"""Continues with C if opponent played CD on 6 and 7."""
56+
P1 = axelrod.GradualKiller()
57+
P2 = axelrod.Player()
58+
P1.history = [D, D, D, D, D, C, C]
59+
P2.history = [C, C, C, C, C, C, D]
60+
self.assertEqual(P1.strategy(P2), 'C')
61+
P1.history = [D, D, D, D, D, C, C, C]
62+
P2.history = [C, C, C, C, C, C, D, D]
63+
self.assertEqual(P1.strategy(P2), 'C')
64+
P1.history = [D, D, D, D, D, C, C, C, C]
65+
P2.history = [C, C, C, C, C, C, D, D, C]
66+
self.assertEqual(P1.strategy(P2), 'C')
67+
P1.history = [D, D, D, D, D, C, C, C, C, C]
68+
P2.history = [C, C, C, C, C, C, D, D, C, C]
69+
self.assertEqual(P1.strategy(P2), 'C')
70+
71+
def test_effect_of_strategy_with_history_DC(self):
72+
"""Continues with C if opponent played DC on 6 and 7."""
73+
P1 = axelrod.GradualKiller()
74+
P2 = axelrod.Player()
75+
P1.history = [D, D, D, D, D, C, C]
76+
P2.history = [C, C, C, C, C, D, C]
77+
self.assertEqual(P1.strategy(P2), 'C')
78+
P1.history = [D, D, D, D, D, C, C, C]
79+
P2.history = [C, C, C, C, C, D, C, C]
80+
self.assertEqual(P1.strategy(P2), 'C')
81+
P1.history = [D, D, D, D, D, C, C, C, C]
82+
P2.history = [C, C, C, C, C, D, C, C, D]
83+
self.assertEqual(P1.strategy(P2), 'C')
84+
P1.history = [D, D, D, D, D, C, C, C, C, C]
85+
P2.history = [C, C, C, C, C, D, C, C, D, C]
86+
self.assertEqual(P1.strategy(P2), 'C')
87+
88+
def test_effect_of_strategy_with_history_CC(self):
89+
"""Continues with D if opponent played DD on 6 and 7."""
90+
P1 = axelrod.GradualKiller()
91+
P2 = axelrod.Player()
92+
P1.history = [D, D, D, D, D, C, C]
93+
P2.history = [C, C, C, C, C, D, D]
94+
self.assertEqual(P1.strategy(P2), 'D')
95+
P1.history = [D, D, D, D, D, C, C, D]
96+
P2.history = [C, C, C, C, C, D, D, C]
97+
self.assertEqual(P1.strategy(P2), 'D')
98+
P1.history = [D, D, D, D, D, C, C, D, D]
99+
P2.history = [C, C, C, C, C, D, D, C, C]
100+
self.assertEqual(P1.strategy(P2), 'D')
101+
P1.history = [D, D, D, D, D, C, C, D, D, D]
102+
P2.history = [C, C, C, C, C, D, D, C, C, D]
103+
self.assertEqual(P1.strategy(P2), 'D')
104+

axelrod/tests/unit/test_grudger.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests for grudger strategies."""
22

33
import axelrod
4+
from random import randint
45

56
from .test_player import TestPlayer
67

@@ -173,3 +174,84 @@ def test_reset(self):
173174
p.reset()
174175
self.assertFalse(p.grudged)
175176
self.assertEqual(p.grudge_memory, 0)
177+
178+
179+
180+
class TestGrudgerAlternator(TestPlayer):
181+
182+
name = "GrudgerAlternator"
183+
player = axelrod.GrudgerAlternator
184+
expected_classifier = {
185+
'memory_depth': float('inf'), # Long memory
186+
'stochastic': False,
187+
'makes_use_of': set(),
188+
'long_run_time': False,
189+
'inspects_source': False,
190+
'manipulates_source': False,
191+
'manipulates_state': False
192+
}
193+
194+
def test_initial_strategy(self):
195+
"""
196+
Starts by cooperating
197+
"""
198+
self.first_play_test(C)
199+
200+
def test_strategy(self):
201+
"""
202+
If opponent defects at any point then the player will alternate D-C.
203+
"""
204+
self.responses_test([C, C, C, C, C], [C, C, C, C, C], [C])
205+
self.responses_test([C, C, C, C, C, C], [C, C, C, C, C, D], [D])
206+
self.responses_test([C, C, C, C, C, C, D], [C, C, C, C, C, D, D], [C])
207+
self.responses_test([C, C, C, C, C, C, D, C], [C, C, C, C, C, D, D, C], [D])
208+
self.responses_test([C, C, C, C, C, C, D, C, D], [C, C, C, C, C, D, D, C, C], [C])
209+
210+
def test_starategy_random_number_rounds(self):
211+
"""
212+
Runs test_strategy for a random number of rounds
213+
"""
214+
# Hasn't defected yet
215+
for _ in range(20):
216+
i = randint(1, 30)
217+
j = randint(1, 30)
218+
opp_hist = [C] * i
219+
my_hist = [C] * i
220+
self.responses_test(my_hist, opp_hist, [C]*j)
221+
222+
# Defected at least once
223+
for _ in range(20):
224+
i = randint(1, 30)
225+
j = randint(1, 30)
226+
opp_hist = [C for r in range(i)] + [D]
227+
my_hist = [C] * (i + 1)
228+
expected_response = [D if r % 2 == 0 else C for r in range(j)]
229+
self.responses_test(my_hist, opp_hist, expected_response)
230+
231+
232+
class TestEasyGo(TestPlayer):
233+
234+
name = "EasyGo"
235+
player = axelrod.EasyGo
236+
expected_classifier = {
237+
'memory_depth': float('inf'), # Long memory
238+
'stochastic': False,
239+
'makes_use_of': set(),
240+
'long_run_time': False,
241+
'inspects_source': False,
242+
'manipulates_source': False,
243+
'manipulates_state': False
244+
}
245+
246+
def test_initial_strategy(self):
247+
"""
248+
Starts by cooperating
249+
"""
250+
self.first_play_test(D)
251+
252+
def test_strategy(self):
253+
"""
254+
If opponent defects at any point then the player will cooperate forever
255+
"""
256+
self.responses_test([C, D, D, D], [C, C, C, C], [D])
257+
self.responses_test([C, C, D, D, D], [C, D, C, C, C], [C])

axelrod/tests/unit/test_resultset.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ def test_interactions_equality(self):
488488

489489
@given(tournament=tournaments(max_size=5,
490490
max_turns=5,
491+
max_noise=0,
491492
max_repetitions=3))
492493
@settings(max_examples=50, timeout=0)
493494
def test_equality_with_round_robin(self, tournament):

docs/reference/all_strategies.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,6 @@ Here are the docstrings of all the strategies in the library.
120120
.. automodule:: axelrod.strategies.titfortat
121121
:members:
122122
:undoc-members:
123+
.. automodule:: axelrod.strategies.gradualkiller
124+
:members:
125+
:undoc-members:

docs/reference/bibliography.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ documentation.
1818
.. [Stewart2012] Stewart, a. J., & Plotkin, J. B. (2012). Extortion and cooperation in the Prisoner’s Dilemma. Proceedings of the National Academy of Sciences, 109(26), 10134–10135. http://doi.org/10.1073/pnas.1208087109
1919
.. [Szabó1992] Szabó, G., & Fáth, G. (2007). Evolutionary games on graphs. Physics Reports, 446(4-6), 97–216. http://doi.org/10.1016/j.physrep.2007.04.004
2020
.. [Tzafestas2000] Tzafestas, E. (2000). Toward adaptive cooperative behavior. From Animals to Animals: Proceedings of the 6th International Conference on the Simulation of Adaptive Behavior {(SAB-2000)}, 2, 334–340.
21+
.. [PRISON1998] LIFL (1998) PRISON. Available at: http://www.lifl.fr/IPD/ipd.frame.html (Accessed: 19 September 2016).

0 commit comments

Comments
 (0)