Skip to content

Commit 8b434a9

Browse files
gaffney2010drvinceknight
authored andcommitted
Implemented WmAdams strategy (k44r from Axelrod's second) (#1142)
* Implemented WmAdams strategy (k44r from Axelrod's second) * Fixed formatting issues mentioned in PR * Minor formatting fixes. * Subtracted first defect.
1 parent 36ac9a4 commit 8b434a9

File tree

5 files changed

+109
-24
lines changed

5 files changed

+109
-24
lines changed

axelrod/strategies/_strategies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
UnnamedStrategy, SteinAndRapoport, TidemanAndChieruzzi)
1010
from .axelrod_second import (
1111
Champion, Eatherley, Tester, Gladstein, Tranquilizer, MoreGrofman,
12-
Kluepfel, Borufsen, Cave)
12+
Kluepfel, Borufsen, Cave, WmAdams)
1313
from .backstabber import BackStabber, DoubleCrosser
1414
from .better_and_better import BetterAndBetter
1515
from .bush_mosteller import BushMosteller
@@ -274,6 +274,7 @@
274274
Winner21,
275275
WinShiftLoseStay,
276276
WinStayLoseShift,
277+
WmAdams,
277278
WorseAndWorse,
278279
WorseAndWorse2,
279280
WorseAndWorse3,

axelrod/strategies/axelrod_second.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,9 +755,9 @@ def strategy(self, opponent: Player) -> Action:
755755
turn = len(self.history) + 1
756756
if turn == 1: return C
757757

758-
did_d = np.vectorize(lambda action: float(action == D))
759-
number_defects = np.sum(did_d(opponent.history))
760-
perc_defects = number_defects / turn # Size of numerator is smaller than denomator -- How it was in the Fortran.
758+
number_defects = opponent.defections
759+
# Size of numerator is smaller than denomator -- How it was in the Fortran.
760+
perc_defects = number_defects / turn
761761

762762
# If overly defect or appears random
763763
if turn > 39 and perc_defects > 0.39: return D
@@ -771,3 +771,41 @@ def strategy(self, opponent: Player) -> Action:
771771
return random_choice(0.5)
772772
else:
773773
return C
774+
775+
class WmAdams(Player):
776+
"""
777+
Strategy submitted to Axelrod's second tournament by William Adams (K44R),
778+
and came in fifth in that tournament.
779+
780+
Count the number of opponent defections after their first move, call
781+
`c_defect`. Defect if c_defect equals 4, 7, or 9. If c_defect > 9,
782+
then defect immediately after opponent defects with probability =
783+
(0.5)^(c_defect-1). Otherwise cooperate.
784+
785+
Names:
786+
787+
- WmAdams: [Axelrod1980b]_
788+
"""
789+
790+
name = "WmAdams"
791+
classifier = {
792+
'memory_depth': float('inf'),
793+
'stochastic': True,
794+
'makes_use_of': set(),
795+
'long_run_time': False,
796+
'inspects_source': False,
797+
'manipulates_source': False,
798+
'manipulates_state': False
799+
}
800+
801+
def strategy(self, opponent: Player) -> Action:
802+
if len(self.history) <= 1:
803+
return C
804+
number_defects = opponent.defections
805+
if opponent.history[0] == D:
806+
number_defects -= 1
807+
808+
if number_defects in [4, 7, 9]: return D
809+
if number_defects > 9 and opponent.history[-1] == D:
810+
return random_choice((0.5) ** (number_defects - 9))
811+
return C

axelrod/tests/strategies/test_axelrod_second.py

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -442,14 +442,15 @@ def test_strategy(self):
442442

443443
# Now we have to test the detect-random logic, which doesn't pick up
444444
# until after 26 turns. So we need a big sample.
445-
actions = [(C, D), (D, D), (D, D), (D, D), (D, D), (D, C), (C, C), (C, D),
446-
(C, C), (D, D), (D, C), (C, C), (C, D), (D, D), (C, D), (D, D),
447-
(D, C), (C, C), (D, C), (C, C), (C, D), (D, D), (D, C), (C, D),
448-
(D, C), (C, C), (C, D),
445+
actions = [(C, D), (D, D), (D, D), (D, D), (D, D), (D, C), (C, C),
446+
(C, D), (C, C), (D, D), (D, C), (C, C), (C, D), (D, D),
447+
(C, D), (D, D), (D, C), (C, C), (D, C), (C, C), (C, D),
448+
(D, D), (D, C), (C, D), (D, C), (C, C), (C, D),
449449
# Success detect random opponent for remaining turns.
450-
(D, D),(D, D),(D, D),(D, C),(D, D),(D, C),(D, D),(D, C),(D, D),
451-
(D, C),(D, C),(D, D),(D, D),(D, C),(D, C),(D, C),(D, C),(D, D),
452-
(D, C),(D, C),(D, C),(D, C),(D, D)]
450+
(D, D), (D, D), (D, D), (D, C), (D, D), (D, C), (D, D),
451+
(D, C), (D, D), (D, C), (D, C), (D, D), (D, D), (D, C),
452+
(D, C), (D, C), (D, C), (D, D), (D, C), (D, C), (D, C),
453+
(D, C), (D, D)]
453454
self.versus_test(axelrod.Random(0.5), expected_actions=actions, seed=10)
454455

455456
class TestBorufsen(TestPlayer):
@@ -475,16 +476,21 @@ def test_strategy(self):
475476
self.versus_test(axelrod.Defector(), expected_actions=actions)
476477

477478
# Alternates with additional coop, every sixth turn
478-
# Won't be labeled as random, since 2/3 of opponent's C follow player's C
479-
# `flip_next_defect` will get set on the sixth turn, which changes the seventh action
479+
# Won't be labeled as random, since 2/3 of opponent's C follow
480+
# player's C
481+
# `flip_next_defect` will get set on the sixth turn, which changes the
482+
# seventh action
480483
# Note that the first two turns of each period of six aren't
481-
# marked as echoes, and the third isn't marked that way until the fourth turn.
484+
# marked as echoes, and the third isn't marked that way until the
485+
# fourth turn.
482486
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (C, D)] * 20
483487
self.versus_test(axelrod.Alternator(), expected_actions=actions)
484488

485489
# Basically does tit-for-tat against Win-Shift, Lose-Stay D
486-
# After 26 turns, will detect random since half of opponent's C follow Cs
487-
# Coming out of it, there will be new pattern. Then random is detected again.
490+
# After 26 turns, will detect random since half of opponent's C follow
491+
# Cs
492+
# Coming out of it, there will be new pattern. Then random is detected
493+
# again.
488494
actions = [(C, D), (D, C), (C, C)] * 8 + \
489495
[(C, D), (D, C)] + [(D, C)] * 25 + \
490496
[(D, C)] + [(C, C), (C, D), (D, C)] * 8 + \
@@ -505,7 +511,7 @@ class TestCave(TestPlayer):
505511
}
506512

507513
def test_strategy(self):
508-
actions = [(C, C)] * 100
514+
actions = [(C, C)] * 100
509515
self.versus_test(axelrod.Cooperator(), expected_actions=actions)
510516

511517
# It will take until turn 18 to respond decide to repond D->D
@@ -531,11 +537,51 @@ def test_strategy(self):
531537

532538
#Here it will take until turn 40 to detect random and defect
533539
actions = [(C, C)]
534-
actions += [(C, D), (D, C), (C, D), (D, C), (C, D), (C, C), (C, D),
535-
(C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C),
536-
(C, D), (C, C), (C, D), (D, C), (C, D), (D, C), (C, D),
537-
(D, C), (C, D), (C, C), (C, D), (C, C), (C, D), (C, C),
538-
(C, D), (D, C), (C, D), (D, C), (C, D), (D, C), (C, D)] #Randomly choose
540+
actions += [(C, D), (D, C), (C, D), (D, C), (C, D), (C, C), (C, D),
541+
(C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C),
542+
(C, D), (C, C), (C, D), (D, C), (C, D), (D, C), (C, D),
543+
(D, C), (C, D), (C, C), (C, D), (C, C), (C, D), (C, C),
544+
(C, D), (D, C), (C, D), (D, C), (C, D), (D, C), (C, D)] #Randomly choose
539545
actions += [(D, C), (C, D), (D, C)] # 17 D have come, so tit for tat for a while
540546
actions += [(D, D), (D, C)] * 100 # Random finally detected
541547
self.versus_test(axelrod.Alternator(), expected_actions=actions, seed=2)
548+
549+
class TestWmAdams(TestPlayer):
550+
name = "WmAdams"
551+
player = axelrod.WmAdams
552+
expected_classifier = {
553+
'memory_depth': float('inf'),
554+
'stochastic': True,
555+
'makes_use_of': set(),
556+
'long_run_time': False,
557+
'inspects_source': False,
558+
'manipulates_source': False,
559+
'manipulates_state': False
560+
}
561+
562+
def test_strategy(self):
563+
actions = [(C, C)] * 100 # Cooperate forever
564+
self.versus_test(axelrod.Cooperator(), expected_actions=actions)
565+
566+
# Will ignore the first four defects
567+
opponent_actions = [D] * 4 + [C] * 100
568+
defect_four = axelrod.MockPlayer(actions=opponent_actions)
569+
actions = [(C, D)] * 4 + [(C, C)] * 100
570+
self.versus_test(defect_four, expected_actions=actions)
571+
572+
actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D),
573+
(C, D), (D, D), (C, D), (D, D), (C, D), (D, D), (D, D),
574+
(D, D), (D, D)]
575+
self.versus_test(axelrod.Defector(), expected_actions=actions, seed=1)
576+
actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D),
577+
(C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (C, D),
578+
(D, D), (D, D)]
579+
self.versus_test(axelrod.Defector(), expected_actions=actions, seed=2)
580+
581+
# After responding to the 11th D (counted as 10 D), just start cooperating
582+
opponent_actions = [D] * 11 + [C] * 100
583+
changed_man = axelrod.MockPlayer(actions=opponent_actions)
584+
actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D),
585+
(C, D), (D, D), (C, D), (D, D), (C, C)]
586+
actions += [(C, C)] * 99
587+
self.versus_test(changed_man, expected_actions=actions, seed=1)

docs/reference/overview_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ repository.
114114
"K41R_", "Herb Weiner", "Not Implemented"
115115
"K42R_", "Otto Borufsen", ":class:`Borufsen <axelrod.strategies.axelrod_second.Borufsen>`"
116116
"K43R_", "R D Anderson", "Not Implemented"
117-
"K44R_", "William Adams", "Not Implemented"
117+
"K44R_", "William Adams", ":class:`WmAdams <axelrod.strategies.axelrod_second.WmAdams>`"
118118
"K45R_", "Michael F McGurrin", "Not Implemented"
119119
"K46R_", "Graham J Eatherley", ":class:`Eatherley <axelrod.strategies.axelrod_second.Eatherley>`"
120120
"K47R_", "Richard Hufford", "Not Implemented"

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ strategies::
4747
... }
4848
>>> strategies = axl.filtered_strategies(filterset)
4949
>>> len(strategies)
50-
77
50+
78
5151

5252
Or, to find out how many strategies only use 1 turn worth of memory to
5353
make a decision::

0 commit comments

Comments
 (0)