+1 (315) 557-6473 

Python Game of Rat and Berry


Python Game of Rat and Berry

Once upon a time, there was an island…

  • The island is 10 sq km in area.
  • Every day there is a 30% chance it will rain on the island.
  • When it rains, the rainfall has a normal distribution with a mean of 20 mm and a standard deviation of 5 mm.
  • Rain nourishes the local plant life. The day after it rains, the plants will produce berries. The number of berries produced is equal to (previous day’s rainfall in mm) * (area of the island in sq km) * (100).
  • Berries persist for 10 days after which they become inedible.

On the island there were rats...

  • Initially, there are 10,000 rats on the island with ages randomly chosen in the range 1 through 20 days (uniform and inclusive).
  • Every day a rat will eat a berry (randomly chosen regardless of age) if one is available somewhere on the island.
  • If a rat does not eat for 3 days, it dies.
  • After 50 days, the rat has a 5% chance of dying from old age. This probably increases by 5% every day thereafter (e.g. 5% after 50 days, 10% after 51 days, 15% after 52 days, etc.).
  • After a rat eats a total of 10 berries and every 8 berries thereafter, it will give birth to a litter of new rats. The litter size is random and uniformly distributed between 6 and 10 inclusive.

On the island, there were also cats…

  • Initially, there are 1000 cats on the island with ages randomly chosen in the range of 1 through 1000 days (uniform and inclusive).
  • Every day a cat will attempt to eat a rat. The probability that a cat will catch a rat is dependent on the density of rats on the island: p = (number of rats/area of the island in sq km) * 0.10. Notice that this probability should be capped at 100%.
  • With experience, cats become better at catching rats. A cat receives an additive bonus to its probability of catching a rat: b = age of cat * 0.015. Again, the total probability should be capped.
  • If a cat does not eat for 5 days, it dies.
  • After 2000 days, the cat has a 1% chance of dying from old age. This probably increases by 0.1% every day thereafter.
  • After a cat eats a total of 50 rats and every 35 rats thereafter, it will give birth to a litter of new cats.
  • The litter size is random and uniformly distributed between 3 and 6 inclusive.

Then, ten thousand days later…

  • Design a simulation to capture the interaction of life on the island over 10,000 days.
  • Your simulation should begin by reading parameters from a parameter file. This file should include all of the numbers in marked bold above. For example…
    • island_size = 10 o rain_chance = 0.30
    • rain_mean = 20
    • rain_std = 5
    • berry_ coefficient = 100
    • berry_persist = 10 etc.

Use classes

  • Save to file information about the rainfall and the daily population of berries, rats, and cats.
SubjectValue
island_size10
rain_chance0.3
rain_mean 20
berry_coefficient 100
rain_std 5
berry_persist 10
num_of_rats10000
rat_coefficient
 3
rat_range 20
rat_total_berries 10
rat_days50
berry_after 8
uniform_dist_start6
uniform_dist_end10
num_of_cats1000
max_cat_age1000
cat_rat_catch_prob0.1
exp_prob
 0.015
cat_days_die2000
cat_rat_eat50
cat_rat_additional35
litter_dist_start 50
litter_dist_end 35
                                  


   # -*- coding: utf-8 -*-

import pandas as pd
from numpy import random
import numpy as np

ratList = []
catList = []
berriesBasket = []

def readFile():
    'function to read a file that consist of many variables for our program'
    
    
    #use pandas read_csv function to read the variable names and values
    #as a dictionary
    dictD = pd.read_csv("data.csv", header=0, index_col=0, squeeze=True).to_dict()

    
    for key,val in dictD.items():
        islandSize = dictD['island_size']
        rainChance = dictD['rain_chance']
        rainMean = dictD['rain_mean']
        berryCoeff = dictD['berry_coefficient']
        rainStd = dictD['rain_std']
        berryPersist = dictD['berry_persist']
        numRats = dictD['num_of_rats']
        ratCoeff = dictD['rat_coefficient']
        ratRange = dictD['rat_range']
        ratTotalBerries = dictD['rat_total_berries']
        ratDays = dictD['rat_days']
        berryAfter = dictD['berry_after']
        uniformDistStart = dictD['uniform_dist_start']   
        uniformDistEnd = dictD['uniform_dist_end']
        numCats = dictD['num_of_cats']
        maxCatAge = dictD['max_cat_age']
        catRatCatchProb = dictD['cat_rat_catch_prob']
        expProb = dictD['exp_prob']
        catDaysDie = dictD['cat_days_die']
        catRatEat = dictD['cat_rat_eat']   
        catRatAdd = dictD['cat_rat_additional']
        litterDistStart = dictD['litter_dist_start']
        litterDistEnd = dictD['litter_dist_end']        
        
        
        return islandSize,rainChance,rainMean,berryCoeff,rainStd,berryPersist,numRats,ratCoeff,ratDays,ratRange,ratTotalBerries,berryAfter,uniformDistStart,uniformDistEnd,numCats,maxCatAge,catRatCatchProb,expProb,catDaysDie,catRatEat,catRatAdd,litterDistStart,litterDistEnd

# getrain
def rain():
    'function to determine if it rains'
    
    # generate a number from 1-100, if 100 is less than 30
    # then it will rain
    if random.rand() < float(readFile()[1]) :
        return 0
        # if it rains, how much will it rain
    return random.normal(float(readFile()[2]),float(readFile()[4]), size=(1, 1))[0][0]
    
def generateRat():
    """ Initialize the rats in the island """
    num_rat = int(readFile()[6])
    for i in range(num_rat):
        rat = Rats(random.randint(0, num_rat))
        ratList.append(rat)

def generateCat():
    """ Initilaze the cat in the island """
    num_cat = int(readFile()[14])
    for _ in range(0, num_cat):
        cat = Cats(random.randint(0, num_cat))
        catList.append(cat)

def deleteDeadObject():
    """ In case rat or cat is dead. Need to remove them all"""
    for berry in berriesBasket:
        if not berry.isEatable():
            berriesBasket.remove(berry)
    for rat in ratList:
        if rat.isDead():
            ratList.remove(rat)
    for cat in catList:
        if cat.isDead():
            catList.remove(cat)

# class for rats
class Rats :
    'class that represents a rat that inherits from Island'

    def __init__(self, age):
        
        #define the constructor variables
        self.ratsBirth_initBerries = int(readFile()[5])
        self.numRats = int(readFile()[6])
        self.ratCoeff = int(readFile()[7])
        self.ratDays = int(readFile()[8])
        self.ratRange = int(readFile()[9])
        self.ratTotalBerries = int(readFile()[10])
        self.berryAfter = int(readFile()[11])
        self.uniformDistStart = int(readFile()[12])
        self.uniformDistEnd = int(readFile()[13])
        self.ratsBeginAge = int(readFile()[19])
        self.days = age
        self.eatDaysAgo = 0
        self.berriesEaten = 0

    def passDay(self):
        self.days += 1
        self.eatDaysAgo += 1

    def tryEat(self):
        berriesNum = len(berriesBasket)
        if berriesNum > 0:
            r = random.randint(0, berriesNum)
            self.eatDaysAgo = 0
            self.berriesEaten += 1
            del berriesBasket[r]
    
    def isDead(self):
        """ simulate rats dead """
        if self.eatDaysAgo >= 3:
            return True
        if self.days > self.ratTotalBerries and (random.rand() < 0.01 * 0.05 * (self.days - 49)):
            return True
        return False
               
    def givingBirth(self):
        """ Simulate rat birth """
        if self.berriesEaten < self.ratsBirth_initBerries:
            return
        if (self.berriesEaten - self.ratsBirth_initBerries) % self.berryAfter == 0:
            ratsBorn = random.randint(self.uniformDistStart, self.uniformDistEnd + 1)
            for r in range(1, ratsBorn):
                ratList.append(Rats(0))
        
#class for cats
class Cats:
    'class that represents a cat'

    def __init__(self, age):
        
        #define the constructor variables
        self.islandArea = int(readFile()[0])
        self.numCats = int(readFile()[14])
        self.maxCatAge = int(readFile()[15])
        self.catchProb = float(readFile()[16])
        self.expProb = float(readFile()[17])
        self.catDaysDie = int(readFile()[18])
        self.catRatEat = int(readFile()[19])
        self.catAdditional = int(readFile()[20])
        self.litterSizeStart = int(readFile()[21])
        self.litterSizeEnd = int(readFile()[22])
        self.days = age
        self.eatDaysAgo = 0
        self.ratsEaten = 0

    def passDay(self):
        self.days += 1
        self.eatDaysAgo += 1

    def tryEat(self):
        """ Simulate eat rats """
        ratsNum = len(ratList)
        if ratsNum > 0 and(random.rand() < (self.catchProb * ratsNum) / self.islandArea + self.days * 5):
            r = random.randint(0, ratsNum)
            self.eatDaysAgo = 0
            self.ratsEaten += 1
            del ratList[r]

    def isDead(self):
        """ Simulate Cat is dead"""
        if self.eatDaysAgo >= 5: # no eat in 5 days.
            return True
        if self.days > self.catDaysDie and (random.rand() < 0.01 * (self.expProb + self.catchProb * (self.days - self.catDaysDie))):
                return True
        return False

    def givingBirth(self):
        """ Simulate cat birth """
        if self.ratsEaten < self.catRatEat:
            return
        if (self.ratsEaten - self.catRatEat) % self.catAdditional == 0:
            rats_born = random.randint(self.litterSizeEnd, self.litterSizeStart + 1)
            for k in range(0, rats_born):
                catList.append(Cats(0))

class Berry:
    def __init__(self):
        self.ageDays = 0
        self.berryPersist = int(readFile()[5])

    def isEatable(self):
        return self.ageDays <= self.berryPersist

    def passDay(self):
        self.ageDays += 1

def simulation():
    """ Simulation the assignment """
    rainn = int(0)
    generateRat()
    generateCat()
    daysLimit = 10000
    islandArea = int(readFile()[0])
    berryCoeff = float(readFile()[3])
    for i in range(1, daysLimit):
        newBerries = int(rainn * islandArea * berryCoeff)
        for berry in range(1, newBerries):
            berriesBasket.append(Berry())
        for berry in berriesBasket:
            berry.passDay()
        for rat in ratList:
            rat.tryEat()
            rat.givingBirth()
            rat.passDay()
        for cat in catList:
            cat.tryEat()
            cat.givingBirth()
            cat.passDay()
        rainn = rain()
        deleteDeadObject()

def main():
    simulation()
    daysLimit = 10000
    print("Simulator in {} days".format(str(daysLimit)))
    print("Berries population: {} ea".format(str(len(berriesBasket))))
    print("Rats population: {} ea".format(str(len(ratList))))
    print("Cats population: {} ea".format(str(len(catList))))
    out = open("output.txt", "w")
    out.write("Simulator in " + str(daysLimit) + "days\n")
    out.write("Berries population: " + str(len(berriesBasket)) + "\n")
    out.write("Rats population: " + str(len(ratList)) + "\n")
    out.write("Cats population: " + str(len(catList)) + "\n")
    out.close()

if __name__ == "__main__":
    main()