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 a new DynamicTwoTitsForTat strategy #1030

Merged
merged 6 commits into from
May 30, 2017
Merged
Show file tree
Hide file tree
Changes from 4 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
3 changes: 2 additions & 1 deletion axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
OmegaTFT, Gradual, ContriteTitForTat, SlowTitForTwoTats, AdaptiveTitForTat,
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier)
SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier, DynamicTwoTitsForTat)
from .verybad import VeryBad
from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse,
WorseAndWorse2, WorseAndWorse3)
Expand Down Expand Up @@ -263,4 +263,5 @@
ZDGen2,
ZDSet2,
e,
DynamicTwoTitsForTat,
]
36 changes: 36 additions & 0 deletions axelrod/strategies/titfortat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from axelrod.actions import Actions, Action
from axelrod.player import Player
from axelrod.strategy_transformers import TrackHistoryTransformer, FinalTransformer
from axelrod.random_ import random_choice

C, D = Actions.C, Actions.D

Expand Down Expand Up @@ -92,6 +93,41 @@ class TwoTitsForTat(Player):
def strategy(opponent: Player) -> Action:
return D if D in opponent.history[-2:] else C

class DynamicTwoTitsForTat(Player):
"""
A player starts by cooperating and then punishes its opponent's
defectiions by opponent with a dynamic bias based off of the
opponents ratio of cooperations to total moves (so their current
probability of cooperating towards cooporating regardless of the
move (aka: forgiveness)).
Copy link
Member

Choose a reason for hiding this comment

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

Blank line before Names please.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

Copy link
Member

Choose a reason for hiding this comment

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

typos and grammar:
defectiions -> defections
opponents ratio -> opponent's ratio
based off of the -> based on

Copy link
Member

Choose a reason for hiding this comment

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

"its opponent's defectiions by opponent"

Should this be either 'its opponent's defections' or 'defections by opponent'?

Copy link
Member

Choose a reason for hiding this comment

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

"(so their current probability of cooperating towards cooporating regardless of the move (aka: forgiveness))."

Sorry, but I don't understand what that line means.


Names:

- Dynamic Two Tits For Tat: Original name by Grant Garrett-Grossman.
"""

name = 'Dynamic Two Tits For Tat'
classifier = {
'memory_depth': 2, # Long memory, memory-2
'stochastic': True,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

@staticmethod
def strategy(opponent):
# First move
if len(opponent.history) == 0:
Copy link
Member

Choose a reason for hiding this comment

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

this would be better as if not opponent.history:

Copy link
Member

Choose a reason for hiding this comment

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

FYI @FakeNameSE this gives some good background: https://stackoverflow.com/questions/53513/best-way-to-check-if-a-list-is-empty

(Apologies, as is was my suggestion, thanks to @meatballs for pointing it out!)

# Make sure we cooporate first turn
return C
if D in opponent.history[-2:]:
# Probability of cooperating regardless
return random_choice(opponent.cooperations / len(opponent.history))
else:
return C

class Bully(Player):
"""A player that behaves opposite to Tit For Tat, including first move.
Expand Down
31 changes: 31 additions & 0 deletions axelrod/tests/strategies/test_titfortat.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,37 @@ def test_strategy(self):
self.versus_test(opponent, expected_actions=actions)


class TestDynamicTwoTitsForTat(TestPlayer):

name = 'Dynamic Two Tits For Tat'
player = axelrod.DynamicTwoTitsForTat
expected_classifier = {
'memory_depth': 2,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
# First move is to cooperate
self.first_play_test(C)
# Test that it is stochastic
opponent = axelrod.MockPlayer(actions=[D, C, D, D, C])
actions = [(C, D), (D, C), (C, D), (D, D), (D, C)]
self.versus_test(opponent, expected_actions=actions, seed=1)
# Should respond differently with a different seed
actions = [(C, D), (D, C), (D, D), (D, D), (C, C)]
self.versus_test(opponent, expected_actions=actions, seed=2)

# Will cooperate if opponent cooperates.
actions = [(C, C), (C, C), (C, C), (C, C), (C, C)]
self.versus_test(axelrod.Cooperator(), expected_actions=actions)
# Test against defector
actions = [(C, D), (D, D), (D, D), (D, D), (D, D)]
self.versus_test(axelrod.Defector(), expected_actions=actions)

class TestBully(TestPlayer):

name = "Bully"
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorials/advanced/classification_of_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ strategies::
... }
>>> strategies = axl.filtered_strategies(filterset)
>>> len(strategies)
66
67

Or, to find out how many strategies only use 1 turn worth of memory to
make a decision::
Expand All @@ -69,7 +69,7 @@ range of memory_depth values, we can use the 'min_memory_depth' and
... }
>>> strategies = axl.filtered_strategies(filterset)
>>> len(strategies)
49
50

We can also identify strategies that make use of particular properties of the
tournament. For example, here is the number of strategies that make use of the
Expand Down