From 561830bba112610eb6bb16b67afd1aec5e861992 Mon Sep 17 00:00:00 2001 From: Ben McGUffog Date: Thu, 1 Feb 2024 12:07:09 +1100 Subject: [PATCH 01/11] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 870a5e2be..9751228eb 100644 --- a/README.rst +++ b/README.rst @@ -79,7 +79,7 @@ The simplest way to install is:: To install from source:: - $ git clone https://github.com/Axelrod-Python/Axelrod.git + $ git clone https://github.com/benjjo/Axelrod.git $ cd Axelrod $ python setup.py install From f2be0b5e314fb2c60226a1beb0c7a2224e3ebfd8 Mon Sep 17 00:00:00 2001 From: benjjo Date: Thu, 1 Feb 2024 15:49:09 +1100 Subject: [PATCH 02/11] added modalTFT --- axelrod/strategies/titfortat.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index e98a8aadf..4f9f58741 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -1,5 +1,6 @@ from axelrod.action import Action, actions_to_str from axelrod.player import Player +import statistics from axelrod.strategy_transformers import ( FinalTransformer, TrackHistoryTransformer, @@ -945,9 +946,36 @@ def strategy(self, opponent): if not opponent.history: # Make sure we cooperate first turn return C - # BBE modification + # BBE modification if opponent.history[-1] == C: # Cooperate with 0.9 return self._random.random_choice(0.9) # Else TFT. Opponent played D, so play D in return. return D + + +class ModalTFT(Player): + """ + A player starts by cooperating and then analyses the history of the opponent. From this information it will + respond with the mode of the opponents historical response. + """ + + # These are various properties for the strategy + name = "Modal TFT" + classifier = { + "memory_depth": 1, # Four-Vector = (1.,0.,1.,0.) + "stochastic": False, + "long_run_time": False, + "inspects_source": False, + "manipulates_source": False, + "manipulates_state": False, + } + + def strategy(self, opponent: Player) -> Action: + """This is the actual strategy""" + # First move + if not self.history: + return C + # React to the opponent's historical moves + return statistics.mode(self.history) + From 6c3be2129b1ba39d2ef2857b70b9565ab8a25f1b Mon Sep 17 00:00:00 2001 From: benjjo Date: Thu, 1 Feb 2024 15:51:57 +1100 Subject: [PATCH 03/11] words --- axelrod/strategies/titfortat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index 4f9f58741..b6e558737 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -957,7 +957,7 @@ def strategy(self, opponent): class ModalTFT(Player): """ A player starts by cooperating and then analyses the history of the opponent. From this information it will - respond with the mode of the opponents historical response. + respond with the mode of the opponents historical responses. """ # These are various properties for the strategy From e9d80164061952e660c979374dad3ff224ee1344 Mon Sep 17 00:00:00 2001 From: benjjo Date: Thu, 1 Feb 2024 15:58:34 +1100 Subject: [PATCH 04/11] _strategies updated with new ModalTFT --- axelrod/strategies/_strategies.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 92dafc523..133cd5a44 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -271,6 +271,7 @@ TitFor2Tats, TitForTat, TwoTitsForTat, + ModalTFT, ) from .verybad import VeryBad from .worse_and_worse import ( @@ -409,6 +410,7 @@ MEM2, MathConstantHunter, Michaelos, + ModalTFT, NTitsForMTats, NaiveProber, Negation, From 627562ac9cd061dd74fc6cb9b97f4ab6afd94311 Mon Sep 17 00:00:00 2001 From: benjjo Date: Thu, 1 Feb 2024 16:38:11 +1100 Subject: [PATCH 05/11] updated ModalTFT to use opponent.history. --- axelrod/strategies/titfortat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index b6e558737..4dbb2a621 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -977,5 +977,5 @@ def strategy(self, opponent: Player) -> Action: if not self.history: return C # React to the opponent's historical moves - return statistics.mode(self.history) + return statistics.mode(opponent.history) From 11262602fd126764dfa7ed326a300dd38ace4032 Mon Sep 17 00:00:00 2001 From: benjjo Date: Thu, 1 Feb 2024 16:43:35 +1100 Subject: [PATCH 06/11] updated memory_depth of ModalTFT to infinite. --- axelrod/strategies/titfortat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index 4dbb2a621..1e2fe82c1 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -963,7 +963,7 @@ class ModalTFT(Player): # These are various properties for the strategy name = "Modal TFT" classifier = { - "memory_depth": 1, # Four-Vector = (1.,0.,1.,0.) + "memory_depth": float("inf"), "stochastic": False, "long_run_time": False, "inspects_source": False, From e982c0b8480e33757963c8b70a5d81821371b9b1 Mon Sep 17 00:00:00 2001 From: benjjo Date: Thu, 1 Feb 2024 16:49:44 +1100 Subject: [PATCH 07/11] moved ModalTFT to alphabetical order --- axelrod/strategies/_strategies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 133cd5a44..02b90fe65 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -260,6 +260,7 @@ HardTitFor2Tats, HardTitForTat, Michaelos, + ModalTFT, NTitsForMTats, OmegaTFT, OriginalGradual, @@ -271,7 +272,6 @@ TitFor2Tats, TitForTat, TwoTitsForTat, - ModalTFT, ) from .verybad import VeryBad from .worse_and_worse import ( From 22189f3c58dfba338ad2f450ceca9c891bc360fe Mon Sep 17 00:00:00 2001 From: benjjo Date: Wed, 7 Feb 2024 15:34:55 +1100 Subject: [PATCH 08/11] Tests added and passed. Strategy updated to return a C when the opponent issued a C in the last round. --- axelrod/strategies/titfortat.py | 10 +++++++--- axelrod/tests/strategies/test_titfortat.py | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index 1e2fe82c1..5e2c14bf3 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -956,8 +956,9 @@ def strategy(self, opponent): class ModalTFT(Player): """ - A player starts by cooperating and then analyses the history of the opponent. From this information it will - respond with the mode of the opponents historical responses. + A player starts by cooperating and then analyses the history of the opponent. If the opponent Cooperated in the + last round, they are immediately returned with a Cooperation. If the opponent chose to Defect in the previous round, + then this strategy will return with the mode of the previous opponent responses. """ # These are various properties for the strategy @@ -977,5 +978,8 @@ def strategy(self, opponent: Player) -> Action: if not self.history: return C # React to the opponent's historical moves - return statistics.mode(opponent.history) + print(statistics.mode(opponent.history)) + return C if opponent.history[-1] == C else statistics.mode(opponent.history) + + diff --git a/axelrod/tests/strategies/test_titfortat.py b/axelrod/tests/strategies/test_titfortat.py index 09d82b80f..5c9c7f5b1 100644 --- a/axelrod/tests/strategies/test_titfortat.py +++ b/axelrod/tests/strategies/test_titfortat.py @@ -1341,3 +1341,23 @@ def test_vs_cooperator2(self): def test_vs_defector(self): actions = [(C, D), (D, D), (D, D), (D, D), (D, D)] self.versus_test(axl.Defector(), expected_actions=actions) + + +class TestModalTFT(TestPlayer): + name = "Modal TFT" + player = axl.ModalTFT + expected_classifier = { + "memory_depth": float("inf"), + "stochastic": False, + "makes_use_of": set(), + "inspects_source": False, + "manipulates_source": False, + "manipulates_state": False, + } + + def test_strategy(self): + opponent = axl.MockPlayer(actions=[C, C, D, D, D, D, C, D]) + actions = [(C, C), (C, C), (C, D), (C, D), (C, D), (D, D), (D, C), (C, D), (D, C)] + self.versus_test(opponent, expected_actions=actions) + + From 9aff1bb0fa9cf67861c5d26487f9b090ee9da236 Mon Sep 17 00:00:00 2001 From: benjjo Date: Wed, 7 Feb 2024 17:11:12 +1100 Subject: [PATCH 09/11] Applied black formatting. --- axelrod/strategies/titfortat.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index 5e2c14bf3..bb7efae83 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -873,7 +873,7 @@ def strategy(self, opponent: Player) -> Action: class RandomTitForTat(Player): """ A player starts by cooperating and then follows by copying its - opponent (tit for tat style). From then on the player + opponent (tit-for-tat style). From then on the player will switch between copying its opponent and randomly responding every other iteration. @@ -981,5 +981,3 @@ def strategy(self, opponent: Player) -> Action: print(statistics.mode(opponent.history)) return C if opponent.history[-1] == C else statistics.mode(opponent.history) - - From 3dfc1bf5da1b5db3744f82c25274964adf019550 Mon Sep 17 00:00:00 2001 From: benjjo Date: Wed, 7 Feb 2024 17:15:35 +1100 Subject: [PATCH 10/11] Removed test print command. Reformatted to match the style of the other classes. --- axelrod/strategies/titfortat.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/axelrod/strategies/titfortat.py b/axelrod/strategies/titfortat.py index bb7efae83..3d611eba3 100644 --- a/axelrod/strategies/titfortat.py +++ b/axelrod/strategies/titfortat.py @@ -957,7 +957,7 @@ def strategy(self, opponent): class ModalTFT(Player): """ A player starts by cooperating and then analyses the history of the opponent. If the opponent Cooperated in the - last round, they are immediately returned with a Cooperation. If the opponent chose to Defect in the previous round, + last round, they are returned with a Cooperation. If the opponent chose to Defect in the previous round, then this strategy will return with the mode of the previous opponent responses. """ @@ -978,6 +978,9 @@ def strategy(self, opponent: Player) -> Action: if not self.history: return C # React to the opponent's historical moves - print(statistics.mode(opponent.history)) - return C if opponent.history[-1] == C else statistics.mode(opponent.history) + if opponent.history[-1] == C: + return C + else: + # returns with the mode of the opponent's history. + return statistics.mode(opponent.history) From 69bba5a5c39bc1610ab411fa269baec6a12714c0 Mon Sep 17 00:00:00 2001 From: benjjo Date: Wed, 7 Feb 2024 18:29:03 +1100 Subject: [PATCH 11/11] Modal Defector added to the library. Tests passed. --- axelrod/strategies/_strategies.py | 3 ++- axelrod/strategies/defector.py | 33 +++++++++++++++++++++++ axelrod/tests/strategies/test_defector.py | 18 +++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 02b90fe65..cad9da264 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -87,7 +87,7 @@ from .cycler import Cycler, EvolvableCycler # pylint: disable=unused-import from .darwin import Darwin from .dbs import DBS -from .defector import Defector, TrickyDefector +from .defector import Defector, TrickyDefector, ModalDefector from .doubler import Doubler from .finite_state_machines import ( TF1, @@ -410,6 +410,7 @@ MEM2, MathConstantHunter, Michaelos, + ModalDefector, ModalTFT, NTitsForMTats, NaiveProber, diff --git a/axelrod/strategies/defector.py b/axelrod/strategies/defector.py index f52637ba0..bc1012126 100644 --- a/axelrod/strategies/defector.py +++ b/axelrod/strategies/defector.py @@ -1,5 +1,6 @@ from axelrod.action import Action from axelrod.player import Player +import statistics C, D = Action.C, Action.D @@ -61,3 +62,35 @@ def strategy(self, opponent: Player) -> Action: ): return C return D + + +class ModalDefector(Player): + """ + A player starts by Defecting and then analyses the history of the opponent. If the opponent Cooperated in the + last round, they are returned with a Defection. If the opponent chose to Defect in the previous round, + then this strategy will return with the mode of the previous opponent responses. + """ + + # These are various properties for the strategy + name = "Modal Defector" + classifier = { + "memory_depth": float("inf"), + "stochastic": False, + "long_run_time": False, + "inspects_source": False, + "manipulates_source": False, + "manipulates_state": False, + } + + def strategy(self, opponent: Player) -> Action: + """This is the actual strategy""" + # First move + if not self.history: + return D + # React to the opponent's historical moves + if opponent.history[-1] == C: + return D + else: + # returns with the mode of the opponent's history. + return statistics.mode(opponent.history) + diff --git a/axelrod/tests/strategies/test_defector.py b/axelrod/tests/strategies/test_defector.py index d9dffa48d..227bc2990 100644 --- a/axelrod/tests/strategies/test_defector.py +++ b/axelrod/tests/strategies/test_defector.py @@ -61,3 +61,21 @@ def test_defects_if_opponent_last_three_are_not_D(self): self.versus_test( axl.MockPlayer(actions=opponent_actions), expected_actions=actions ) + + +class TestModalDefector(TestPlayer): + name = "Modal Defector" + player = axl.ModalDefector + expected_classifier = { + "memory_depth": float("inf"), + "stochastic": False, + "makes_use_of": set(), + "inspects_source": False, + "manipulates_source": False, + "manipulates_state": False, + } + + def test_strategy(self): + opponent = axl.MockPlayer(actions=[C, C, D, D, D, D, C, D]) + actions = [(D, C), (D, C), (D, D), (C, D), (C, D), (D, D), (D, C), (D, D), (D, C)] + self.versus_test(opponent, expected_actions=actions)