-
Notifications
You must be signed in to change notification settings - Fork 267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ModalTFT, ModalDefector strategies - Ben McGuffog #1433
base: dev
Are you sure you want to change the base?
Changes from all commits
561830b
f2be0b5
f6f823c
6c3be21
e9d8016
627562a
1126260
e982c0b
22189f3
9aff1bb
3dfc1bf
69bba5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this comment/line is from our contributing guidelines. You can remove it. |
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than use the statistics library, the history class already keeps a running count of C and D, so you can do something like |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
|
@@ -872,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. | ||
|
||
|
@@ -945,9 +946,41 @@ 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. If the opponent Cooperated in the | ||
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. | ||
""" | ||
|
||
# These are various properties for the strategy | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||
name = "Modal TFT" | ||
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 C | ||
# React to the opponent's historical moves | ||
if opponent.history[-1] == C: | ||
return C | ||
else: | ||
# returns with the mode of the opponent's history. | ||
return statistics.mode(opponent.history) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment re: statistics.mode |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to add a few more tests that single out the specific behaviors like the first move and that the mode works for both C and D. If possible try to use a real strategy like Alternator rather than mock players, but mocks are ok if it's hard to target a particular case. |
||
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll want to keep this as is for others.