Skip to content
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

Added Rowsam (k58r) strategy from Axelrod's second. #1228

Merged
merged 7 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
MoreGrofman,
MoreTidemanAndChieruzzi,
RichardHufford,
Rowsam,
Tester,
Tranquilizer,
Weiner,
Expand Down Expand Up @@ -388,6 +389,7 @@
RichardHufford,
Ripoff,
RiskyQLearner,
Rowsam,
SelfSteem,
ShortMem,
Shubik,
Expand Down
106 changes: 106 additions & 0 deletions axelrod/strategies/axelrod_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -1953,3 +1953,109 @@ def strategy(self, opponent: Player) -> Action:
if opponent.defections / turn >= 0.15:
return D
return C


class Rowsam(Player):
"""
Strategy submitted to Axelrod's second tournament by Glen Rowsam (K58R)
and came in 21st in that tournament.

The strategy starts in Normal mode, where it cooperates every turn. Every
six turns it checks the score per turn. [Rather the score of all previous
turns divided by the turn number, which will be one more than the number of
turns scored.] If this measure is less than 2.5 (the strategy is doing
badly) and it increases `distrust_points`. `distrust_points` is a variable
that starts at 0; if it ever exceeds 6 points, the strategy will enter
Defect mode and defect from then on. It will increase `distrust_points`
depending on the precise score per turn according to:

- 5 points if score per turn is less than 1.0
- 3 points if score per turn is less than 1.5, but at least 1.0
- 2 points if score per turn is less than 2.0, but at least 1.5
- 1 points if score per turn is less than 2.5, but at least 2.0

If `distrust_points` are increased, then the strategy defects on that turn,
then cooperates and defects on the next two turns. [Unless
`distrust_points` exceeds 6 points, then it will enter Defect mode
immediately.]

Every 18 turns in Normal mode, the strategy will decrement `distrust_score`
if it's more than 3. This represents a wearing off effect of distrust.


Names:

- Rowsam: [Axelrod1980b]_
"""

name = "Rowsam"
classifier = {
"memory_depth": float("inf"),
"stochastic": False,
"makes_use_of": set("game"),
"long_run_time": False,
"inspects_source": False,
"manipulates_source": False,
"manipulates_state": False,
}

def __init__(self) -> None:
super().__init__()
self.mode = "Normal"
self.distrust_points = 0
self.current_score = 0
self.opponent_score = 0

def _score_last_round(self, opponent: Player):
"""Updates the scores for each player."""
game = self.match_attributes["game"]
last_round = (self.history[-1], opponent.history[-1])
scores = game.score(last_round)
self.current_score += scores[0]
self.opponent_score += scores[1]

def strategy(self, opponent: Player) -> Action:
turn = len(self.history) + 1
if turn > 1:
self._score_last_round(opponent)

if self.mode == "Defect":
return D

if self.mode == "Coop Def Cycle 1":
self.mode = "Coop Def Cycle 2"
return C

if self.mode == "Coop Def Cycle 2":
self.mode = "Normal"
return D

# Opportunity for distrust to cool off.
if turn % 18 == 0:
if self.distrust_points >= 3:
self.distrust_points -= 1

# In normal mode, only check for strategy updates every sixth turn.
if turn % 6 != 0:
return C

points_per_turn = self.current_score / turn # Off by one
if points_per_turn < 1.0:
self.distrust_points += 5
elif points_per_turn < 1.5:
self.distrust_points += 3
elif points_per_turn < 2.0:
self.distrust_points += 2
elif points_per_turn < 2.5:
self.distrust_points += 1
else:
# Continue Cooperating
return C

if self.distrust_points >= 7:
self.mode = "Defect"
else:
# Def this time, then coop, then def.
self.mode = "Coop Def Cycle 1"
return D

93 changes: 93 additions & 0 deletions axelrod/tests/strategies/test_axelrod_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -1815,3 +1815,96 @@ def test_strategy(self):
Change_of_Heart, expected_actions=actions, attrs={"credit": -2}
)
# Still Cooperate, because Defect rate is low

class TestRowsam(TestPlayer):
name = "Rowsam"
player = axelrod.Rowsam
expected_classifier = {
"memory_depth": float("inf"),
"stochastic": False,
"makes_use_of": set("game"),
"long_run_time": False,
"inspects_source": False,
"manipulates_source": False,
"manipulates_state": False,
}

def test_strategy(self):
# Should always cooperate with Cooperator
actions = [(C, C)] * 100
self.versus_test(axelrod.Cooperator(), expected_actions=actions)

# Against a Defector should eventually enter Defect mode
actions = [(C, D)] * 5
actions += [(D, D), (C, D), (D, D)] # Do a Coop-Def cycle
self.versus_test(axelrod.Defector(), expected_actions=actions, attrs={
"distrust_points": 5})
actions += [(C, D)] * 3 # Continue for now
actions += [(D, D)] * 100 # Now Defect mode
self.versus_test(axelrod.Defector(), expected_actions=actions, attrs={
"distrust_points": 10, "mode": "Defect"})

# Test specific score scenarios
# 5 Defects
opponent_actions = [D] * 5 + [C] * 100
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = [(C, D)] * 5
actions += [(D, C)]
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 5, "current_score": 0})

# 3 Defects
opponent_actions = [D] * 3 + [C] * 100
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = [(C, D)] * 3
actions += [(C, C)] * 2
actions += [(D, C)]
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 3, "current_score": 6})

# 2 Defects
opponent_actions = [D] * 2 + [C] * 100
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = [(C, D)] * 2
actions += [(C, C)] * 3
actions += [(D, C)]
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 2, "current_score": 9})

# 1 Defect
opponent_actions = [D] * 1 + [C] * 100
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = [(C, D)] * 1
actions += [(C, C)] * 4
actions += [(D, C)]
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 1, "current_score": 12})

# Test that some distrust_points wear off.
opponent_actions = [D] * 3 + [C] * 100
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = [(C, D)] * 3
actions += [(C, C)] * 2
actions += [(D, C)]
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 3, "current_score": 6})
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions += [(C, C), (D, C)] # Complete Coop-Def cycle
actions += [(C, C)] * 3
actions += [(D, C)]
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 4, "current_score": 28})
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions += [(C, C), (D, C)] # Complete Coop-Def cycle
actions += [(C, C)] * 4 # No defect or cycle this time.
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 3, "current_score": 50}) # One point wears off.
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions += [(C, C)] * 18
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 2}) # Second point wears off
custom_opponent = axelrod.MockPlayer(actions=opponent_actions)
actions += [(C, C)] * 18
self.versus_test(custom_opponent, expected_actions=actions, attrs={
"distrust_points": 2}) # But no more

2 changes: 1 addition & 1 deletion docs/reference/overview_of_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ repository.
"K55R_", "Steve Newman", "Not Implemented"
"K56R_", "Stanley F Quayle", "Not Implemented"
"K57R_", "Rudy Nydegger", "Not Implemented"
"K58R_", "Glen Rowsam", "Not Implemented"
"K58R_", "Glen Rowsam", ":class:`Rowsam <axelrod.strategies.axelrod_second.Rowsam>`"
"K59R_", "Leslie Downing", "Not Implemented"
"K60R_", "Jim Graaskamp and Ken Katzen", ":class:`GraaskampKatzen <axelrod.strategies.axelrod_second.GraaskampKatzen>`"
"K61R_", "Danny C Champion", ":class:`Champion <axelrod.strategies.axelrod_second.Champion>`"
Expand Down