Skip to content

Commit 66bf7b2

Browse files
authored
Merge pull request #1091 from dmanc/master
Michaelos strategy
2 parents 6e4daa5 + e02e232 commit 66bf7b2

File tree

4 files changed

+104
-4
lines changed

4 files changed

+104
-4
lines changed

axelrod/strategies/_strategies.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@
7676
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
7777
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
7878
OmegaTFT, Gradual, ContriteTitForTat, AdaptiveTitForTat,
79-
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier,
80-
DynamicTwoTitsForTat, NTitsForMTats)
79+
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier, DynamicTwoTitsForTat, NTitsForMTats, Michaelos)
8180
from .verybad import VeryBad
8281
from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse,
8382
WorseAndWorse2, WorseAndWorse3)
@@ -191,6 +190,7 @@
191190
MathConstantHunter,
192191
NaiveProber,
193192
MEM2,
193+
Michaelos,
194194
MindBender,
195195
MindController,
196196
MindReader,

axelrod/strategies/titfortat.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,3 +778,52 @@ def strategy(self, opponent: Player) -> Action:
778778
def reset(self):
779779
super().reset()
780780
self.retaliate_count = 0
781+
782+
783+
@FinalTransformer((D,), name_prefix=None)
784+
class Michaelos(Player):
785+
"""
786+
Plays similar to Tit-for-Tat with two exceptions:
787+
1) Defect on last turn.
788+
2) After own defection and opponent's cooperation, 50 percent of the time,
789+
cooperate. The other 50 percent of the time, always defect for the rest of
790+
the game.
791+
792+
Names:
793+
794+
- Michaelos: [LessWrong2011]_
795+
"""
796+
797+
name = 'Michaelos'
798+
classifier = {
799+
'memory_depth': float('inf'),
800+
'stochastic': True,
801+
'makes_use_of': {'length'},
802+
'long_run_time': False,
803+
'inspects_source': False,
804+
'manipulates_source': False,
805+
'manipulates_state': False
806+
}
807+
808+
def __init__(self):
809+
super().__init__()
810+
self.is_defector = False
811+
812+
def strategy(self, opponent: Player) -> Action:
813+
if not self.history:
814+
return C
815+
if self.is_defector:
816+
return D
817+
if self.history[-1] == D and opponent.history[-1] == C:
818+
decision = random_choice()
819+
if decision == C:
820+
return C
821+
else:
822+
self.is_defector = True
823+
return D
824+
825+
return opponent.history[-1]
826+
827+
def reset(self):
828+
super().reset()
829+
self.is_defector = False

axelrod/tests/strategies/test_titfortat.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,3 +717,54 @@ def test_varying_memory_depth(self):
717717
self.assertEqual(self.player(1, 1).classifier['memory_depth'], 1)
718718
self.assertEqual(self.player(0, 3).classifier['memory_depth'], 3)
719719
self.assertEqual(self.player(5, 3).classifier['memory_depth'], 5)
720+
721+
722+
class TestMichaelos(TestPlayer):
723+
"""
724+
Tests for the Michaelos strategy
725+
"""
726+
727+
name = "Michaelos: (D,)"
728+
player = axelrod.Michaelos
729+
expected_classifier = {
730+
'memory_depth': float('inf'),
731+
'stochastic': True,
732+
'makes_use_of': {'length'},
733+
'inspects_source': False,
734+
'manipulates_source': False,
735+
'manipulates_state': False
736+
}
737+
738+
def test_strategy(self):
739+
740+
actions = [(C, C), (C, C), (C, C), (D, C)]
741+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
742+
attrs={"is_defector": False}, seed=2)
743+
744+
actions = [(C, C), (C, C), (C, C), (C, C)]
745+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
746+
attrs={"is_defector": False},
747+
match_attributes={"length": -1}, seed=2)
748+
749+
actions = [(C, D), (D, D), (D, D), (D, D)]
750+
self.versus_test(axelrod.Defector(), expected_actions=actions,
751+
attrs={"is_defector": False}, seed=2)
752+
753+
actions = [(C, D), (D, D), (D, D), (D, D)]
754+
self.versus_test(axelrod.Defector(), expected_actions=actions,
755+
attrs={"is_defector": False},
756+
match_attributes={"length": -1}, seed=2)
757+
758+
# Chance of becoming a defector is 50% after (D, C) occurs.
759+
actions = [(C, C), (C, D), (D, C), (C, D), (D, C)]
760+
self.versus_test(axelrod.Alternator(), expected_actions=actions,
761+
attrs={"is_defector": False}, seed=3)
762+
763+
actions = [(C, C), (C, D), (D, C), (D, D), (D, C), (D, D), (D, C)]
764+
self.versus_test(axelrod.Alternator(), expected_actions=actions,
765+
attrs={"is_defector": True}, seed=2)
766+
767+
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (D, D), (D, C)]
768+
self.versus_test(axelrod.Alternator(), expected_actions=actions,
769+
attrs={"is_defector": True},
770+
match_attributes={"length": -1}, seed=1)

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-
71
50+
72
5151

5252
Or, to find out how many strategies only use 1 turn worth of memory to
5353
make a decision::
@@ -80,7 +80,7 @@ length of each match of the tournament::
8080
... }
8181
>>> strategies = axl.filtered_strategies(filterset)
8282
>>> len(strategies)
83-
28
83+
29
8484

8585
Note that in the filterset dictionary, the value for the 'makes_use_of' key
8686
must be a list. Here is how we might identify the number of strategies that use

0 commit comments

Comments
 (0)