-
Notifications
You must be signed in to change notification settings - Fork 264
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9838f84
commit ee4c454
Showing
4 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
from axelrod.action import Action, actions_to_str | ||
from axelrod.player import Player | ||
from axelrod.strategy_transformers import ( | ||
FinalTransformer, | ||
TrackHistoryTransformer, | ||
) | ||
|
||
C, D = Action.C, Action.D | ||
|
||
class FreqAnalyzer(Player): | ||
""" | ||
A player starts by playing TitForTat for the first 30 turns (dataset generation phase). | ||
Take the matrix of last 2 moves by both Player and Opponent. | ||
While in dataset generation phase, construct a dictionary d, where keys are each 4 move sequence | ||
and the corresponding value for each key is a list of the subsequent Opponent move. The 4 move sequence | ||
starts with the Opponent move. | ||
For example, if a game at turn 5 looks like this: | ||
Opp: C, C, D, C, D | ||
Player: C, C, C, D, C | ||
d should look like this: | ||
{ [CCCC]: [D], | ||
[CCDC]: [C], | ||
[DCCD]: [D] } | ||
During dataset generation phase, Player will play TitForTat. After end of dataset generation phase, | ||
Player will switch strategies. Upon encountering a particular 4-move sequence in the game, Player will look up history | ||
of subsequent Opponent move. If ratio of defections to total moves exceeds p, Player will defect. Otherwise, | ||
Player will cooperate. | ||
Could fall under "Hunter" class of strategies. | ||
More likely falls under LookerUp class of strategies. | ||
Names: | ||
- FreqAnalyzer (FREQ): Original by Ian Miller | ||
""" | ||
|
||
# These are various properties for the strategy | ||
name = "FreqAnalyzer" | ||
classifier = { | ||
"memory_depth": float("inf"), | ||
"stochastic": False, | ||
"long_run_time": False, | ||
"inspects_source": False, | ||
"manipulates_source": False, | ||
"manipulates_state": False, | ||
} | ||
def __init__(self) -> None: | ||
""" | ||
Parameters | ||
---------- | ||
p, float | ||
The probability to cooperate | ||
""" | ||
super().__init__() | ||
self.minimum_cooperation_ratio = 0.5 | ||
self.frequency_table = dict() | ||
self.last_sequence = '' | ||
self.current_sequence = '' | ||
|
||
def strategy(self, opponent: Player) -> Action: | ||
"""This is the actual strategy""" | ||
if len(self.history) > 5: | ||
self.last_sequence = str(opponent.history[-3]) + str(self.history[-3]) + str(opponent.history[-2]) + str(self.history[-2]) | ||
self.current_sequence = str(opponent.history[-2]) + str(self.history[-2]) + str(opponent.history[-1]) + str(self.history[-1]) | ||
|
||
self.update_table(opponent) | ||
|
||
if len(self.history) < 30: | ||
# Play TitForTat | ||
# First move | ||
if not self.history: | ||
return C | ||
# React to the opponent's last move | ||
if opponent.history[-1] == D: | ||
return D | ||
return C | ||
else: | ||
try: | ||
results = self.frequency_table[self.current_sequence] | ||
cooperates = results.count('C') | ||
if (cooperates / len(self.history)) > self.minimum_cooperation_ratio: | ||
return C | ||
return D | ||
except: | ||
if not self.history: | ||
return C | ||
# React to the opponent's last move | ||
if opponent.history[-1] == D: | ||
return D | ||
return C | ||
|
||
def update_table(self, opponent: Player): | ||
print(self.frequency_table) | ||
print("___________________") | ||
print("current sequence is {}", self.last_sequence) | ||
if self.last_sequence in self.frequency_table.keys(): | ||
print("seen this key before") | ||
print("freq table keys = {}", self.frequency_table.keys()) | ||
results = self.frequency_table[self.last_sequence] | ||
results.append(opponent.history[-1]) | ||
self.frequency_table[self.last_sequence] = results | ||
else: | ||
print("not seen this key ever") | ||
self.frequency_table[self.last_sequence] = [opponent.history[-1]] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
"""Tests for the Stalker strategy.""" | ||
|
||
import axelrod as axl | ||
|
||
from .test_player import TestPlayer | ||
|
||
C, D = axl.Action.C, axl.Action.D | ||
|
||
|
||
class TestStalker(TestPlayer): | ||
|
||
name = "Stalker: (D,)" | ||
player = axl.Stalker | ||
expected_classifier = { | ||
"memory_depth": float("inf"), | ||
"stochastic": True, | ||
"makes_use_of": {"game", "length"}, | ||
"long_run_time": False, | ||
"inspects_source": False, | ||
"manipulates_source": False, | ||
"manipulates_state": False, | ||
} | ||
|
||
def test_strategy(self): | ||
actions = [(C, C)] * 3 + [(D, C)] | ||
self.versus_test(opponent=axl.Cooperator(), expected_actions=actions) | ||
|
||
# wish_score < current_average_score < very_good_score | ||
actions = [(C, C)] * 7 + [(C, D), (C, D), (C, C), (C, C), (D, C)] | ||
self.versus_test( | ||
opponent=axl.MockPlayer(actions=[C] * 7 + [D] * 2), | ||
expected_actions=actions, | ||
) | ||
|
||
actions = [(C, C)] * 7 + [(C, D), (C, C), (D, C)] | ||
self.versus_test( | ||
opponent=axl.MockPlayer(actions=[C] * 7 + [D]), | ||
expected_actions=actions, | ||
) | ||
|
||
# current_average_score > 2 | ||
actions = [(C, C)] * 9 + [(D, C)] | ||
self.versus_test(axl.Cooperator(), expected_actions=actions) | ||
|
||
# 1 < current_average_score < 2 | ||
actions = [(C, C)] * 7 + [(C, D)] * 4 + [(D, D)] | ||
self.versus_test( | ||
opponent=axl.MockPlayer(actions=[C] * 7 + [D] * 5), | ||
expected_actions=actions, | ||
) | ||
|
||
def test_strategy2(self): | ||
# current_average_score < 1 | ||
actions = ( | ||
[(C, D)] | ||
+ [(D, D)] * 2 | ||
+ [(C, D)] * 3 | ||
+ [(D, D), (C, D), (D, D), (C, D), (D, D), (C, D), (D, D)] | ||
) | ||
self.versus_test(axl.Defector(), expected_actions=actions, seed=3222) | ||
|
||
def test_strategy3(self): | ||
actions = [(C, D)] * 3 + [ | ||
(D, D), | ||
(C, D), | ||
(D, D), | ||
(C, D), | ||
(C, D), | ||
(D, D), | ||
(C, D), | ||
(C, D), | ||
(C, D), | ||
(D, D), | ||
] | ||
self.versus_test(axl.Defector(), expected_actions=actions, seed=649) | ||
|
||
def test_strategy4(self): | ||
# defect in last round | ||
actions = [(C, C)] * 199 + [(D, C)] | ||
self.versus_test( | ||
axl.Cooperator(), | ||
expected_actions=actions, | ||
match_attributes={"length": 200}, | ||
) | ||
|
||
# Force a defection before the end of the actual match which ensures | ||
# that current_average_score > very_good_score | ||
actions = [(C, C)] * 3 + [(D, C)] * 3 | ||
self.versus_test( | ||
opponent=axl.Cooperator(), | ||
expected_actions=actions, | ||
match_attributes={"length": 4}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters