Skip to content

Commit

Permalink
Added basic plugin capability, add random, grudger and tit-for-tat st…
Browse files Browse the repository at this point in the history
…rategies, added track and iterations options. Changed iteration and food defaults and food awards.
  • Loading branch information
bendavieshe3 committed May 22, 2011
1 parent 7940953 commit 5c29da6
Show file tree
Hide file tree
Showing 3 changed files with 385 additions and 53 deletions.
179 changes: 159 additions & 20 deletions src/critters.py
Expand Up @@ -11,27 +11,30 @@ class Critter(object):
number_of = 0


def __init__(self, strategy):
def __init__(self, name, strategy):
'''critter constructor
>>> Critter.number_of = 0
>>> critter = Critter(None)
>>> critter = Critter('c1', None)
>>> critter.name
'Critter_1'
'c1'
>>> critter.food
0
>>> critter2 = Critter(None)
5
>>> critter2 = Critter('c2', None)
>>> critter2.name
'Critter_2'
'c2'
'''
self.food = 0
self.food = 5
self.strategy = strategy
Critter.number_of += 1
self.name = "Critter_%d" % Critter.number_of
if name is None:
self.name = "Critter_%d" % Critter.number_of
else:
self.name = name

def interact(self, other_critter):
'''Interact with another critter
>>> c1 = Critter(CheatStrategy())
>>> c2 = Critter(CheatStrategy())
>>> c1 = Critter('c1', CheatStrategy())
>>> c2 = Critter('c2', CheatStrategy())
>>> c1.interact(c2)
0
'''
Expand All @@ -41,30 +44,30 @@ def observe_interaction(self, critter1, critter1_action,
critter2, critter2_action):
'''
take into account an interaction
>>> c1 = Critter(CheatStrategy())
>>> c2 = Critter(CheatStrategy())
>>> c1 = Critter(None, CheatStrategy())
>>> c2 = Critter(None, CheatStrategy())
>>> c1.observe_interaction(c1,0,c2,0)
'''
self.strategy.observe_interaction(critter1, critter1_action,
self.strategy.observe_interaction(self, critter1, critter1_action,
critter2, critter2_action)

def add_food(self, food_amount):
'''
Adds food to the critter
>>> critter = Critter(None)
>>> critter = Critter(None, None)
>>> critter.add_food(10)
>>> critter.food
10
15
'''
self.food += food_amount

def remove_food(self, food_amount):
'''
Removes food from the critter
>>> critter = Critter(None)
>>> critter = Critter(None, None)
>>> critter.remove_food(10)
>>> critter.food
-10
-5
'''
self.food -= food_amount

Expand All @@ -79,17 +82,17 @@ def interact(self, other_agent):
perform an interaction with another agent and return a result code
if not implemented in subclass, this always returns 0 for the default response
>>> strategy = AbstractStrategy()
>>> strategy.interact(Critter(None))
>>> strategy.interact(Critter(None, None))
0
'''
return AbstractStrategy.UNCOOPERATE

def observe_interaction(self, agent1, agent1_action, agent2, agent2_action):
def observe_interaction(self, me, agent1, agent1_action, agent2, agent2_action):
'''
provides information to the strategy about what transpired in an interaction.
Does not return anything
>>> strategy = AbstractStrategy()
>>> strategy.observe_interaction(Critter(None), 1, Critter(None), 0)
>>> strategy.observe_interaction(Critter(None, None), Critter(None, None), 1, Critter(None, None), 0)
'''
pass
Expand Down Expand Up @@ -118,6 +121,142 @@ def interact(self, other_agent):
'''
return SuckerStrategy.COOPERATE

class RandomStrategy(AbstractStrategy):
'''A strategy that randomly decides to cooperate or not each time'''

def interact(self, other_agent):
'''
Upon interacting this strategy advising a random outcome
>>> random_strategy = RandomStrategy()
>>> random_strategy.interact(None) # doctest:+ELLIPSIS, +SKIP
1
>>> random_strategy = RandomStrategy()
>>> random_strategy.interact(None) # doctest:+ELLIPSIS, +SKIP
0
'''

import random
return random.choice((RandomStrategy.COOPERATE,
RandomStrategy.UNCOOPERATE))

class GrudgerStrategy(AbstractStrategy):
'''
A strategy that never cooperates again with an agent that has failed
to cooperate with this agent in the past
>>> grudger_strategy = GrudgerStrategy()
>>> grudger = Critter('g1', grudger_strategy)
'''

def __init__(self):
''' constructor'''
super(GrudgerStrategy,self).__init__()
self.agents_to_grudge = list()


def interact(self, other_agent):
'''
Upon interacting, cooperate if the other agent has never not cooperated
with this specific agent. If this is the first time of an interaction,
cooperate
>>> g = Critter('g', GrudgerStrategy())
>>> c1 = Critter('c1', None)
>>> c2 = Critter('c1', None)
>>> g.interact(c1)
1
>>> g.interact(c2)
1
>>> g.observe_interaction(g, 1, c1, 0)
>>> g.interact(c1)
0
>>> g.interact(c1)
0
'''
if self.agents_to_grudge.count(other_agent.name):
return GrudgerStrategy.UNCOOPERATE
return GrudgerStrategy.COOPERATE

def observe_interaction(self, me, agent1, agent1_action, agent2, agent2_action):
'''
provides information to the strategy about what transpired in an interaction.
Does not return anything
>>> grudger_strategy = GrudgerStrategy()
>>> grudger = Critter('g1', grudger_strategy)
>>> other_critter1 = Critter('c1', None)
>>> other_critter2 = Critter('c2', None)
>>> #observer other interaction
>>> grudger_strategy.observe_interaction(grudger, other_critter1, 1, other_critter2, 0)
>>> grudger_strategy.observe_interaction(grudger, grudger, 1, other_critter2, 0)
>>> grudger_strategy.observe_interaction(grudger, grudger, 0, other_critter1, 1)
>>> grudger_strategy.agents_to_grudge
['c2']
'''
if agent1.name == me.name:
if agent2_action == GrudgerStrategy.UNCOOPERATE:
if self.agents_to_grudge.count(agent2.name) == 0:
self.agents_to_grudge.append(agent2.name)
elif agent2.name == me.name:
if agent1_action == GrudgerStrategy.UNCOOPERATE:
if self.agents_to_grudge.count(agent1.name) == 0:
self.agents_to_grudge.append(agent1.name)

class TitForTatStrategy(AbstractStrategy):
'''
A strategy that will initially coperate with another agent, but will
punish an agent whose last action was to try to cheat tit for tat
>>> t4t_strategy = TitForTatStrategy()
>>> t4t = Critter('t1', t4t_strategy)
'''

def __init__(self):
''' constructor'''
super(TitForTatStrategy,self).__init__()
self.last_agent_interaction = dict()


def interact(self, other_agent):
'''
Upon interacting, cooperate if the other agent was last known to cooperate.
If the other agent last cheated, cheat back
If this is the first time of an interaction cooperate
>>> t = Critter('t', TitForTatStrategy())
>>> c1 = Critter('c1', None)
>>> c2 = Critter('c1', None)
>>> t.interact(c1)
1
>>> t.interact(c2)
1
>>> t.observe_interaction(t, 1, c1, 0)
>>> t.interact(c1)
0
>>> t.observe_interaction(t, 1, c1, 1)
>>> t.interact(c1)
1
'''
if self.last_agent_interaction.has_key(other_agent.name):
return self.last_agent_interaction[other_agent.name]
return TitForTatStrategy.COOPERATE

def observe_interaction(self, me, agent1, agent1_action, agent2, agent2_action):
'''
provides information to the strategy about what transpired in an interaction.
Does not return anything
>>> t4t_strategy = TitForTatStrategy()
>>> t4t = Critter('t1', t4t_strategy)
>>> other_critter1 = Critter('c1', None)
>>> other_critter2 = Critter('c2', None)
>>> #observer other interaction
>>> t4t_strategy.observe_interaction(t4t, other_critter1, 1, other_critter2, 0)
>>> t4t_strategy.observe_interaction(t4t, t4t, 1, other_critter2, 0)
>>> t4t_strategy.observe_interaction(t4t, t4t, 0, other_critter1, 1)
>>> t4t_strategy.last_agent_interaction
{'c2': 0, 'c1': 1}
'''
if agent1.name == me.name:
self.last_agent_interaction[agent2.name] = agent2_action
elif agent2.name == me.name:
self.last_agent_interaction[agent1.name] = agent1_action


if __name__ == '__main__':
import doctest
doctest.testmod()
22 changes: 19 additions & 3 deletions src/main.py 100644 → 100755
Expand Up @@ -8,8 +8,10 @@

def main(argv):
world_to_run = 'PrisonersDilemma'
track_critter = None
iterations = 1500
try:
opts, args = getopt.getopt(argv, 'h','--help')
opts, args = getopt.getopt(argv, 'ht:i:','--help,--track,--iterations')

except getopt.GetoptError:
usage()
Expand All @@ -18,16 +20,30 @@ def main(argv):
if opt in ('-h','--help'):
usage()
sys.exit()
elif opt in ('-t','--track'):
track_critter = arg
elif opt in ('-i','--iterations'):
iterations = int(arg)

world_to_run = "".join(args) or world_to_run

print "running world %s" % world_to_run

instantiate_world(world_to_run).run()
xworld = instantiate_world(world_to_run)
xworld.add_plugin(world.TabularReporter())

if track_critter:
xworld.add_plugin(world.CritterTracker(track_critter))
xworld.run(iterations)



def usage():
'''prints usage instructions'''
print('Usage: main.py [world]')
print('Usage: main.py [world]')
print('options:')
print('-i,iterations\tNumber of iterations to run')
print('-t,track\ttrack a named critter')

def instantiate_world(name_of_world):
'''instantiates the named world (class = world.[name_of_world]World)'''
Expand Down

0 comments on commit 5c29da6

Please sign in to comment.