* 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