From a64348066ad6464dfdd9cbad1a3e5b12a1f08b12 Mon Sep 17 00:00:00 2001 From: "T.J. Gaffney" Date: Tue, 21 Nov 2017 05:04:42 -0500 Subject: [PATCH 1/4] Implemented WmAdams strategy (k44r from Axelrod's second) --- axelrod/strategies/_strategies.py | 3 +- axelrod/strategies/axelrod_second.py | 37 +++++++++++++++++++ .../tests/strategies/test_axelrod_second.py | 36 ++++++++++++++++++ docs/reference/overview_of_strategies.rst | 2 +- .../advanced/classification_of_strategies.rst | 2 +- 5 files changed, 77 insertions(+), 3 deletions(-) diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index c0b0abd46..e4faca977 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -9,7 +9,7 @@ UnnamedStrategy, SteinAndRapoport, TidemanAndChieruzzi) from .axelrod_second import ( Champion, Eatherley, Tester, Gladstein, Tranquilizer, MoreGrofman, - Kluepfel, Borufsen, Cave) + Kluepfel, Borufsen, Cave, WmAdams) from .backstabber import BackStabber, DoubleCrosser from .better_and_better import BetterAndBetter from .bush_mosteller import BushMosteller @@ -274,6 +274,7 @@ Winner21, WinShiftLoseStay, WinStayLoseShift, + WmAdams, WorseAndWorse, WorseAndWorse2, WorseAndWorse3, diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index ed06e9348..92fcd1541 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -771,3 +771,40 @@ def strategy(self, opponent: Player) -> Action: return random_choice(0.5) else: return C + +class WmAdams(Player): + """ + Strategy submitted to Axelrod's second tournament by William Adams (K49R), + and came in fifth in that tournament. + + Count the number of opponent defects after their first move, call + `c_defect`. Defect if c_defect equals 4, 7, or 9. If c_defect > 9, + then defect immediately after opponent defect with probability = + (0.5)^(c_defect-1). Otherwise cooperate. + + Names: + + - WmAdams: [Axelrod1980b]_ + """ + + name = "WmAdams" + classifier = { + 'memory_depth': float('inf'), + 'stochastic': True, + 'makes_use_of': set(), + 'long_run_time': False, + 'inspects_source': False, + 'manipulates_source': False, + 'manipulates_state': False + } + + def strategy(self, opponent: Player) -> Action: + if len(self.history) <=1: + return C + did_d = np.vectorize(lambda action: float(action == D)) + number_defects = np.sum(did_d(opponent.history[1:])) + + if number_defects == 4 or number_defects == 7 or number_defects == 9: return D + if number_defects > 9 and opponent.history[-1] == D: + return random_choice((0.5)**(number_defects-9)) + return C diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 286359506..9e5a21d67 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -542,3 +542,39 @@ def test_strategy(self): actions += [(D, C), (C, D), (D, C)] # 17 D have come, so tit for tat for a while actions += [(D, D), (D, C)] * 100 # Random finally detected self.versus_test(axelrod.Alternator(), expected_actions=actions) + +class TestCave(TestPlayer): + name = "WmAdams" + player = axelrod.WmAdams + expected_classifier = { + 'memory_depth': float('inf'), + 'stochastic': True, + 'makes_use_of': set(), + 'long_run_time': False, + 'inspects_source': False, + 'manipulates_source': False, + 'manipulates_state': False + } + + def test_strategy(self): + actions = [(C, C)] * 100 # Cooperate forever + self.versus_test(axelrod.Cooperator(), expected_actions=actions) + + # Will ignore the first four defects + opponent_actions = [D] * 4 + [C] * 100 + defect_four = axelrod.MockPlayer(actions=opponent_actions) + actions = [(C, D)] * 4 + [(C, C)] * 100 + self.versus_test(defect_four, expected_actions=actions) + + actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (D, D)] + self.versus_test(axelrod.Defector(), expected_actions=actions, seed=1) + actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (C, D), (D, D), (D, D)] + self.versus_test(axelrod.Defector(), expected_actions=actions, seed=2) + + # After responding to the 11th D (counted as 10 D), just start cooperating + opponent_actions = [D] * 11 + [C] * 100 + changed_man = axelrod.MockPlayer(actions=opponent_actions) + actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, C)] + actions += [(C,C)] * 99 + self.versus_test(changed_man, expected_actions=actions, seed=1) + diff --git a/docs/reference/overview_of_strategies.rst b/docs/reference/overview_of_strategies.rst index 78e2e1287..8d49b7a3a 100644 --- a/docs/reference/overview_of_strategies.rst +++ b/docs/reference/overview_of_strategies.rst @@ -114,7 +114,7 @@ repository. "K41R_", "Herb Weiner", "Not Implemented" "K42R_", "Otto Borufsen", ":class:`Borufsen `" "K43R_", "R D Anderson", "Not Implemented" - "K44R_", "William Adams", "Not Implemented" + "K44R_", "William Adams", ":class:`WmAdams `" "K45R_", "Michael F McGurrin", "Not Implemented" "K46R_", "Graham J Eatherley", ":class:`Eatherley `" "K47R_", "Richard Hufford", "Not Implemented" diff --git a/docs/tutorials/advanced/classification_of_strategies.rst b/docs/tutorials/advanced/classification_of_strategies.rst index 33dd7bb77..79789e31f 100644 --- a/docs/tutorials/advanced/classification_of_strategies.rst +++ b/docs/tutorials/advanced/classification_of_strategies.rst @@ -47,7 +47,7 @@ strategies:: ... } >>> strategies = axl.filtered_strategies(filterset) >>> len(strategies) - 77 + 78 Or, to find out how many strategies only use 1 turn worth of memory to make a decision:: From 90c529bf13551b1d15a1cee33d8fa57c5518051b Mon Sep 17 00:00:00 2001 From: "T.J. Gaffney" Date: Sat, 25 Nov 2017 16:00:32 -0500 Subject: [PATCH 2/4] Fixed formatting issues mentioned in PR --- axelrod/strategies/axelrod_second.py | 21 +++++++++---------- .../tests/strategies/test_axelrod_second.py | 11 +++++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 92fcd1541..216176958 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -755,9 +755,9 @@ def strategy(self, opponent: Player) -> Action: turn = len(self.history) + 1 if turn == 1: return C - did_d = np.vectorize(lambda action: float(action == D)) - number_defects = np.sum(did_d(opponent.history)) - perc_defects = number_defects / turn # Size of numerator is smaller than denomator -- How it was in the Fortran. + number_defects = opponent.defections + # Size of numerator is smaller than denomator -- How it was in the Fortran. + perc_defects = number_defects / turn # If overly defect or appears random if turn > 39 and perc_defects > 0.39: return D @@ -774,12 +774,12 @@ def strategy(self, opponent: Player) -> Action: class WmAdams(Player): """ - Strategy submitted to Axelrod's second tournament by William Adams (K49R), + Strategy submitted to Axelrod's second tournament by William Adams (K44R), and came in fifth in that tournament. - Count the number of opponent defects after their first move, call + Count the number of opponent defections after their first move, call `c_defect`. Defect if c_defect equals 4, 7, or 9. If c_defect > 9, - then defect immediately after opponent defect with probability = + then defect immediately after opponent defects with probability = (0.5)^(c_defect-1). Otherwise cooperate. Names: @@ -799,12 +799,11 @@ class WmAdams(Player): } def strategy(self, opponent: Player) -> Action: - if len(self.history) <=1: + if len(self.history) <= 1: return C - did_d = np.vectorize(lambda action: float(action == D)) - number_defects = np.sum(did_d(opponent.history[1:])) + number_defects = opponent.defections - if number_defects == 4 or number_defects == 7 or number_defects == 9: return D + if number_defects in [4, 7, 9]: return D if number_defects > 9 and opponent.history[-1] == D: - return random_choice((0.5)**(number_defects-9)) + return random_choice((0.5) ** (number_defects - 9)) return C diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index c41c3207f..54246d93d 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -563,14 +563,19 @@ def test_strategy(self): actions = [(C, D)] * 4 + [(C, C)] * 100 self.versus_test(defect_four, expected_actions=actions) - actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (D, D)] + actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), + (C, D), (D, D), (C, D), (D, D), (C, D), (D, D), (D, D), + (D, D), (D, D)] self.versus_test(axelrod.Defector(), expected_actions=actions, seed=1) - actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (C, D), (D, D), (D, D)] + actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), + (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (C, D), + (D, D), (D, D)] self.versus_test(axelrod.Defector(), expected_actions=actions, seed=2) # After responding to the 11th D (counted as 10 D), just start cooperating opponent_actions = [D] * 11 + [C] * 100 changed_man = axelrod.MockPlayer(actions=opponent_actions) - actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, C)] + actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), + (C, D), (D, D), (C, D), (D, D), (C, C)] actions += [(C,C)] * 99 self.versus_test(changed_man, expected_actions=actions, seed=1) From da80753bb60d5e4035bf33f87dcbe2093bbef63f Mon Sep 17 00:00:00 2001 From: "T.J. Gaffney" Date: Sat, 25 Nov 2017 16:31:21 -0500 Subject: [PATCH 3/4] Minor formatting fixes. --- axelrod/strategies/axelrod_second.py | 4 +- .../tests/strategies/test_axelrod_second.py | 56 ++++++++++--------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 216176958..1328cec63 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -777,9 +777,9 @@ class WmAdams(Player): Strategy submitted to Axelrod's second tournament by William Adams (K44R), and came in fifth in that tournament. - Count the number of opponent defections after their first move, call + Count the number of opponent defections after their first move, call `c_defect`. Defect if c_defect equals 4, 7, or 9. If c_defect > 9, - then defect immediately after opponent defects with probability = + then defect immediately after opponent defects with probability = (0.5)^(c_defect-1). Otherwise cooperate. Names: diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 54246d93d..aa73106bc 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -442,14 +442,15 @@ def test_strategy(self): # Now we have to test the detect-random logic, which doesn't pick up # until after 26 turns. So we need a big sample. - actions = [(C, D), (D, D), (D, D), (D, D), (D, D), (D, C), (C, C), (C, D), - (C, C), (D, D), (D, C), (C, C), (C, D), (D, D), (C, D), (D, D), - (D, C), (C, C), (D, C), (C, C), (C, D), (D, D), (D, C), (C, D), - (D, C), (C, C), (C, D), + actions = [(C, D), (D, D), (D, D), (D, D), (D, D), (D, C), (C, C), + (C, D), (C, C), (D, D), (D, C), (C, C), (C, D), (D, D), + (C, D), (D, D), (D, C), (C, C), (D, C), (C, C), (C, D), + (D, D), (D, C), (C, D), (D, C), (C, C), (C, D), # Success detect random opponent for remaining turns. - (D, D),(D, D),(D, D),(D, C),(D, D),(D, C),(D, D),(D, C),(D, D), - (D, C),(D, C),(D, D),(D, D),(D, C),(D, C),(D, C),(D, C),(D, D), - (D, C),(D, C),(D, C),(D, C),(D, D)] + (D, D), (D, D), (D, D), (D, C), (D, D), (D, C), (D, D), + (D, C), (D, D), (D, C), (D, C), (D, D), (D, D), (D, C), + (D, C), (D, C), (D, C), (D, D), (D, C), (D, C), (D, C), + (D, C), (D, D)] self.versus_test(axelrod.Random(0.5), expected_actions=actions, seed=10) class TestBorufsen(TestPlayer): @@ -475,16 +476,21 @@ def test_strategy(self): self.versus_test(axelrod.Defector(), expected_actions=actions) # Alternates with additional coop, every sixth turn - # Won't be labeled as random, since 2/3 of opponent's C follow player's C - # `flip_next_defect` will get set on the sixth turn, which changes the seventh action + # Won't be labeled as random, since 2/3 of opponent's C follow + # player's C + # `flip_next_defect` will get set on the sixth turn, which changes the + # seventh action # Note that the first two turns of each period of six aren't - # marked as echoes, and the third isn't marked that way until the fourth turn. + # marked as echoes, and the third isn't marked that way until the + # fourth turn. actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (C, D)] * 20 self.versus_test(axelrod.Alternator(), expected_actions=actions) # Basically does tit-for-tat against Win-Shift, Lose-Stay D - # After 26 turns, will detect random since half of opponent's C follow Cs - # Coming out of it, there will be new pattern. Then random is detected again. + # After 26 turns, will detect random since half of opponent's C follow + # Cs + # Coming out of it, there will be new pattern. Then random is detected + # again. actions = [(C, D), (D, C), (C, C)] * 8 + \ [(C, D), (D, C)] + [(D, C)] * 25 + \ [(D, C)] + [(C, C), (C, D), (D, C)] * 8 + \ @@ -505,7 +511,7 @@ class TestCave(TestPlayer): } def test_strategy(self): - actions = [(C, C)] * 100 + actions = [(C, C)] * 100 self.versus_test(axelrod.Cooperator(), expected_actions=actions) # It will take until turn 18 to respond decide to repond D->D @@ -531,16 +537,16 @@ def test_strategy(self): #Here it will take until turn 40 to detect random and defect actions = [(C, C)] - actions += [(C, D), (D, C), (C, D), (D, C), (C, D), (C, C), (C, D), - (C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C), - (C, D), (C, C), (C, D), (D, C), (C, D), (D, C), (C, D), - (D, C), (C, D), (C, C), (C, D), (C, C), (C, D), (C, C), - (C, D), (D, C), (C, D), (D, C), (C, D), (D, C), (C, D)] #Randomly choose + actions += [(C, D), (D, C), (C, D), (D, C), (C, D), (C, C), (C, D), + (C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C), + (C, D), (C, C), (C, D), (D, C), (C, D), (D, C), (C, D), + (D, C), (C, D), (C, C), (C, D), (C, C), (C, D), (C, C), + (C, D), (D, C), (C, D), (D, C), (C, D), (D, C), (C, D)] #Randomly choose actions += [(D, C), (C, D), (D, C)] # 17 D have come, so tit for tat for a while actions += [(D, D), (D, C)] * 100 # Random finally detected self.versus_test(axelrod.Alternator(), expected_actions=actions, seed=2) -class TestCave(TestPlayer): +class TestWmAdams(TestPlayer): name = "WmAdams" player = axelrod.WmAdams expected_classifier = { @@ -564,18 +570,18 @@ def test_strategy(self): self.versus_test(defect_four, expected_actions=actions) actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), - (C, D), (D, D), (C, D), (D, D), (C, D), (D, D), (D, D), - (D, D), (D, D)] + (C, D), (D, D), (C, D), (D, D), (C, D), (D, D), (D, D), + (D, D), (D, D)] self.versus_test(axelrod.Defector(), expected_actions=actions, seed=1) actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), - (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (C, D), - (D, D), (D, D)] + (C, D), (D, D), (C, D), (D, D), (D, D), (D, D), (C, D), + (D, D), (D, D)] self.versus_test(axelrod.Defector(), expected_actions=actions, seed=2) # After responding to the 11th D (counted as 10 D), just start cooperating opponent_actions = [D] * 11 + [C] * 100 changed_man = axelrod.MockPlayer(actions=opponent_actions) actions = [(C, D), (C, D), (C, D), (C, D), (C, D), (D, D), (C, D), - (C, D), (D, D), (C, D), (D, D), (C, C)] - actions += [(C,C)] * 99 + (C, D), (D, D), (C, D), (D, D), (C, C)] + actions += [(C, C)] * 99 self.versus_test(changed_man, expected_actions=actions, seed=1) From dd91f0a27cb3aec6d110bd4e6435ac1c80331d40 Mon Sep 17 00:00:00 2001 From: "T.J. Gaffney" Date: Sat, 25 Nov 2017 16:57:37 -0500 Subject: [PATCH 4/4] Subtracted first defect. --- axelrod/strategies/axelrod_second.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 1328cec63..3ea80b7b9 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -802,6 +802,8 @@ def strategy(self, opponent: Player) -> Action: if len(self.history) <= 1: return C number_defects = opponent.defections + if opponent.history[0] == D: + number_defects -= 1 if number_defects in [4, 7, 9]: return D if number_defects > 9 and opponent.history[-1] == D: