Skip to content

Commit c67e460

Browse files
committed
Add reproduce method to Player and add self.init_args to appropriate strategies
1 parent acdce5a commit c67e460

13 files changed

+62
-31
lines changed

axelrod/player.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ def is_cheater(s):
2828
classifier['manipulates_source'] or\
2929
classifier['manipulates_state']
3030

31-
3231
def update_histories(player1, player2, move1, move2):
3332
"""Updates histories and cooperation / defections counts following play."""
3433
# Update histories
@@ -73,6 +72,7 @@ def __init__(self):
7372
self.tournament_attributes = {'length': -1, 'game': None}
7473
self.cooperations = 0
7574
self.defections = 0
75+
self.init_args = ()
7676

7777
def __repr__(self):
7878
"""The string method for the strategy."""
@@ -98,6 +98,16 @@ def play(self, opponent, noise=0):
9898
s1, s2 = self._add_noise(noise, s1, s2)
9999
update_histories(self, opponent, s1, s2)
100100

101+
def reproduce(self):
102+
"""Clones the player without history, reapplying configuration
103+
parameters as necessary."""
104+
105+
cls = self.__class__
106+
#print(cls)
107+
#print(self.init_args)
108+
new_player = cls(*self.init_args)
109+
return new_player
110+
101111
def reset(self):
102112
"""Resets history.
103113

axelrod/round_robin.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,21 @@ def _pair_of_players(self, player1_index, player2_index):
8080
player1 = self.players[player1_index]
8181
class1 = player1.__class__
8282
if player1_index == player2_index:
83-
# Check for arguments in __init__. If more than one (self), then
84-
# deepcopy rather than instantiating the class variable
85-
argspec = inspect.getargspec(player1.__init__)
86-
if len(argspec.args) > 1:
87-
player2 = copy.deepcopy(player1)
88-
else:
89-
player2 = class1()
90-
player2.tournament_attributes = player1.tournament_attributes
9183
class2 = class1
84+
try:
85+
player2 = player1.reproduce()
86+
except TypeError:
87+
print(class1)
88+
exit()
89+
## Check for arguments in __init__. If more than one (self), then
90+
## deepcopy rather than instantiating the class variable
91+
#argspec = inspect.getargspec(player1.__init__)
92+
#if len(argspec.args) > 1:
93+
#player2 = copy.deepcopy(player1)
94+
#else:
95+
#player2 = class1()
96+
#player2.tournament_attributes = player1.tournament_attributes
97+
#class2 = class1
9298
else:
9399
player2 = self.players[player2_index]
94100
class2 = player2.__class__

axelrod/strategies/axelrod_tournaments.py

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Davis(Player):
2929
def __init__(self, rounds_to_cooperate=10):
3030
Player.__init__(self)
3131
self._rounds_to_cooperate = rounds_to_cooperate
32+
self.init_args = (self._rounds_to_cooperate,)
3233

3334
def strategy(self, opponent):
3435
"""Begins by playing C, then plays D for the remaining rounds if the
@@ -61,6 +62,9 @@ def __init__(self, start_coop_prob=1.0, end_coop_prob=0.5,
6162
self._start_coop_prob = start_coop_prob
6263
self._end_coop_prob = end_coop_prob
6364
self._rounds_of_decay = rounds_of_decay
65+
self.init_args = (start_coop_prob,
66+
end_coop_prob,
67+
rounds_of_decay)
6468

6569
def _cooperation_probability(self):
6670
"""It's not clear what the interpolating function is, so we'll do
@@ -95,6 +99,7 @@ def __init__(self):
9599
p = float(2) / 7
96100
four_vector = (p, p, p, p)
97101
super(self.__class__, self).__init__(four_vector)
102+
self.init_args = ()
98103

99104

100105
class Joss(MemoryOnePlayer):
@@ -109,6 +114,7 @@ def __init__(self, p=0.9):
109114
four_vector = (p, 0, p, 0)
110115
self.p = p
111116
super(self.__class__, self).__init__(four_vector)
117+
self.init_args = (p,)
112118

113119
def __repr__(self):
114120
return "%s: %s" % (self.name, round(self.p, 2))
@@ -192,6 +198,7 @@ def __init__(self, rounds_to_cooperate=11):
192198
Player.__init__(self)
193199
self._rounds_to_cooperate = rounds_to_cooperate
194200
self.__class__.memory_depth = rounds_to_cooperate
201+
self.init_args = (rounds_to_cooperate,)
195202

196203
def strategy(self, opponent):
197204
rounds = self._rounds_to_cooperate

axelrod/strategies/cycler.py

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def __init__(self, cycle="CCD"):
5454
self.cycle = cycle
5555
self.name += " " + cycle
5656
self.classifier['memory_depth'] = len(cycle) - 1
57+
self.init_args = (cycle,)
5758

5859
def strategy(self, opponent):
5960
curent_round = len(self.history)

axelrod/strategies/darwin.py

-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ def __init__(self):
4343
super(Darwin, self).__init__()
4444
self.response = self.__class__.genome[0]
4545

46-
4746
def strategy(self, opponent):
4847
# Frustrate psychics and ensure that simulated rounds
4948
# do not influence genome.
@@ -68,13 +67,11 @@ def strategy(self, opponent):
6867

6968
return current
7069

71-
7270
def reset(self):
7371
""" Reset instance properties. """
7472
Player.reset(self)
7573
self.__class__.genome[0] = 'C' # Ensure initial Cooperate
7674

77-
7875
def mutate(self, outcome, trial):
7976
""" Select response according to outcome. """
8077
if outcome < 0 and (len(self.__class__.genome) >= trial):

axelrod/strategies/gobymajority.py

+13-10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def __init__(self, memory_depth=0, soft=True):
2121
Player.__init__(self)
2222
self.soft = soft
2323
self.classifier['memory_depth'] = memory_depth
24+
self.init_args = (memory_depth, soft)
2425

2526
def strategy(self, opponent):
2627
"""This is affected by the history of the opponent.
@@ -58,32 +59,34 @@ class GoByMajority40(GoByMajority):
5859
GoByMajority player with a memory of 40.
5960
"""
6061

61-
def __init__(self, memory_depth=40):
62-
super(self.__class__, self).__init__(memory_depth=memory_depth)
62+
def __init__(self, memory_depth=40, soft=True):
63+
super(self.__class__, self).__init__(memory_depth=memory_depth,
64+
soft=soft)
6365

6466

6567
class GoByMajority20(GoByMajority):
6668
"""
6769
GoByMajority player with a memory of 20.
6870
"""
6971

70-
def __init__(self, memory_depth=20):
71-
super(self.__class__, self).__init__(memory_depth=memory_depth)
72-
72+
def __init__(self, memory_depth=20, soft=True):
73+
super(self.__class__, self).__init__(memory_depth=memory_depth,
74+
soft=soft)
7375

7476
class GoByMajority10(GoByMajority):
7577
"""
7678
GoByMajority player with a memory of 10.
7779
"""
7880

79-
def __init__(self, memory_depth=10):
80-
super(self.__class__, self).__init__(memory_depth=memory_depth)
81-
81+
def __init__(self, memory_depth=10, soft=True):
82+
super(self.__class__, self).__init__(memory_depth=memory_depth,
83+
soft=soft)
8284

8385
class GoByMajority5(GoByMajority):
8486
"""
8587
GoByMajority player with a memory of 5.
8688
"""
8789

88-
def __init__(self, memory_depth=5):
89-
super(self.__class__, self).__init__(memory_depth=memory_depth)
90+
def __init__(self, memory_depth=5, soft=True):
91+
super(self.__class__, self).__init__(memory_depth=memory_depth,
92+
soft=soft)

axelrod/strategies/grumpy.py

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(self, starting_state='Nice', grumpy_threshold=10,
2424
self.starting_state = starting_state
2525
self.grumpy_threshold = grumpy_threshold
2626
self.nice_threshold = nice_threshold
27+
self.init_args = (starting_state, grumpy_threshold, nice_threshold)
2728

2829
def strategy(self, opponent):
2930
"""A player that gets grumpier the more the opposition defects,

axelrod/strategies/memoryone.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ def __init__(self, initial='C'):
2525
('D', 'C'): 'D',
2626
('D', 'D'): 'C',
2727
}
28-
self._initial = initial
2928
self.classifier['stochastic'] = False
29+
self._initial = initial
30+
self.init_args = (initial,)
3031

3132
def strategy(self, opponent):
3233
"""Switches if it doesn't get the best payout, traditionally equivalent
@@ -58,6 +59,7 @@ def __init__(self, four_vector, initial='C'):
5859
self._four_vector = dict(zip([('C', 'C'), ('C', 'D'), ('D', 'C'), ('D', 'D')], map(float, four_vector)))
5960
self._initial = initial
6061
self.classifier['stochastic'] = any(0 < x < 1 for x in set(four_vector))
62+
self.init_args = (four_vector, initial)
6163

6264
def strategy(self, opponent):
6365
if not len(opponent.history):
@@ -83,6 +85,7 @@ def __init__(self, p=None):
8385
self.p = p
8486
four_vector = [1, p, 1, p]
8587
super(self.__class__, self).__init__(four_vector)
88+
self.init_args = (p,)
8689

8790
def __repr__(self):
8891
return "%s: %s" % (self.name, round(self.p, 2))
@@ -107,6 +110,7 @@ def __init__(self, ep=0.05):
107110
self.ep = ep
108111
four_vector = (1.-ep, ep, ep, 1.-ep)
109112
super(self.__class__, self).__init__(four_vector)
113+
self.init_args = (ep,)
110114

111115

112116
class ZeroDeterminantPlayer(MemoryOnePlayer):
@@ -137,16 +141,18 @@ def __init__(self, phi=0., s=None, l=None):
137141

138142
four_vector = [p1, p2, p3, p4]
139143
MemoryOnePlayer.__init__(self, four_vector)
144+
self.init_args = (phi, s, l)
140145

141146

142147
class ZDGTFT2(ZeroDeterminantPlayer):
143148
"""A Generous Zero Determinant Strategy."""
144149

145150
name = 'ZD-GTFT-2'
146151

147-
def __init__(self, phi=0., chi=2.):
152+
def __init__(self):
148153
(R, P, S, T) = Game().RPST()
149154
ZeroDeterminantPlayer.__init__(self, phi=0.25, s=0.5, l=R)
155+
self.init_args = ()
150156

151157

152158
class ZDExtort2(ZeroDeterminantPlayer):
@@ -157,6 +163,7 @@ class ZDExtort2(ZeroDeterminantPlayer):
157163
def __init__(self):
158164
(R, P, S, T) = Game().RPST()
159165
ZeroDeterminantPlayer.__init__(self, phi=1./9, s=0.5, l=P)
166+
self.init_args = ()
160167

161168

162169
### Strategies for recreating tournaments
@@ -174,6 +181,7 @@ def __init__(self, q=0.9):
174181
four_vector = (1., 1 - q, 1, 1 - q)
175182
super(self.__class__, self).__init__(four_vector)
176183
self.q = q
184+
self.init_args = (q,)
177185

178186
def __repr__(self):
179187
return "%s: %s" % (self.name, round(self.q, 2))

axelrod/strategies/meta.py

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ def __init__(self, team=None):
9797
self.team = ordinary_strategies
9898

9999
MetaPlayer.__init__(self)
100+
self.init_args = (team,)
100101

101102
# For each player, we will keep the history of proposed moves and
102103
# a running score since the beginning of the game.

axelrod/strategies/mindreader.py

-3
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ class MindReader(Player):
5454
'manipulates_state': True
5555
}
5656

57-
def __init__(self):
58-
Player.__init__(self)
59-
6057
def strategy(self, opponent):
6158
"""Pretends to play the opponent a number of times before each match.
6259
The primary purpose is to look far enough ahead to see if a defect will

axelrod/strategies/oncebitten.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def __init__(self, forget_probability = 0.05):
100100
self.D_count = 0
101101
self._initial = 'C'
102102
self.forget_probability = forget_probability
103+
self.init_args = (forget_probability,)
103104

104105
def strategy(self, opponent):
105106
r = random.random()
@@ -133,10 +134,6 @@ class FoolMeForever(Player):
133134
'manipulates_state': False
134135
}
135136

136-
def __init__(self):
137-
Player.__init__(self)
138-
self.classifier['stochastic'] = False
139-
140137
def strategy(self, opponent):
141138
if opponent.defections > 0:
142139
return 'C'

axelrod/strategies/rand.py

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Random(Player):
1717
def __init__(self, p=0.5):
1818
Player.__init__(self)
1919
self.p = p
20+
self.init_args = (p,)
2021

2122
def strategy(self, opponent):
2223
r = random.random()

axelrod/strategies/retaliate.py

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(self, retaliation_threshold=0.1):
2727
'Retaliate (' +
2828
str(self.retaliation_threshold) + ')')
2929
self.play_counts = defaultdict(int)
30+
self.init_args = (retaliation_threshold,)
3031

3132
def strategy(self, opponent):
3233
"""
@@ -94,6 +95,7 @@ def __init__(self, retaliation_threshold = 0.1, retaliation_limit = 20,):
9495
self.retaliation_threshold = retaliation_threshold
9596
self.retaliation_limit = retaliation_limit
9697
self.play_counts = defaultdict(int)
98+
self.init_args = (retaliation_threshold, retaliation_limit)
9799

98100
self.name = (
99101
'Limited Retaliate (' +

0 commit comments

Comments
 (0)