Skip to content

Commit 40c3c87

Browse files
authored
Merge pull request #1144 from gaffney2010/master
Implemented GraaskampKatzen strategy from Axelrod's Second (k60r)
2 parents 3ea8330 + 806b13f commit 40c3c87

File tree

4 files changed

+119
-11
lines changed

4 files changed

+119
-11
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, WmAdams)
12+
Kluepfel, Borufsen, Cave, WmAdams, GraaskampKatzen)
1313
from .backstabber import BackStabber, DoubleCrosser
1414
from .better_and_better import BetterAndBetter
1515
from .bush_mosteller import BushMosteller
@@ -170,6 +170,7 @@
170170
GoByMajority40,
171171
GoByMajority5,
172172
Golden,
173+
GraaskampKatzen,
173174
Gradual,
174175
GradualKiller,
175176
Grofman,

axelrod/strategies/axelrod_second.py

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def strategy(self, opponent: Player) -> Action:
203203
# Play TFT
204204
return opponent.history[-1]
205205

206+
206207
class Tranquilizer(Player):
207208

208209
"""
@@ -468,6 +469,7 @@ def strategy(self, opponent: Player) -> Action:
468469
return C
469470
return D
470471

472+
471473
class Kluepfel(Player):
472474
"""
473475
Strategy submitted to Axelrod's second tournament by Charles Kluepfel
@@ -549,7 +551,7 @@ def strategy(self, opponent: Player) -> Action:
549551

550552
if one_move_ago == two_moves_ago and two_moves_ago == three_moves_ago:
551553
return one_move_ago
552-
554+
553555
r = random.random() # Everything following is stochastic
554556
if one_move_ago == two_moves_ago:
555557
if r < 0.9:
@@ -567,6 +569,7 @@ def strategy(self, opponent: Player) -> Action:
567569
else:
568570
return one_move_ago.flip()
569571

572+
570573
class Borufsen(Player):
571574
"""
572575
Strategy submitted to Axelrod's second tournament by Otto Borufsen
@@ -588,8 +591,8 @@ class Borufsen(Player):
588591
cooperate. (Doesn't block third rule.)
589592
3. Otherwise, do tit-for-tat.
590593
591-
Start in normal mode, but every 25 turns starting with the 27th turn,
592-
re-evaluate the mode. Enter defect mode if any of the following
594+
Start in normal mode, but every 25 turns starting with the 27th turn,
595+
re-evaluate the mode. Enter defect mode if any of the following
593596
conditions hold:
594597
595598
- Detected random: Opponent cooperated 7-18 times since last mode
@@ -689,7 +692,7 @@ def strategy(self, opponent: Player) -> Action:
689692
return D
690693
else:
691694
assert self.mode == "Normal"
692-
695+
693696
# Look for mutual defects
694697
if self.history[-1] == D and opponent.history[-1] == D:
695698
self.mutual_defect_streak += 1
@@ -699,7 +702,7 @@ def strategy(self, opponent: Player) -> Action:
699702
self.mutual_defect_streak = 0
700703
self.echo_streak = 0 # Reset both streaks.
701704
return self.try_return(C)
702-
705+
703706
# Look for echoes
704707
# Fortran code defaults two turns back to C if only second turn
705708
my_two_back, opp_two_back = C, C
@@ -719,6 +722,7 @@ def strategy(self, opponent: Player) -> Action:
719722
# Tit-for-tat
720723
return self.try_return(opponent.history[-1])
721724

725+
722726
class Cave(Player):
723727
"""
724728
Strategy submitted to Axelrod's second tournament by Rob Cave (K49R), and
@@ -756,13 +760,15 @@ def strategy(self, opponent: Player) -> Action:
756760
if turn == 1: return C
757761

758762
number_defects = opponent.defections
759-
# Size of numerator is smaller than denomator -- How it was in the Fortran.
760763
perc_defects = number_defects / turn
761764

762765
# If overly defect or appears random
763-
if turn > 39 and perc_defects > 0.39: return D
764-
if turn > 29 and perc_defects > 0.65: return D
765-
if turn > 19 and perc_defects > 0.79: return D
766+
if turn > 39 and perc_defects > 0.39:
767+
return D
768+
if turn > 29 and perc_defects > 0.65:
769+
return D
770+
if turn > 19 and perc_defects > 0.79:
771+
return D
766772

767773
if opponent.history[-1] == D:
768774
if number_defects > 17:
@@ -772,6 +778,7 @@ def strategy(self, opponent: Player) -> Action:
772778
else:
773779
return C
774780

781+
775782
class WmAdams(Player):
776783
"""
777784
Strategy submitted to Axelrod's second tournament by William Adams (K44R),
@@ -809,3 +816,67 @@ def strategy(self, opponent: Player) -> Action:
809816
if number_defects > 9 and opponent.history[-1] == D:
810817
return random_choice((0.5) ** (number_defects - 9))
811818
return C
819+
820+
class GraaskampKatzen(Player):
821+
"""
822+
Strategy submitted to Axelrod's second tournament by Jim Graaskamp and Ken
823+
Katzen (K60R), and came in sixth in that tournament.
824+
825+
Play Tit-for-Tat at first, and track own score. At select checkpoints,
826+
check for a high score. Switch to Default Mode if:
827+
828+
- On move 11, score < 23
829+
- On move 21, score < 53
830+
- On move 31, score < 83
831+
- On move 41, score < 113
832+
- On move 51, score < 143
833+
- On move 101, score < 293
834+
835+
Once in Defect Mode, defect forever.
836+
837+
Names:
838+
839+
- GraaskampKatzen: [Axelrod1980b]_
840+
"""
841+
842+
name = "GraaskampKatzen"
843+
classifier = {
844+
'memory_depth': float('inf'),
845+
'stochastic': False,
846+
'makes_use_of': set(['game']),
847+
'long_run_time': False,
848+
'inspects_source': False,
849+
'manipulates_source': False,
850+
'manipulates_state': False
851+
}
852+
853+
def __init__(self):
854+
super().__init__()
855+
self.own_score = 0
856+
self.mode = "Normal"
857+
858+
def update_score(self, opponent: Player):
859+
game = self.match_attributes["game"]
860+
last_round = (self.history[-1], opponent.history[-1])
861+
self.own_score += game.score(last_round)[0]
862+
863+
def strategy(self, opponent: Player) -> Action:
864+
if self.mode == "Defect":
865+
return D
866+
867+
turn = len(self.history) + 1
868+
if turn == 1:
869+
return C
870+
871+
self.update_score(opponent)
872+
873+
if turn == 11 and self.own_score < 23 or \
874+
turn == 21 and self.own_score < 53 or \
875+
turn == 31 and self.own_score < 83 or \
876+
turn == 41 and self.own_score < 113 or \
877+
turn == 51 and self.own_score < 143 or \
878+
turn == 101 and self.own_score < 293:
879+
self.mode = "Defect"
880+
return D
881+
882+
return opponent.history[-1] # Tit-for-Tat

axelrod/tests/strategies/test_axelrod_second.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,39 @@ def test_strategy(self):
585585
(C, D), (D, D), (C, D), (D, D), (C, C)]
586586
actions += [(C, C)] * 99
587587
self.versus_test(changed_man, expected_actions=actions, seed=1)
588+
589+
class TestGraaskampKatzen(TestPlayer):
590+
name = "GraaskampKatzen"
591+
player = axelrod.GraaskampKatzen
592+
expected_classifier = {
593+
'memory_depth': float('inf'),
594+
'stochastic': False,
595+
'makes_use_of': set(["game"]),
596+
'long_run_time': False,
597+
'inspects_source': False,
598+
'manipulates_source': False,
599+
'manipulates_state': False
600+
}
601+
602+
def test_strategy(self):
603+
actions = [(C, C)] * 100 # Cooperate forever
604+
self.versus_test(axelrod.Cooperator(), expected_actions=actions)
605+
606+
# GK does not great against
607+
opponent_actions = [C, D, D] * 100
608+
GK_Foil = axelrod.MockPlayer(actions=opponent_actions)
609+
actions = [(C, C), (C, D), (D, D)]
610+
actions += [(D, C), (C, D), (D, D)] * 2
611+
actions += [(D, C)]
612+
actions += [(D, D), (D, D), (D, C)] * 20 # Defect here on
613+
self.versus_test(GK_Foil, expected_actions=actions)
614+
615+
# Fail on second checkpoint
616+
opponent_actions = [C] * 10 + [C, D, D] * 100
617+
Delayed_GK_Foil = axelrod.MockPlayer(actions=opponent_actions)
618+
actions = [(C, C)] * 10
619+
actions += [(C, C), (C, D), (D, D)]
620+
actions += [(D, C), (C, D), (D, D)] * 2
621+
actions += [(D, C)]
622+
actions += [(D, D), (D, D), (D, C)] * 20 # Defect here on
623+
self.versus_test(Delayed_GK_Foil, expected_actions=actions)

docs/reference/overview_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ repository.
130130
"K57R_", "Rudy Nydegger", "Not Implemented"
131131
"K58R_", "Glen Rowsam", "Not Implemented"
132132
"K59R_", "Leslie Downing", "Not Implemented"
133-
"K60R_", "Jim Graaskamp and Ken Katzen", "Not Implemented"
133+
"K60R_", "Jim Graaskamp and Ken Katzen", ":class:`GraaskampKatzen <axelrod.strategies.axelrod_second.GraaskampKatzen>`"
134134
"K61R_", "Danny C Champion", ":class:`Champion <axelrod.strategies.axelrod_second.Champion>`"
135135
"K62R_", "Howard R Hollander", "Not Implemented"
136136
"K63R_", "George Duisman", "Not Implemented"

0 commit comments

Comments
 (0)