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

Add the K86R (MoreGrofman) Strategy #1124

Merged
merged 18 commits into from
Sep 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a93d74a
Write out strategy logic
buckbaskin Aug 23, 2017
aca96ae
Fix some identified pep8 compliance issues
buckbaskin Aug 23, 2017
1a9fa68
Update the strategies/_strategies.py file with MoreGrofman
buckbaskin Aug 23, 2017
6ffdaea
Add MoreGrofman strategy to the list of strategies
buckbaskin Aug 23, 2017
bc50c84
Add tests to verify the MoreGrofman logic
buckbaskin Aug 23, 2017
900e885
Make advised syntax changes with double quote, using count
buckbaskin Aug 24, 2017
29de9ba
Add test that demonstrates error in strategy logic
buckbaskin Aug 24, 2017
f3625e8
Add an extended test to match a 30 round Fortran match
buckbaskin Aug 24, 2017
e870730
Adjust indexing for an off-by-1 error. Test passes, will try longer test
buckbaskin Aug 24, 2017
2480ca7
Repair off-by-1 error in Python implementation and Add tests to verify
buckbaskin Aug 24, 2017
79f0499
Update comments to reflect behavior that matches Fortran behavior
buckbaskin Aug 26, 2017
8f64aad
Clarify behavior re: inspection of history
buckbaskin Aug 26, 2017
37664eb
Make a style change to else logic
buckbaskin Aug 26, 2017
1334535
Change expected test memory depth to 8
buckbaskin Aug 26, 2017
251da15
Fix Spacing Issue that broke docs compilation
buckbaskin Aug 28, 2017
60ac912
Make style changes to MoreGrofman strategy
buckbaskin Sep 5, 2017
64efcae
Shorten the actions list for testing against Fortran examples
buckbaskin Sep 5, 2017
ad55ec5
Merge branch 'master' of github.com:Axelrod-Python/Axelrod into more-…
buckbaskin Sep 6, 2017
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
3 changes: 2 additions & 1 deletion axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .axelrod_first import (
Davis, RevisedDowning, Feld, Grofman, Nydegger, Joss, Shubik, Tullock,
UnnamedStrategy, SteinAndRapoport, TidemanAndChieruzzi)
from .axelrod_second import Champion, Eatherley, Tester, Gladstein, Tranquilizer
from .axelrod_second import Champion, Eatherley, Tester, Gladstein, Tranquilizer, MoreGrofman
from .backstabber import BackStabber, DoubleCrosser
from .better_and_better import BetterAndBetter
from .calculator import Calculator
Expand Down Expand Up @@ -197,6 +197,7 @@
MindReader,
MindWarper,
MirrorMindReader,
MoreGrofman,
Negation,
NiceAverageCopier,
NTitsForMTats,
Expand Down
57 changes: 57 additions & 0 deletions axelrod/strategies/axelrod_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,60 @@ def strategy(self, opponent: Player) -> Action:
return C
return D
return opponent.history[-1]


class MoreGrofman(Player):
"""
Submitted to Axelrod's second tournament by Bernard Grofman.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add the Fortran rule name (K86R) to the docstring?


This strategy has 3 phases:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also need a space here.

This strategy has 3 phases:

1. First


1. First it cooperates on the first two rounds
2. For rounds 3-7 inclusive, it plays the same as the opponent's last move
3. Thereafter, it applies the following logic, looking at its memory of the
last 8\* rounds (ignoring the most recent round).

- If its own previous move was C and the opponent has defected less than
3 times in the last 8\* rounds, cooperate
- If its own previous move was C and the opponent has defected 3 or
more times in the last 8\* rounds, defect
- If its own previous move was D and the opponent has defected only once
or not at all in the last 8\* rounds, cooperate
- If its own previous move was D and the opponent has defected more than
once in the last 8\* rounds, defect

\* The code looks at the first 7 of the last 8 rounds, ignoring the most
recent round.

Names:
- Grofman's strategy: [Axelrod1980b]_
- K86R: [Axelrod1980b]_
"""
name = "MoreGrofman"
classifier = {
'memory_depth': 8,
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent: Player) -> Action:
# Cooperate on the first two moves
if len(self.history) < 2:
return C
# For rounds 3-7, play the opponent's last move
elif 2 <= len(self.history) <= 6:
return opponent.history[-1]
else:
# Note: the Fortran code behavior ignores the opponent behavior
# in the last round and instead looks at the first 7 of the last
# 8 rounds.
opponent_defections_last_8_rounds = opponent.history[-8:-1].count(D)
if self.history[-1] == C and opponent_defections_last_8_rounds <= 2:
return C
if self.history[-1] == D and opponent_defections_last_8_rounds <= 1:
return C
return D
82 changes: 80 additions & 2 deletions axelrod/tests/strategies/test_axelrod_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ def test_strategy(self):
self.versus_test(opponent, expected_actions=actions,
attrs={'patsy': False})


class TestTranquilizer(TestPlayer):

name = "Tranquilizer"
Expand All @@ -175,7 +174,6 @@ class TestTranquilizer(TestPlayer):
'manipulates_state': False
}


# test for initalised variables

def test_init(self):
Expand Down Expand Up @@ -330,3 +328,83 @@ def test_strategy(self):
"two_turns_after_good_defection_ratio_count": 1}
self.versus_test(opponent, expected_actions=actions,
attrs=expected_attrs)


class TestMoreGrofman(TestPlayer):

name = "MoreGrofman"
player = axelrod.MoreGrofman
expected_classifier = {
'memory_depth': 8,
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
# Cooperate for the first two rounds
actions = [(C, C), (C, C)]
self.versus_test(axelrod.Cooperator(), expected_actions=actions)

# Cooperate for the first two rounds, then play tit for tat for 3-7
actions = [(C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C)]
self.versus_test(axelrod.Alternator(), expected_actions=actions)

# Demonstrate MoreGrofman Logic
# Own previous move was C, opponent defected less than 3 times in last 8
moregrofman_actions = [C] * 7 + [C]
opponent_actions = [C] * 6 + [D] * 2
opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = list(zip(moregrofman_actions, opponent_actions))
self.versus_test(opponent, expected_actions=actions)

# Own previous move was C, opponent defected 3 or more times in last 8
moregrofman_actions = ([C] * 3 + [D] * 3 + [C]) + [D]
opponent_actions = ([C] * 2 + [D] * 3 + [C] * 2) + [D]
opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = list(zip(moregrofman_actions, opponent_actions))
self.versus_test(opponent, expected_actions=actions)

# Own previous move was D, opponent defected once or less in last 8
moregrofman_actions = ([C] * 6 + [D]) + [C]
opponent_actions = ([C] * 5 + [D] * 1 + [C]) + [D]
opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = list(zip(moregrofman_actions, opponent_actions))
self.versus_test(opponent, expected_actions=actions)

# Own previous move was D, opponent defected more than once in last 8
moregrofman_actions = ([C] * 2 + [D] * 5) + [D]
opponent_actions = ([D] * 7) + [D]
opponent = axelrod.MockPlayer(actions=opponent_actions)
actions = list(zip(moregrofman_actions, opponent_actions))
self.versus_test(opponent, expected_actions=actions)

# Test to make sure logic matches Fortran (discrepancy found 8/23/2017)
opponent = axelrod.AntiTitForTat()
# Actions come from a match run by Axelrod Fortran using Player('k86r')
actions = [(C, C), (C, D), (D, D), (D, C), (C, C), (C, D), (D, D),
(D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (C, C)]
self.versus_test(opponent, expected_actions=actions)

# Test to match the Fortran implementation for 30 rounds
opponent = axelrod.AntiTitForTat()
actions = [(C, C), (C, D), (D, D), (D, C), (C, C), (C, D), (D, D),
(D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (C, C),
(C, D), (C, D), (C, D), (C, D), (D, D), (D, C), (D, C), (D, C),
(D, C), (D, C), (D, C), (D, C), (C, C), (C, D), (C, D)]
self.versus_test(opponent, expected_actions=actions)

# Test to match the Fortran implementation for 60 rounds
opponent = axelrod.AntiTitForTat()
actions = [(C, C), (C, D), (D, D), (D, C), (C, C), (C, D), (D, D),
(D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (C, C),
(C, D), (C, D), (C, D), (C, D), (D, D), (D, C), (D, C), (D, C),
(D, C), (D, C), (D, C), (D, C), (C, C), (C, D), (C, D), (C, D),
(C, D), (D, D), (D, C), (D, C), (D, C), (D, C), (D, C), (D, C),
(D, C), (C, C), (C, D), (C, D), (C, D), (C, D), (D, D), (D, C),
(D, C), (D, C), (D, C), (D, C), (D, C), (D, C), (C, C), (C, D),
(C, D), (C, D), (C, D), (D, D), (D, C)]
self.versus_test(opponent, expected_actions=actions)