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 dead=.

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<`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<`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'

sum unit if obj_type=="dead"
replace dead=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)  ///
(line dead round, sort)

* Different specifications at the beginning of the model yield different results.

sleep 5000

graph combine $graph_list

No comments:

Post a Comment