Skip to content

Commit 1ffb8f3

Browse files
authored
Merge pull request #743 from mturzanska/prober4
Implement prober4 strategy from PRISON project
2 parents ce822e0 + b3eb0ea commit 1ffb8f3

File tree

3 files changed

+137
-1
lines changed

3 files changed

+137
-1
lines changed

axelrod/strategies/_strategies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from .mindreader import MindReader, ProtectedMindReader, MirrorMindReader
4848
from .mutual import Desperate, Hopeless, Willing
4949
from .oncebitten import OnceBitten, FoolMeOnce, ForgetfulFoolMeOnce, FoolMeForever
50-
from .prober import (Prober, Prober2, Prober3, HardProber,
50+
from .prober import (Prober, Prober2, Prober3, Prober4, HardProber,
5151
NaiveProber, RemorsefulProber)
5252
from .punisher import Punisher, InversePunisher
5353
from .qlearner import RiskyQLearner, ArrogantQLearner, HesitantQLearner, CautiousQLearner
@@ -165,6 +165,7 @@
165165
Prober,
166166
Prober2,
167167
Prober3,
168+
Prober4,
168169
ProtectedMindReader,
169170
Punisher,
170171
Raider,

axelrod/strategies/prober.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,68 @@ def strategy(self, opponent):
102102
return D if opponent.history[-1:] == [D] else C
103103

104104

105+
class Prober4(Player):
106+
"""
107+
Plays C, C, D, C, D, D, D, C, C, D, C, D, C, C, D, C, D, D, C, D initially.
108+
Counts retaliating and provocative defections of the opponent.
109+
If the absolute difference between the counts is smaller or equal to 2,
110+
defects forever.
111+
Otherwise plays C for the next 5 turns and TFT for the rest of the game.
112+
113+
Names:
114+
115+
- prober4: [PRISON1998]_
116+
"""
117+
118+
name = 'Prober 4'
119+
classifier = {
120+
'stochastic': False,
121+
'memory_depth': float('inf'),
122+
'makes_use_of': set(),
123+
'long_run_time': False,
124+
'inspects_source': False,
125+
'manipulates_source': False,
126+
'manipulates_state': False
127+
}
128+
129+
@init_args
130+
def __init__(self):
131+
Player.__init__(self)
132+
self.init_sequence = [
133+
C, C, D, C, D, D, D, C, C, D, C, D, C, C, D, C, D, D, C, D
134+
]
135+
self.just_Ds = 0
136+
self.unjust_Ds = 0
137+
self.turned_defector = False
138+
139+
def strategy(self, opponent):
140+
if not self.history:
141+
return self.init_sequence[0]
142+
turn = len(self.history)
143+
if turn < len(self.init_sequence):
144+
if opponent.history[-1] == D:
145+
if self.history[-1] == D:
146+
self.just_Ds += 1
147+
if self.history[-1] == C:
148+
self.unjust_Ds += 1
149+
return self.init_sequence[turn]
150+
if turn == len(self.init_sequence):
151+
diff_in_Ds = abs(self.just_Ds - self.unjust_Ds)
152+
self.turned_defector = (diff_in_Ds <= 2)
153+
if self.turned_defector:
154+
return D
155+
if not self.turned_defector:
156+
if turn < len(self.init_sequence) + 5:
157+
return C
158+
return D if opponent.history[-1] == D else C
159+
160+
def reset(self):
161+
Player.reset(self)
162+
self.just_Ds = 0
163+
self.unjust_Ds = 0
164+
self.turned_defector = False
165+
166+
105167
class HardProber(Player):
106168
"""
107169
Plays D, D, C, C initially. Defects forever if opponent cooperated in moves

axelrod/tests/unit/test_prober.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,79 @@ def test_strategy(self):
9999
self.responses_test([D, C, C, D, C], [C, D, C, C], [C])
100100

101101

102+
class TestProber4(TestPlayer):
103+
104+
name = "Prober 4"
105+
player = axelrod.Prober4
106+
expected_classifier = {
107+
'stochastic': False,
108+
'memory_depth': float('inf'),
109+
'makes_use_of': set(),
110+
'long_run_time': False,
111+
'inspects_source': False,
112+
'manipulates_source': False,
113+
'manipulates_state': False
114+
}
115+
initial_sequence = [
116+
C, C, D, C, D, D, D, C, C, D, C, D, C, C, D, C, D, D, C, D
117+
]
118+
119+
def test_initial_strategy(self):
120+
"""Starts by playing CCDCDDDCCDCDCCDCDDCD."""
121+
self.responses_test([], [], self.initial_sequence)
122+
123+
def test_strategy(self):
124+
# After playing the initial sequence defects forever
125+
# if the absolute difference in the number of retaliating
126+
# and provocative defections of the opponent is smaller or equal to 2
127+
128+
provocative_histories = [
129+
[C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C],
130+
[C, D, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C],
131+
[C, D, C, D, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C],
132+
[C, C, D, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C],
133+
[C, C, D, C, D, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C],
134+
[D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D],
135+
]
136+
137+
history1 = self.initial_sequence
138+
responses = [D] * 10
139+
attrs = {'turned_defector': True}
140+
for history2 in provocative_histories:
141+
self.responses_test(history1, history2, responses, attrs=attrs)
142+
143+
# Otherwise cooperates for 5 rounds
144+
unprovocative_histories = [
145+
[C, C, D, C, D, D, D, C, C, D, C, D, C, C, D, C, D, D, C, D],
146+
[D, D, C, D, C, C, C, D, D, C, D, C, D, D, C, D, C, C, D, C],
147+
[C, C, D, C, D, D, C, C, C, C, C, C, C, C, C, C, C, C, C, C],
148+
[C, C, D, C, D, D, C, C, D, C, C, C, C, C, C, D, D, D, C, C],
149+
[C, C, C, C, D, D, C, C, D, C, C, D, D, C, D, C, D, C, C, C],
150+
]
151+
152+
responses = [C] * 5
153+
attrs = {'turned_defector': False}
154+
for history2 in unprovocative_histories:
155+
self.responses_test(history1, history2, responses, attrs=attrs)
156+
157+
# and plays like TFT afterwards
158+
history1 += responses
159+
history2 += responses
160+
self.responses_test(history1, history2, [C], attrs=attrs)
161+
162+
history1 += [C]
163+
history2 += [D]
164+
self.responses_test(history1, history2, [D], attrs=attrs)
165+
166+
history1 += [D]
167+
history2 += [C]
168+
self.responses_test(history1, history2, [C], attrs=attrs)
169+
170+
history1 += [C]
171+
history2 += [D]
172+
self.responses_test(history1, history2, [D], attrs=attrs)
173+
174+
102175
class TestHardProber(TestPlayer):
103176

104177
name = "Hard Prober"

0 commit comments

Comments
 (0)