Modeling Bunny&Wolf Population

Joy Huang
Data Mining the City
4 min readSep 26, 2018
The fields are a perfect hunting ground for wolves

The goal was to create a simulation modeled after populations of rabbits and wolves in the wild. The rabbit population, if left uncheck, grows exponentially, reproducing within seconds of contact with each other. Bunnies are set to die after reproducing 3 times.

initializing bunnies

Set bunnies with “r” and wolves with “w”, then SPACE to begin simulation.

bunnies really go at it

Wolves exhibit hunting behavior by speeding up when within proximity to a rabbit. When a wolf successfully catches a rabbit, it eats it, and the rabbit dies.

initializing wolves

Running the simulation several times, it becomes apparent that wolves are quite adept at reducing rabbit populations, as long as there are 6+ wolves.

so many rabbits to eat, so little time

Who will win in the battle for survival largely depends on the starting populations of each species.

both species are hard at work
hungry wolves win this round

Semester project summary: https://medium.com/@jaybuns/semester-project-ideas-b8cc69fc6eaf

import random
import math
xMax = 1500
yMax = 1500
class Rabbit:
def __init__(self, xPos, yPos, startSim=False):
self.xPos = xPos
self.yPos = yPos
self.repNum = 0
self.startSim = startSim

self.speed = random.randint(5,10)
self.direction = random.uniform(0, PI*2)

def display(self):
#img needs resizing
image(bunImg, self.xPos, self.yPos, 50, 75)
if self.startSim == True:
self.xPos = self.xPos + self.speed * cos(self.direction) + random.randint(-10,10)
self.yPos = self.yPos + self.speed * sin(self.direction) + random.randint(-10,10)

if self.xPos >= xMax:
self.xPos = 0
elif self.xPos <= 0:
self.xPos = xMax
if self.yPos >= yMax:
self.yPos = 0
elif self.yPos <= 0:
self.yPos = yMax

def beginSim(self):
self.startSim = True

def reproduce(self):
self.repNum += 1
def changeDir(self, wolf):
self.direction = math.atan((self.yPos-wolf.yPos)/(self.xPos-wolf.xPos+1)) if (self.xPos-wolf.xPos) == 0 else math.atan((self.yPos-wolf.yPos)/(self.xPos-wolf.xPos+1))
self.speed = 10


class Wolf:
def __init__(self, xPos, yPos, startSim=False):
self.xPos = xPos
self.yPos = yPos
self.bunSnack = 0
self.startSim = startSim

self.speed = random.randint(5, 10)
self.direction = random.uniform(0, PI*2)

def display(self):
#img needs resizing
image(wolfImg, self.xPos, self.yPos, 100, 110)
if self.startSim == True:
self.xPos = self.xPos + self.speed * cos(self.direction) + random.randint(-10,10)
self.yPos = self.yPos + self.speed * sin(self.direction) + random.randint(-10,10)

if self.xPos >= xMax:
self.xPos = 0
elif self.xPos <= 0:
self.xPos = xMax
if self.yPos >= yMax:
self.yPos = 0
elif self.yPos <= 0:
self.yPos = yMax

def eatBun(self):
self.bunSnack += 1

def chase(self, rabbit):
self.direction = math.atan((rabbit.yPos-self.yPos)/(rabbit.xPos-self.xPos+1)) if (rabbit.xPos-self.xPos) == 0 else math.atan((rabbit.yPos-self.yPos)/(rabbit.xPos-self.xPos+1))
self.speed = 15

def beginSim(self):
self.startSim = True
bunList = []
wolfList = []
maxBun = 100
maxWolf = 3
def setup():
size(xMax, yMax)
global bunImg
global wolfImg
global plantImg, groundImg, rockImg

bunImg = loadImage('bunimg.png')
wolfImg = loadImage('wolfimg.png')
rockImg = loadImage('rock.png')
plantImg = loadImage('plant.png')
groundImg = loadImage('ground.png')
def keyPressed():
if key == 'w':
new_wolf = Wolf(mouseX, mouseY)
wolfList.append(new_wolf)
elif key == 'r':
new_bun = Rabbit(mouseX, mouseY)
bunList.append(new_bun)
elif key == ' ':
for wolf in wolfList:
wolf.beginSim()
for rabbit in bunList:
rabbit.beginSim()
def gradient():

noStroke()
g = color(30,73,91)
y = color(103,181,139)
gradientSteps = 100 #how detailed will the gradient be
gradientStripWidth = height/gradientSteps
i = 0
while i < gradientSteps:
i+=1
t = map(i,0,gradientSteps,0.0,1.0);
interpolatedColor = lerpColor(g,y,t);
fill(interpolatedColor)
rect(i*gradientStripWidth,0,gradientStripWidth,height)
def environ():


for p in range(width):
for q in range (height):
if q%2 == 0:
image(plantImg, p*300+100, q*200+100, 100, 100)
def draw():
background(106, 155, 51)
gradient()
#environ()

for wolf in wolfList:
wolf.display()
for rabbit in bunList:
rabbit.display()
bunPair()
bunChase()
bunEat()
print 'bun count: ', len(bunList)
print 'wolf count: ', len(wolfList)
def bunPair():
toRemove = []
newBuns = []
for r_i in range(len(bunList)):
for b_i in range(r_i+1, len(bunList)):
r = bunList[r_i]
b = bunList[b_i]
if abs(r.xPos - b.xPos) < 10 and abs(r.yPos - b.yPos) < 10 and len(bunList) < maxBun: #finding spatial conditions for reproduction
r.reproduce() #+1 reproduction count
b.reproduce()
babyBun = Rabbit((r.xPos + b.xPos)/2, (r.yPos + b.yPos)/2, startSim=True) #create baby bunny with location midpoint of first 2
r.xPos = random.randint(0, xMax)
r.yPos = random.randint(0, yMax)
b.xPos = random.randint(0, xMax)
b.yPos = random.randint(0, yMax)
newBuns.append(babyBun) #adding new bunny to rabbit list
if r.repNum > 3: #condition for deleting bun
toRemove.append(r_i)
if b.repNum > 3:
toRemove.append(b_i)
for deceasedBun_i in sorted(toRemove, reverse=True):
bunList.pop(deceasedBun_i)
bunList.extend(newBuns)

def bunChase():
toRemove = []
for w_i in range(len(wolfList)):
for r_i in range(len(bunList)):
w = wolfList[w_i]
r = bunList[r_i]
if abs(w.xPos - r.xPos) < 30 and abs(w.yPos - r.yPos) < 30: #finding spatial conditions for reproduction
w.chase(r)
r.changeDir(w)

def bunEat():
toRemoveBun = []
toRemoveWolf = []
newWolves = []
for w_i in range(len(wolfList)):
for r_i in range(len(bunList)):
w = wolfList[w_i]
r = bunList[r_i]
if abs(w.xPos - r.xPos) < 10 and abs(w.yPos - r.yPos) < 10: #finding spatial conditions for reproduction
w.eatBun()
toRemoveBun.append(r_i)
if w.bunSnack > 3:
toRemoveWolf.append(w_i)
babyWolf = Wolf(w.xPos + random.randint(-50, 50), w.yPos + random.randint(-50, 50), startSim=True)
newWolves.append(babyWolf)
for deceasedBun_i in sorted(toRemoveBun, reverse=True):
bunList.pop(deceasedBun_i)
for deceasedWolf_i in sorted(list(set(toRemoveWolf)), reverse=True):
wolfList.pop(deceasedWolf_i)
wolfList.extend(newWolves)

--

--