[Edu-sig] A simple simulation

Kirby Urner pdx4d@teleport.com
Tue, 04 Apr 2000 16:58:42 -0700


Greetings Python fans --

Took me a an hour or more to throw this together:  a simple
simulation.  Ducks, Wolves and Bugs are all subclasses of
creature with a favorite food (Wolves eat Ducks eat Bugs 
eat each other).  

Every clock cycle triggers a random happening in the life 
of each creature.  It either:  gives birth, hunts (finds 
favorite food or goes hungry), or dies.  Pretty simple.

Too simple of course.  For one thing, solo creatures of 
these types can't auto-reproduce (well, maybe some bugs...).  
I should add a "find mate" algorithm similar to the "hunt" 
one (only randomly successful).  If we're down to only 
one of a kind, no more offspring.  

Assigning the attribute male/female at random and only 
letting opposites mate would require yet more lines of code 
(but not many).  Then there's age to think about.  So 
many ways to make this more "realistic".  

And what about the environment, what about pollution
and global warming?  Some bugs might _like_ global warming.

But still, as a "cave painting", we're already well on 
the way to sketching what simulations are about. Re
"cave paintings" see:
http://www.python.org/pipermail/edu-sig/2000-February/000154.html

Here's what it looks like when running:

>>> import simula
>>> simula.run(4)
>>> --- Initialize -------
Duck1 is born
Duck2 is born
Bug1 is born
Bug2 is born
Wolf1 is born
--- Tick 0 -------
Bug1 gives birth
Bug3 is born
Duck2 gives birth
Duck3 is born
Bug1 gets eaten by Duck1
Bug1 dies
Bug2 dies
Wolf1 gives birth
Wolf2 is born
--- Tick 1 -------
Duck2 dies
Duck1 goes hungry
Duck1 gets eaten by Wolf2
Duck1 dies
Duck3 goes hungry
Wolf1 gives birth
Wolf3 is born
Bug3 dies
--- Tick 2 -------
Wolf2 gives birth
Wolf4 is born
Wolf3 dies
Duck3 goes hungry
Duck3 gets eaten by Wolf1
Duck3 dies
--- Tick 3 -------
Wolf2 dies
Wolf1 dies
Wolf4 gives birth
Wolf5 is born

Here's the source code (simula.py module):

# primitive simulation
# by kirby urner
# oregon curriculum network
# april 4, 2000

import copy, random

creatures  = {}
counter    = {}
        
def run(n):
    setstage()
    for j in range(n):  # time spans
       print "--- Tick %s -------" % j
       for i in creatures.values():
           i.randevent()

def setstage():
    print "--- Initialize -------" 
    Duck()
    Duck()
    Bug()
    Bug()
    Wolf()

class Creature:
    
    def __init__(self):
        self.isborn()

    def isborn(self):
        species = self.__class__.__name__
        if not counter.has_key(species):
            counter[species]=0        
        counter[species] = counter[species] + 1
        self.name = species + str(counter[species])
        creatures[self.name] = self
        print self.name  + " is born"
        self.stomach = 3  # gets an initial boost (thanks mom!)
        
    def reproduces(self):
        print self.name + " gives birth"
        species = self.__class__.__name__
        newobj = copy.copy(self)  # conceived
        newobj.isborn()           # Hello World!

    def dies(self):
        print self.name + " dies"
        del creatures[self.name]  # Goodbye World!
        self = None

    def hunts(self):
        mealfound = 0
        for i in range(3):  # three chances to find favorite food
            gotcha = random.choice(creatures.values())
            if (gotcha.__class__.__name__ == self.favoritefood 
                and not (gotcha.name == self.name)): # can't eat self
                mealfound = 1
                self.stomach = self.stomach + 1
                print gotcha.name + " gets eaten by " + self.name
                gotcha.dies()
                break
            
        if not mealfound:  # didn't find food this time
            self.stomach = self.stomach - 1  
            print self.name + " goes hungry"

        if self.stomach == 0:  # 3 strikes and you're out
            print self.name + " starves" 
            self.die()

    def randevent(self):
        event = random.choice(range(3))  # reproduce, hunt
        if   event == 0: self.reproduces()
        elif event == 1: self.hunts()
        else:            self.dies()  # ... or die
        
class Duck(Creature):
    favoritefood = 'Bug'

class Wolf(Creature):
    favoritefood = 'Duck'

class Bug(Creature):
    favoritefood = 'Bug'