Skip to content

Commit 1100a92

Browse files
committed
Merge pull request #296 from marcharper/strategy_reorg
Some strategy reorganizations
2 parents 391cf7b + 92b5125 commit 1100a92

24 files changed

+271
-235
lines changed

README.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ The documentation includes details of how to setup a tournament but here is an
5757
example showing how to create a tournament with all stochastic strategies::
5858

5959
import axelrod
60-
strategies = [s() for s in axelrod.ordinary_strategies if s().stochastic]
60+
strategies = [s() for s in axelrod.ordinary_strategies if s().classifier['stochastic']]
6161
tournament = axelrod.Tournament(strategies)
6262
results = tournament.play()
6363

@@ -67,10 +67,8 @@ The :code:`results` object now contains all the results we could need::
6767

6868
gives::
6969

70-
['Inverse', 'Forgetful Fool Me Once', 'Nice Average Copier', 'Champion',
71-
'Generous Tit-For-Tat', 'Eatherley', 'ZD-GTFT-2', 'Meta Majority', 'Soft Joss',
72-
'Average Copier', 'Feld', 'Stochastic WSLS', 'Tullock', 'Joss', 'ZD-Extort-2',
73-
'Grofman', 'Random', 'Meta Winner', 'Meta Minority']
70+
['Meta Hunter', 'Inverse', 'Forgetful Fool Me Once', 'GTFT: 0.33', 'Champion', 'ZD-GTFT-2', 'Eatherley', 'Math Constant Hunter', 'Random Hunter', 'Soft Joss: 0.9', 'Meta Majority', 'Nice Average Copier', 'Feld', 'Meta Minority', 'Grofman', 'Stochastic WSLS', 'ZD-Extort-2', 'Tullock', 'Joss: 0.9', 'Arrogant QLearner', 'Average Copier', 'Cautious QLearner', 'Hesitant QLearner', 'Risky QLearner', 'Random: 0.5', 'Meta Winner']
71+
7472

7573
Results
7674
=======

axelrod/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from __future__ import absolute_import
22

3+
# The order of imports matters!
34
from .random_ import random_choice
4-
55
from .plot import *
66
from .game import *
77
from .player import *
88
from .mock_player import *
99
from .round_robin import *
10+
from .strategies import *
1011
from .tournament import *
1112
from .tournament_manager import *
12-
from .strategies import *
1313
from .ecosystem import *

axelrod/player.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66
flip_dict = {C: D, D: C}
77

88

9+
# Strategy classifiers
10+
11+
def is_cheater(s):
12+
"""
13+
A function to check if a strategy cheats.
14+
"""
15+
classifier = s.classifier
16+
return classifier['inspects_source'] or\
17+
classifier['manipulates_source'] or\
18+
classifier['manipulates_state']
19+
20+
921
def update_histories(player1, player2, move1, move2):
1022
"""Updates histories and cooperation / defections counts following play."""
1123
# Update histories
@@ -42,8 +54,6 @@ def __init__(self):
4254
"""Initiates an empty history and 0 score for a player."""
4355
self.history = []
4456
self.classifier = copy.copy(self.classifier)
45-
self.classifier['stochastic'] = (
46-
"random" in inspect.getsource(self.__class__))
4757
if self.name == "Player":
4858
self.classifier['stochastic'] = False
4959
for dimension in self.default_classifier:

axelrod/strategies/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,18 @@
1+
from ..player import is_cheater
12
from ._strategies import *
3+
4+
# `from ._strategies import *` import the collection `strategies`
5+
# Now import the Meta strategies. This cannot be done in _strategies
6+
# because it creates circular dependencies
7+
8+
from .meta import MetaMajority, MetaMinority, MetaWinner, MetaHunter
9+
strategies.extend((MetaHunter, MetaMajority, MetaMinority, MetaWinner))
10+
11+
# Distinguished strategy collections in addition to
12+
# `strategies` from _strategies.py
13+
14+
ordinary_strategies = [s for s in strategies if not is_cheater(s())]
15+
cheating_strategies = [s for s in strategies if is_cheater(s())]
16+
17+
# Defined by fiat for demo purposes
18+
basic_strategies = [Alternator, Cooperator, Defector, Random, TitForTat]

axelrod/strategies/_strategies.py

Lines changed: 48 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,52 @@
11
from __future__ import absolute_import
22

3-
from .alternator import *
4-
from .appeaser import *
5-
from .averagecopier import *
6-
from .axelrod_tournaments import *
7-
from .backstabber import *
3+
from .alternator import Alternator
4+
from .appeaser import Appeaser
5+
from .averagecopier import AverageCopier, NiceAverageCopier
6+
from .axelrod_tournaments import (
7+
Davis, Feld, Grofman, Joss, Shubik, Tullock, Champion, Eatherley, Tester)
8+
from .backstabber import BackStabber, DoubleCrosser
89
from .calculator import Calculator
9-
from .cooperator import *
10-
from .cycler import *
11-
from .darwin import *
12-
from .defector import *
13-
from .forgiver import *
14-
from .geller import *
15-
from .gobymajority import *
16-
from .grudger import *
17-
from .grumpy import *
18-
from .hunter import *
19-
from .inverse import *
20-
from .mathematicalconstants import *
21-
from .memoryone import *
22-
from .meta import *
23-
from .mindcontrol import *
24-
from .mindreader import *
25-
from .oncebitten import *
26-
from .prober import *
27-
from .punisher import *
28-
from .qlearner import *
29-
from .rand import *
30-
from .retaliate import *
31-
from .titfortat import *
10+
from .cooperator import Cooperator, TrickyCooperator
11+
from .cycler import AntiCycler, CyclerCCD, CyclerCCCD, CyclerCCCCCD
12+
from .darwin import Darwin
13+
from .defector import Defector, TrickyDefector
14+
from .forgiver import Forgiver, ForgivingTitForTat
15+
from .geller import Geller, GellerCooperator, GellerDefector
16+
from .gobymajority import (
17+
GoByMajority, GoByMajority10, GoByMajority20, GoByMajority40,
18+
GoByMajority5)
19+
from .grudger import Grudger, ForgetfulGrudger, OppositeGrudger, Aggravater
20+
from .grumpy import Grumpy
21+
from .hunter import (
22+
DefectorHunter, CooperatorHunter, AlternatorHunter, MathConstantHunter,
23+
RandomHunter)
24+
from .inverse import Inverse
25+
from .mathematicalconstants import Golden, Pi, e
26+
from .memoryone import (
27+
WinStayLoseShift,GTFT, StochasticCooperator, StochasticWSLS, ZDGTFT2,
28+
ZDExtort2, SoftJoss, MemoryOnePlayer)
29+
from .mindcontrol import MindController, MindWarper, MindBender
30+
from .mindreader import MindReader, ProtectedMindReader
31+
from .oncebitten import OnceBitten, FoolMeOnce, ForgetfulFoolMeOnce, FoolMeForever
32+
from .prober import Prober, Prober2, Prober3, HardProber
33+
from .punisher import Punisher, InversePunisher
34+
from .qlearner import RiskyQLearner, ArrogantQLearner, HesitantQLearner, CautiousQLearner
35+
from .rand import Random
36+
from .retaliate import (
37+
Retaliate, Retaliate2, Retaliate3, LimitedRetaliate, LimitedRetaliate2,
38+
LimitedRetaliate3)
39+
from .titfortat import (
40+
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
41+
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats)
3242

33-
# A list of strategies to quickly create a tournament
34-
basic_strategies = [
35-
Alternator,
36-
Cooperator,
37-
Defector,
38-
Random,
39-
TitForTat,
40-
]
4143

42-
# All the strategies in the tournament
43-
strategies = basic_strategies + [
44+
# Note: Meta* strategies are handled in .__init__.py, so this is not the
45+
# final form of the list
46+
47+
strategies = [
4448
Aggravater,
49+
Alternator,
4550
AlternatorHunter,
4651
AntiCycler,
4752
AntiTitForTat,
@@ -53,12 +58,14 @@
5358
Calculator,
5459
CautiousQLearner,
5560
Champion,
61+
Cooperator,
5662
CooperatorHunter,
5763
CyclerCCCCCD,
5864
CyclerCCCD,
5965
CyclerCCD,
6066
Darwin,
6167
Davis,
68+
Defector,
6269
DefectorHunter,
6370
DoubleCrosser,
6471
Eatherley,
@@ -93,10 +100,6 @@
93100
LimitedRetaliate2,
94101
LimitedRetaliate3,
95102
MathConstantHunter,
96-
MetaHunter,
97-
MetaMajority,
98-
MetaMinority,
99-
MetaWinner,
100103
MindBender,
101104
MindController,
102105
MindReader,
@@ -110,6 +113,7 @@
110113
Prober3,
111114
ProtectedMindReader,
112115
Punisher,
116+
Random,
113117
RandomHunter,
114118
Retaliate,
115119
Retaliate2,
@@ -121,6 +125,7 @@
121125
StochasticWSLS,
122126
SuspiciousTitForTat,
123127
Tester,
128+
TitForTat,
124129
TitFor2Tats,
125130
TrickyCooperator,
126131
TrickyDefector,
@@ -130,17 +135,4 @@
130135
ZDExtort2,
131136
ZDGTFT2,
132137
e,
133-
]
134-
135-
136-
def is_cheater(s):
137-
"""
138-
A function to check if a strategy cheats.
139-
"""
140-
classifier = s.classifier
141-
return classifier['inspects_source'] or\
142-
classifier['manipulates_source'] or\
143-
classifier['manipulates_state']
144-
145-
ordinary_strategies = [s for s in strategies if not is_cheater(s)]
146-
cheating_strategies = [s for s in strategies if is_cheater(s)]
138+
]

axelrod/strategies/axelrod_tournaments.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
Additional strategies from Axelrod's two tournaments.
33
"""
44

5-
from axelrod import Player
6-
75
import random
86

7+
from axelrod import Player
8+
from.memoryone import MemoryOnePlayer
9+
910

1011
flip_dict = {'C': 'D', 'D': 'C'}
1112

13+
1214
## First Tournament
1315

1416
class Davis(Player):
@@ -47,7 +49,7 @@ class Feld(Player):
4749
name = "Feld"
4850
classifier = {
4951
'memory_depth': 200, # Varies actually, eventually becomes depth 1
50-
'stochastic': False,
52+
'stochastic': True,
5153
'inspects_source': False,
5254
'manipulates_source': False,
5355
'manipulates_state': False
@@ -82,6 +84,36 @@ def strategy(self, opponent):
8284
return 'D'
8385

8486

87+
class Grofman(MemoryOnePlayer):
88+
"""
89+
Cooperates with probability 2/7.
90+
"""
91+
92+
name = "Grofman"
93+
94+
def __init__(self):
95+
p = float(2) / 7
96+
four_vector = (p, p, p, p)
97+
super(self.__class__, self).__init__(four_vector)
98+
99+
100+
class Joss(MemoryOnePlayer):
101+
"""
102+
Cooperates with probability 0.9 when the opponent cooperates, otherwise
103+
emulates Tit-For-Tat.
104+
"""
105+
106+
name = "Joss"
107+
108+
def __init__(self, p=0.9):
109+
four_vector = (p, 0, p, 0)
110+
self.p = p
111+
super(self.__class__, self).__init__(four_vector)
112+
113+
def __repr__(self):
114+
return "%s: %s" % (self.name, round(self.p, 2))
115+
116+
85117
class Shubik(Player):
86118
"""
87119
Plays like Tit-For-Tat with the following modification. After
@@ -141,6 +173,7 @@ def reset(self):
141173
self.retaliation_length = 0
142174
self.retaliation_remaining = 0
143175

176+
144177
class Tullock(Player):
145178
"""
146179
Cooperates for the first 11 rounds then randomly cooperates 10% less often
@@ -149,7 +182,7 @@ class Tullock(Player):
149182
name = "Tullock"
150183
classifier = {
151184
'memory_depth': 11, # long memory, modified by init
152-
'stochastic': False,
185+
'stochastic': True,
153186
'inspects_source': False,
154187
'manipulates_source': False,
155188
'manipulates_state': False
@@ -183,7 +216,7 @@ class Champion(Player):
183216
name = "Champion"
184217
classifier = {
185218
'memory_depth': float('inf'),
186-
'stochastic': False,
219+
'stochastic': True,
187220
'inspects_source': False,
188221
'manipulates_source': False,
189222
'manipulates_state': False
@@ -217,7 +250,7 @@ class Eatherley(Player):
217250
name = "Eatherley"
218251
classifier = {
219252
'memory_depth': float('inf'),
220-
'stochastic': False,
253+
'stochastic': True,
221254
'inspects_source': False,
222255
'manipulates_source': False,
223256
'manipulates_state': False

axelrod/strategies/calculator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import itertools
22

33
from axelrod import Player
4-
from .memoryone import Joss
4+
from .axelrod_tournaments import Joss
55

66

77
class Calculator(Player):

axelrod/strategies/cycler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def __init__(self, cycle="CCD"):
5353
Player.__init__(self)
5454
self.cycle = cycle
5555
self.name += " " + cycle
56-
self.memory_depth = len(cycle)
56+
self.classifier['memory_depth'] = len(cycle) - 1
5757

5858
def strategy(self, opponent):
5959
curent_round = len(self.history)

axelrod/strategies/geller.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def strategy(self, opponent):
5555
else:
5656
return opponent.strategy(self)
5757

58+
5859
class GellerCooperator(Geller):
5960
"""Observes what the payer will do (like :code:`Geller`) but if unable to
6061
will cooperate.
@@ -69,6 +70,7 @@ class GellerCooperator(Geller):
6970
'manipulates_state': False
7071
}
7172

73+
7274
class GellerDefector(Geller):
7375
"""Observes what the payer will do (like :code:`Geller`) but if unable to
7476
will defect.

axelrod/strategies/gobymajority.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ class GoByMajority(Player):
1313
'stochastic': False,
1414
'inspects_source': False,
1515
'manipulates_source': False,
16-
'manipulates_state': False
16+
'manipulates_state': False,
17+
'memory_depth': 0 # memory_depth may be altered by __init__
1718
}
18-
# memory_depth is set by __init__
1919

2020
def __init__(self, memory_depth=0, soft=True):
2121
Player.__init__(self)

0 commit comments

Comments
 (0)