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 5 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
from .axelrod_second import Champion, Eatherley, Tester, Gladstein, 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
59 changes: 59 additions & 0 deletions axelrod/strategies/axelrod_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,62 @@ def strategy(self, opponent: Player) -> Action:
else:
# Play TFT
return opponent.history[-1]


class MoreGrofman(Player):
'''
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 change these to "

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
- If its own previous move was C and the opponent has defected less than
Copy link
Member

Choose a reason for hiding this comment

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

CI is failing because this isn't building in the documentation. Need a space:

    3. Thereafter, it applies the following logic

      - If its own previous move was C and the opponent has defected less than

twice in the last 7 rounds, cooperate
- If its own previous move was C and the opponent has defected twice or
more in the last 7 rounds, defect
- If its own previous move was D and the opponent has defected only once
or not at all in the last 7 rounds, cooperate
- If its own previous move was D and the opponent has defected more than
once in the last 7 rounds, defect

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

def __init__(self) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need this __init__ if it simply calls the parent class __init__

super().__init__()

def strategy(self, opponent: Player) -> Action:
# Cooperate on the first two moves
if not self.history or len(self.history) in [1]:
Copy link
Member

Choose a reason for hiding this comment

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

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]
# Logic for the rest of the game
Copy link
Member

Choose a reason for hiding this comment

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

This comment isn't necessary

else:
opponent_defections_last_7_rounds = 0
Copy link
Member

Choose a reason for hiding this comment

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

opponent_defections_last_7_rounds = opponent.history[-7:].count(D)

for action in opponent.history[-7:]:
if action == D:
opponent_defections_last_7_rounds += 1
if self.history[-1] == C:
Copy link
Member

@marcharper marcharper Aug 30, 2017

Choose a reason for hiding this comment

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

Can this be simplified to:

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

?

if opponent_defections_last_7_rounds < 2:
return C
else:
Copy link
Member

@drvinceknight drvinceknight Aug 26, 2017

Choose a reason for hiding this comment

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

no need to have an else, just replace the else with return D

Similarly below (line 264).

(Not a big deal: just a stylistic suggestion.)

return D
else:
if opponent_defections_last_7_rounds in [0, 1]:
return C
else:
return D
53 changes: 53 additions & 0 deletions axelrod/tests/strategies/test_axelrod_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,56 @@ def test_strategy(self):
actions = [(D, C), (C, C), (C, D), (C, D), (D, D)]
self.versus_test(opponent, expected_actions=actions,
attrs={'patsy': False})


class TestMoreGrofman(TestPlayer):

name = "MoreGrofman"
player = axelrod.MoreGrofman
expected_classifier = {
'memory_depth': 7,
Copy link
Member

Choose a reason for hiding this comment

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

This now needs to be 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 twice in last 7
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 more than twice in last 7
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 in last 7
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 twice in last 7
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)