Skip to content

Commit 592823b

Browse files
authored
Merge pull request #1016 from souravsingh/new-strategy
Add EugineNier strategy from LessWrong
2 parents ed8c536 + f5f89a6 commit 592823b

File tree

4 files changed

+92
-5
lines changed

4 files changed

+92
-5
lines changed

axelrod/strategies/_strategies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
7777
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
7878
OmegaTFT, Gradual, ContriteTitForTat, SlowTitForTwoTats, AdaptiveTitForTat,
79-
SpitefulTitForTat, SlowTitForTwoTats2, Alexei)
79+
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier)
8080
from .verybad import VeryBad
8181
from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse,
8282
WorseAndWorse2, WorseAndWorse3)
@@ -126,6 +126,7 @@
126126
DoubleResurrection,
127127
EasyGo,
128128
Eatherley,
129+
EugineNier,
129130
EventualCycleHunter,
130131
EvolvedANN,
131132
EvolvedANN5,

axelrod/strategies/titfortat.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,10 @@ def strategy(self, opponent: Player) -> Action:
642642
class Alexei(Player):
643643
"""
644644
Plays similar to Tit-for-Tat, but always defect on last turn.
645-
645+
646646
Names:
647647
648-
- Alexei's Strategy: [LessWrong2011]_
648+
- Alexei: [LessWrong2011]_
649649
"""
650650

651651
name = 'Alexei'
@@ -665,3 +665,43 @@ def strategy(self, opponent: Player) -> Action:
665665
if opponent.history[-1] == D:
666666
return D
667667
return C
668+
669+
@FinalTransformer((D,), name_prefix=None)
670+
class EugineNier(Player):
671+
"""
672+
Plays similar to Tit-for-Tat, but with two conditions:
673+
1) Always Defect on Last Move
674+
2) If other player defects five times, switch to all defects.
675+
676+
Names:
677+
678+
- Eugine Nier: [LessWrong2011]_
679+
"""
680+
681+
name = 'EugineNier'
682+
classifier = {
683+
'memory_depth': float('inf'),
684+
'stochastic': False,
685+
'makes_use_of': {'length'},
686+
'long_run_time': False,
687+
'inspects_source': False,
688+
'manipulates_source': False,
689+
'manipulates_state': False
690+
}
691+
692+
def __init__(self):
693+
super().__init__()
694+
self.is_defector = False
695+
696+
def strategy(self, opponent: Player) -> Action:
697+
if not self.history:
698+
return C
699+
if not (self.is_defector) and opponent.defections >= 5:
700+
self.is_defector = True
701+
if self.is_defector:
702+
return D
703+
return opponent.history[-1]
704+
705+
def reset(self):
706+
super().reset()
707+
self.is_defector = False

axelrod/tests/strategies/test_titfortat.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,10 +593,56 @@ def test_strategy(self):
593593
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (C, D)]
594594
self.versus_test(axelrod.Alternator(), expected_actions=actions,
595595
match_attributes={"length": -1})
596-
596+
597597
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (D, D)]
598598
self.versus_test(axelrod.Alternator(), expected_actions=actions)
599599

600600
opponent = axelrod.MockPlayer(actions=[C, C, D, D, C, D])
601601
actions = [(C, C), (C, C), (C, D), (D, D), (D, C), (D, D)]
602602
self.versus_test(opponent, expected_actions=actions)
603+
604+
class TestEugineNier(TestPlayer):
605+
"""
606+
Tests for the Eugine Nier strategy
607+
"""
608+
609+
name = "EugineNier: ('D',)"
610+
player = axelrod.EugineNier
611+
expected_classifier = {
612+
'memory_depth': float('inf'),
613+
'stochastic': False,
614+
'makes_use_of': {'length'},
615+
'inspects_source': False,
616+
'manipulates_source': False,
617+
'manipulates_state': False
618+
}
619+
620+
def test_strategy(self):
621+
self.first_play_test(C)
622+
self.second_play_test(rCC=C, rCD=D, rDC=C, rDD=D)
623+
624+
actions = [(C, C), (C, C), (C, C), (D, C)]
625+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
626+
attrs={"is_defector": False})
627+
628+
actions = [(C, C), (C, C), (C, C), (C, C)]
629+
self.versus_test(axelrod.Cooperator(), expected_actions=actions,
630+
attrs={"is_defector": False},
631+
match_attributes={"length": -1})
632+
633+
634+
# Plays TfT and defects in last round
635+
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (D, D)]
636+
self.versus_test(axelrod.Alternator(), expected_actions=actions,
637+
attrs={"is_defector": False})
638+
639+
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (C, D)]
640+
self.versus_test(axelrod.Alternator(), expected_actions=actions,
641+
attrs={"is_defector": False},
642+
match_attributes={"length": -1})
643+
644+
# Becomes defector after 5 defections
645+
opponent = axelrod.MockPlayer(actions=[D, C, D, D, D, D, C, C])
646+
actions = [(C, D), (D, C), (C, D), (D, D),
647+
(D, D), (D, D), (D, C), (D, C)]
648+
self.versus_test(opponent, expected_actions=actions)

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ length of each match of the tournament::
8080
... }
8181
>>> strategies = axl.filtered_strategies(filterset)
8282
>>> len(strategies)
83-
27
83+
28
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)