Permalink
Browse files

Refactored some classes into separate files. Added environment. Added…

… Strategy view plugin to show populations. Added per-iteration consumption and the concept of death if a critters food slips below 0
  • Loading branch information...
1 parent 5b02e5a commit 51fd11226d075b78b5b2cec4bc86eafbb911662d @bendavieshe3 committed May 25, 2011
Showing with 357 additions and 162 deletions.
  1. +76 −0 src/environment.py
  2. +3 −3 src/generations.py
  3. +200 −0 src/plugins.py
  4. +40 −13 src/strategies.py
  5. +38 −146 src/world.py
View
@@ -0,0 +1,76 @@
+'''
+Created on May 25, 2011
+
+@author: bendavies
+'''
+import critters, strategies
+
+#constants
+
+ITERATION_FOOD_CONSUMPTION = 5
+
+
+class Environment(object):
+ '''Hosts all of the objects in the simulation'''
+
+ def __init__(self):
+ '''
+ Initialises the environment
+ Usage:
+ >>> env = Environment()
+ '''
+ self.iteration_no = 0
+ self.population = list()
+ self.strategy_counts = dict()
+
+ def start_iteration(self):
+ self.iteration_no += 1
+
+ def end_iteration(self):
+ '''
+ Ends the iteration and forces all critters to consume food
+ '''
+
+ #all critters consume food
+ for critter in self.population:
+ critter.remove_food(ITERATION_FOOD_CONSUMPTION)
+
+ #if a critter has 0 or less food, he dies :(
+ if critter.food <= 0:
+ self.population.remove(critter)
+
+ def add_critter(self, critter):
+ '''
+ Adds a critter to the environment
+
+ >>> e = Environment()
+ >>> sucker = critters.Critter('s1', strategies.SuckerStrategy())
+ >>> cheater = critters.Critter('c1', strategies.CheatStrategy())
+ >>> e.add_critter(sucker)
+ >>> len(e.population)
+ 1
+ '''
+
+ if critter not in self.population:
+ self.population.append(critter)
+
+ strategy = critter.strategy.short_name
+ if strategy not in self.strategy_counts:
+ self.strategy_counts[strategy] = 1
+ else:
+ self.strategy_counts[strategy] += 1
+
+ def add_critters(self, critter_list):
+ '''
+ Add multiple critters to the environment
+ '''
+ for critter in critter_list:
+ self.add_critter(critter)
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
+
+
+
+
View
@@ -4,7 +4,7 @@
@author: ben
'''
-import sys, getopt, world
+import sys, getopt, world, plugins
def main(argv):
world_to_run = 'PrisonersDilemma'
@@ -30,10 +30,10 @@ def main(argv):
print "running world %s" % world_to_run
xworld = instantiate_world(world_to_run)
- xworld.add_plugin(world.TabularReporter())
+ xworld.add_plugin(plugins.StrategyTabularReporter())
if track_critter:
- xworld.add_plugin(world.CritterTracker(track_critter))
+ xworld.add_plugin(plugins.CritterTracker(track_critter))
xworld.run(iterations)
View
@@ -0,0 +1,200 @@
+'''
+Created on May 24, 2011
+
+@author: bendavies
+'''
+import strategies
+
+
+class EventPlugin(object):
+ '''An archetype for plugin types'''
+
+ def on_environment_start(self, environment):
+ '''called prior to the start of iterations with the initial environment'''
+ pass
+
+ def on_iteration_start(self, environment):
+ '''called at the start of the iteration'''
+ pass
+
+ def on_iteration_end(self, environment):
+ '''called at the end of the iteration'''
+ pass
+
+ def on_environment_end(self, environment):
+ '''called at the end of the simulation when the environment will no longer
+ change'''
+ pass
+
+ def on_interaction_end(self, agent1, agent1_outcome, agent2, agent2_outcome):
+ '''called at the end of an interaction between two agents'''
+ pass
+
+class IndividualTabularReporter(EventPlugin):
+ '''Provides basic text output to the standard out'''
+
+ def on_environment_start(self, environment):
+ '''called prior to the start of iterations with the initial environment'''
+ self.print_headers(environment)
+
+ def on_iteration_start(self, environment):
+ '''called at the start of the iteration'''
+ pass
+
+ def on_iteration_end(self, environment):
+ '''called at the end of the iteration'''
+ if environment.iteration_no == 1 or environment.iteration_no % 5 == 0:
+ self.print_iteration_line(environment)
+
+ def on_environment_end(self, environment):
+ '''called at the end of the simulation when the environment will no longer
+ change'''
+ print 'Final Food Totals'
+ self.print_iteration_line(environment)
+ self.print_headers(environment)
+
+ population = environment.population
+ max_food = max([critter.food for critter in population])
+ winners = [critter.name + ' ' for critter in population
+ if (critter.food == max_food)]
+ print('winners are %s' % ''.join(winners))
+
+ def print_headers(self, environment):
+ '''Write the headers'''
+ header_line = 'p:\t'
+ for critter in environment.population:
+ header_line += '%s\t' % critter.name
+ print header_line
+
+ def print_iteration_line(self, environment):
+ '''Write a reporting line for the iteration with current food values'''
+ report_line = ('%d:\t' % environment.iteration_no)
+ for critter in environment.population:
+ report_line += '%d\t' % critter.food
+ print report_line
+
+class StrategyTabularReporter(EventPlugin):
+ '''Provides basic output summarising strategy level numbers to the std out'''
+
+ def on_environment_start(self, environment):
+ '''called prior to the start of iterations with the initial environment'''
+ self.print_headers(environment)
+
+ def on_iteration_start(self, environment):
+ '''called at the start of the iteration'''
+ pass
+
+ def on_iteration_end(self, environment):
+ '''called at the end of the iteration'''
+ if environment.iteration_no == 1 or environment.iteration_no % 5 == 0:
+ self.print_iteration_line(environment)
+
+ def on_environment_end(self, environment):
+ '''called at the end of the simulation when the environment will no longer
+ change'''
+ print 'Final Population Totals'
+ critter_count, food_count = self.calculate_strategy_totals(environment)
+
+ self.print_iteration_line(environment)
+
+ #print extra food totals line
+ header_line = 'p:\t'
+ for strategy in environment.strategy_counts.keys():
+ header_line += '%s\t' % food_count[strategy]
+ print header_line
+
+ self.print_headers(environment)
+
+ max_critters = max(critter_count.values())
+ winners = [strategy + ' ' for strategy in critter_count.keys()
+ if critter_count[strategy] == max_critters]
+
+ print('winners are %s' % ''.join(winners))
+
+ def print_headers(self, environment):
+ '''Write the headers'''
+ header_line = 'p:\t'
+ for strategy in environment.strategy_counts.keys():
+ header_line += '%s\t' % strategy
+ print header_line
+
+ def print_iteration_line(self, environment):
+ '''Write a reporting line for the iteration with current food values'''
+
+ #work out strategy totals
+ critter_count, food_count = self.calculate_strategy_totals(environment)
+
+ report_line = ('%d:\t' % environment.iteration_no)
+ for strategy in environment.strategy_counts.keys():
+ report_line += '%d\t' % critter_count[strategy]
+ print report_line
+
+ def calculate_strategy_totals(self, environment):
+ food_count = dict()
+ critter_count = dict()
+ for strategy in environment.strategy_counts.keys():
+ food_count[strategy] = 0
+ critter_count[strategy] = 0
+
+ for critter in environment.population:
+ food_count[critter.strategy.short_name] += critter.food
+ critter_count[critter.strategy.short_name] += 1
+
+ return critter_count, food_count
+
+class CritterTracker(EventPlugin):
+ '''Keeps track of an individual critter and summarises their interaction at
+ the conclusion of the environment'''
+
+ def __init__(self, critter_name):
+ self.critter_name = critter_name
+ self.interactions = list()
+ super(CritterTracker, self).__init__()
+
+ def on_environment_end(self, environment):
+ '''
+ Display a summary of what the tracked critter interacted
+ '''
+ UNCOOPERATE = strategies.UNCOOPERATE
+ COOPERATE = strategies.COOPERATE
+
+ print 'Detailed interaction tracking of %s:' % self.critter_name
+
+ for interaction in self.interactions:
+ our_action = interaction[1]
+ their_action = interaction[3]
+ their_name = interaction[2]
+
+ if our_action == UNCOOPERATE and their_action == UNCOOPERATE:
+ outcome_description = 'had no interaction with'
+ elif our_action == COOPERATE and their_action == COOPERATE:
+ outcome_description = 'cooperated with'
+ elif our_action == COOPERATE:
+ outcome_description = 'was suckered by'
+ else:
+ outcome_description = 'cheated'
+
+ print '%s\t%d %d\t%s\t%s %s %s' % (self.critter_name, our_action,
+ their_action, their_name,
+ self.critter_name, outcome_description,
+ their_name)
+
+
+ def on_interaction_end(self, agent1, agent1_outcome, agent2, agent2_outcome):
+ '''called at the end of an interaction between two agents'''
+ if agent1.name == self.critter_name:
+ self.interactions.append((agent1.name,
+ agent1_outcome,
+ agent2.name,
+ agent2_outcome))
+ elif agent2.name == self.critter_name:
+ self.interactions.append((agent2.name,
+ agent2_outcome,
+ agent1.name,
+ agent1_outcome))
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
+
Oops, something went wrong.

0 comments on commit 51fd112

Please sign in to comment.