## Thursday, June 7, 2012

### Zombie Invasion - spatial multi-agent system simulation

* This is a simulation of a zombie infestation

* Initially there is X number of people on a grid and some small percentage of zombies

* As the zombies encounter people they become zombies.

* There are also weapons boxes on the map.

* If a human encounters a weapons box then the human becomes armed with 5 shots and if that human meets a zombie that human will kill up to 5 zombies.

clear

local num_humans=10000
* Set number of weapons cases
local cases = 60

* Set the number of bullets in each weapons case
local weapon_capacity = 13

* Specify the initial percent of humans which are zombified
local percent_zombies = 1

* Specify the dimensions of the world grid
local xrange=150
local yrange=150

* Number of rounds
local num_rounds=187

* Graph interval
local graph_int = 12

* Tell stata to not graph as the simulation progresses
local draw=0

set obs `num_humans'

gen obj_id=_n

* To begin with all types are human
gen obj_type = "human"

set obs `=`num_humans'+`cases''

replace obj_type = "cases" if obj_type==""

gen zombie_rand = rbinomial(1,`percent_zombies'/100)

replace obj_type = "zombie" if zombie_rand==1 & obj_type=="human"

gen infested=0
replace infested=1 if obj_type == "zombie"

* People are distributed uniformly throughout the data.
gen x=int(runiform()*`xrange')
gen y=int(runiform()*`yrange')

* Cases are disbributed chi-squared centered in the middle of the data.
replace x=rnormal()^2 if obj_type == "cases"
sum x  if obj_type == "cases"
replace x=round((x-r(min))/(r(max)-r(min)) * `xrange')  if obj_type == "cases"

replace y=rnormal()^2  if obj_type == "cases"
sum y  if obj_type == "cases"
replace y=round((y-r(min))/(r(max)-r(min)) * `yrange')  if obj_type == "cases"

gen bullets=0

* This tells stata to either draph the graphs as it runs the code or wait till the end to draw the graphs.
if `draw'==0 local nodraw
if `draw'==1 local nodraw nodraw

two (scatter y x if obj_type=="cases", msymbol(square) color(yellow))  ///
(scatter y x if obj_type=="human" & bullets==0, mcolor(gs7) msymbol(smcircle))       ///
(scatter y x if obj_type=="human" & bullets>0, color(black) msymbol(smcircle))       ///
(scatter y x if obj_type=="zombie", mcolor(cranberry) msymbol(smcircle))             ///
, legend(label (1 "Weapons Cases")        ///
label (2 "Humans")            ///
label (3 "Armed Humans")     ///
label (4 "Zombies")          ///
rows(1))  `nodraw' title(Round 0)

two (scatter y x if obj_type=="cases", msymbol(square) color(orange) )  ///
(scatter y x if obj_type=="human" & bullets==0, mcolor(gs7) msymbol(smcircle))       ///
(scatter y x if obj_type=="human" & bullets>0, color(black) msymbol(smcircle))       ///
(scatter y x if obj_type=="zombie", mcolor(cranberry) msymbol(smcircle))             ///
, nodraw  name(round0, replace) legend(off)

global graph_list round0

gen weapon_case=1 if obj_type == "cases"

gen zombies=.
gen unarmed_humans=.
gen weapons_cases=.
gen armed_humans=.

gen unit=1

cap set obs `num_rounds'

cap forv i=1(1)`num_rounds' {
tempvar count infested zombie_encounter bullets arms move

* check if any objects share the same squere
bysort x y: gen `count' = _N if obj_type=="human"     ///
| obj_type=="zombie"

bysort x y: egen `zombie_encounter' = max(infested) if obj_type=="human" ///
| obj_type=="zombie"

bysort x y: egen `bullets' = max(bullets) if obj_type=="human"     ///
| obj_type=="zombie"

* If a human enters the same square as a zombie or another human
* Then that human either shoots the zombie or misfires shooting at the human.
* Checks to see if anybody has initially this person has bullets.
* If so this then this humans looses one bullet
replace bullets = bullets-1 if obj_type=="human" & bullets > 0 & `zombie_encounter'>0

* If the zombie encountered someone with bullets then the zombie is shot and killed
replace obj_type="dead" if obj_type=="zombie" & `bullets' > 0 & `count'>1

* Check if any of the zombies and unarmed humans share the same square with a zombie
bysort x y: egen `infested' = max(infested) if obj_type=="human" ///
| obj_type=="zombie"

replace obj_type = "zombie" if `infested' == 1 & obj_type=="human"
replace infested=1 if obj_type == "zombie"

* Now let's arm the humans
bysort x y: egen `arms' = max(weapon_case) if obj_type=="human" ///
| obj_type=="cases"

replace bullets = `weapon_capacity' if `arms'==1

* Now let's move the humans and zombies
gen `move' = int(runiform()*4)
di 1111

replace x=x+1 if  `move'==0 & (obj_type=="human" | obj_type=="zombie") ///
& x&lt;`xrange'
replace x=x-1 if  `move'==1 & (obj_type=="human" | obj_type=="zombie") ///
& x>0
replace y=y+1 if  `move'==2 & (obj_type=="human" | obj_type=="zombie") ///
& y&lt;`yrange'
replace y=y-1 if  `move'==3 & (obj_type=="human" | obj_type=="zombie") ///
& y>0

if `i'/`graph_int'==int(`i'/`graph_int') {

two (scatter y x if obj_type=="cases", msymbol(square) color(orange))  ///
(scatter y x if obj_type=="human" & bullets==0, mcolor(gs7)  msymbol(smcircle))       ///
(scatter y x if obj_type=="zombie", mcolor(cranberry) msymbol(smcircle))             ///
(scatter y x if obj_type=="human" & bullets>0, color(black) msymbol(smcircle))       ///
, legend(label (1 "Weapons Cases")        ///
label (2 "Humans")            ///
label (4 "Armed Humans")     ///
label (3 "Zombies")          ///
rows(1)) `nodraw' title(Round `i')

two (scatter y x if obj_type=="cases", msymbol(square) color(yellow))  ///
(scatter y x if obj_type=="human" & bullets==0, mcolor(gs7) msymbol(smcircle))       ///
(scatter y x if obj_type=="zombie", mcolor(cranberry) msymbol(smcircle))             ///
(scatter y x if obj_type=="human" & bullets>0, color(black) )       ///
, legend(off) nodraw name(round`i', replace)

global graph_list \$graph_list round`i'
}

sum unit if obj_type=="zombie"
replace zombies=r(N) if obj_id==`i'

sum unit if obj_type=="human" & bullets==0
replace unarmed_humans=r(N) if obj_id==`i'

sum unit if obj_type=="cases"
replace weapons_cases=r(N) if obj_id==`i'

sum unit if obj_type=="human" & bullets>0
replace armed_humans=r(N) if obj_id==`i'

noi di _c " `i'"
drop `count' `infested' `zombie_encounter' `bullets' `arms' `move'

}

sort obj_id

gen round=obj_id if zombies!=.

two (line zombies round, sort) ///
(line unarmed_humans round, sort)  ///
(line armed_humans round, sort)  ///