Missile Attack Evacuation
Model was written in NetLogo 6.4.0
•
Viewed 42 times
•
Downloaded 2 times
•
Run 0 times
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
Comments and Questions
Please start the discussion about this model!
(You'll first need to log in.)
Click to Run Model
extensions [palette] globals [ building1-coordinates building2-coordinates shelter-coordinates-top ; New shelter coordinates shelter-coordinates-bottom ; New shelter coordinates in-shelter-top-count ; Track people in top shelter in-shelter-bottom-count ; Track people in bottom shelter shelter-top-occupants ; Current count in top shelter shelter-bottom-occupants ; Current count in bottom shelter missile-targets explosion-areas impact-areas casualties injured-count floor-colors exits missiles-launched pending-explosions simulation-complete initial-reaction-percentage ; Store initial reaction percentage first-hit ; Track if first missile has hit early-evacuees ; People who left before first missile hit late-evacuees ; People who left after first missile hit shelter-reached ; People who made it to shelter building-stayers ; People who chose to stay in building ] breed [building-occupants building-occupant] breed [missiles missile] breed [explosions explosion] breed [exit-visuals exit-visual] breed [floor-labels floor-label] exit-visuals-own [ floor-number building-number ] building-occupants-own [ in-building? ; Whether currently in building in-shelter? ; Whether in shelter health ; Health status target ; Current target (exit or person to follow) following-who ; Who am I following (nobody if going to exit) building-number ; Which building floor-number ; Which floor evacuation-speed ; Movement speed reacting? ; Whether reacting to alarm next-exit ; Next chosen exit waiting-time ; Time spent waiting switch-chance ; Probability of switching exits (starts at 0.5) chosen-shelter ; "top" or "bottom" shelter-attempt-count ; Track how many times tried to enter a full shelter waiting-at-shelter? ; Whether currently waiting outside shelter evacuation-decision ; "shelter", "stay", or "none" evacuation-timing ; "early", "late", or "none" ] missiles-own [ impact-point explosion-radius speed ] explosions-own [ duration radius ] to setup clear-all set-colors setup-globals setup-buildings setup-shelter setup-people set first-hit false set initial-reaction-percentage reaction-percentage set missiles-launched 0 set simulation-complete false reset-ticks end to set-colors ; New dynamic color generation based on number-of-floors set floor-colors [] let base-color 140 ; Darkest blue let color-step (255 - base-color) / (number-of-floors - 1) let i 0 repeat number-of-floors [ let current-color base-color + (i * color-step) set floor-colors lput (list current-color current-color 255) floor-colors set i i + 1 ] end to setup-globals set exits [] set explosion-areas [] set casualties 0 set injured-count 0 set in-shelter-top-count 0 set in-shelter-bottom-count 0 set missile-targets [] set pending-explosions [] set impact-areas [] end to setup-buildings let building-width 16 let building-height 24 let b1x (min-pxcor + building-width) let b1y 10 let b2x (max-pxcor - building-width) let b2y 10 create-building b1x b1y building-width building-height 1 create-building b2x b2y building-width building-height 2 set building1-coordinates (list b1x b1y building-width building-height) set building2-coordinates (list b2x b2y building-width building-height) end to setup-shelter ; Create two shelters, top and bottom let shelter-width 14 let shelter-height 6 ; Bottom shelter let shelter-bottom-x 0 let shelter-bottom-y (min-pycor + 8) ; Top shelter let shelter-top-x 0 let shelter-top-y (max-pycor - 8) ; Store coordinates for both shelters set shelter-coordinates-bottom (list shelter-bottom-x shelter-bottom-y shelter-width shelter-height) set shelter-coordinates-top (list shelter-top-x shelter-top-y shelter-width shelter-height) ; Create bottom shelter visuals ask patches with [ pxcor >= shelter-bottom-x - (shelter-width / 2) and pxcor <= shelter-bottom-x + (shelter-width / 2) and pycor >= shelter-bottom-y - (shelter-height / 2) and pycor <= shelter-bottom-y + (shelter-height / 2) ] [ set pcolor gray + 2 ] ; Create top shelter visuals ask patches with [ pxcor >= shelter-top-x - (shelter-width / 2) and pxcor <= shelter-top-x + (shelter-width / 2) and pycor >= shelter-top-y - (shelter-height / 2) and pycor <= shelter-top-y + (shelter-height / 2) ] [ set pcolor gray + 2 ] ; Create shelter labels create-floor-labels 1 [ setxy shelter-bottom-x (shelter-bottom-y + 1) set label "SHELTER" set color black ] create-floor-labels 1 [ setxy shelter-top-x (shelter-top-y + 1) set label "SHELTER" set color black ] end to setup-people let total-occupants initial-people let occupants-per-building floor (total-occupants / 2) ; Calculate base number of people per floor (minimum) let base-per-floor floor (occupants-per-building / number-of-floors) ; Calculate remaining people to distribute randomly let remaining-building1 (occupants-per-building - (base-per-floor * number-of-floors)) ; Building 1 population distribution let building1-floor-counts [] repeat number-of-floors [ set building1-floor-counts lput base-per-floor building1-floor-counts ] ; Distribute remaining people randomly across floors for building 1 repeat remaining-building1 [ let floor-index random number-of-floors let current-count item floor-index building1-floor-counts set building1-floor-counts replace-item floor-index building1-floor-counts (current-count + 1) ] ; Building 2 calculations and similar distribution let occupants-building2 (total-occupants - occupants-per-building) let base-per-floor2 floor (occupants-building2 / number-of-floors) let remaining-building2 (occupants-building2 - (base-per-floor2 * number-of-floors)) let building2-floor-counts [] repeat number-of-floors [ set building2-floor-counts lput base-per-floor2 building2-floor-counts ] repeat remaining-building2 [ let floor-index random number-of-floors let current-count item floor-index building2-floor-counts set building2-floor-counts replace-item floor-index building2-floor-counts (current-count + 1) ] ; Create people in both buildings using the floor counts foreach range number-of-floors [ floor1 -> create-people-for-building floor1 building1-floor-counts building1-coordinates 1 create-people-for-building floor1 building2-floor-counts building2-coordinates 2 ] end to setup-person-properties [floor1 building-num] set shape "person" set color green set size 1 set health 100 set floor-number floor1 set in-building? true set in-shelter? false set building-number building-num set evacuation-speed 0.5 + random-float 0.5 set reacting? reaction-percentage >= 100 or random 100 < reaction-percentage ; FIXED VERSION set waiting-time 0 set switch-chance random-float 0.5 set following-who nobody set next-exit nobody set chosen-shelter ifelse-value (random 2 = 0) ["top"] ["bottom"] set shelter-attempt-count 0 set waiting-at-shelter? false set evacuation-decision "none" set evacuation-timing "none" end to create-people-for-building [floor1 floor-counts building-coords building-num] let people-on-floor item floor1 floor-counts let x-pos item 0 building-coords let y-pos item 1 building-coords let width item 2 building-coords let height item 3 building-coords create-building-occupants people-on-floor [ ; Calculate floor position let floor-height height / number-of-floors let y-base y-pos - (height / 2) + (floor1 * floor-height) ; Random position within floor bounds setxy (x-pos - (width / 2) + 1 + random-float (width - 2)) (y-base + 1 + random-float (floor-height - 2)) setup-person-properties floor1 building-num ] end to create-building [x y width height building-number1] let floor-height height / number-of-floors let exits-per-floor number-of-exits ; Create floors with different colors foreach range number-of-floors [ floor1 -> let floor-color item floor1 floor-colors let y-base y - (height / 2) + (floor1 * floor-height) ; Create floor patches with distinct colors ask patches with [ pxcor >= x - (width / 2) and pxcor <= x + (width / 2) and pycor >= y-base and pycor < y-base + floor-height ] [ set pcolor approximate-rgb (item 0 floor-color) (item 1 floor-color) (item 2 floor-color) ] ; Create floor label create-floor-labels 1 [ setxy (x - (width / 2) + 2) (y-base + floor-height / 2) set label (floor1 + 1) set color black ] ; Create exits for this floor let exit-spacing width / (exits-per-floor + 1) let exit-num 1 repeat exits-per-floor [ let exit-x x - (width / 2) + (exit-spacing * exit-num) let exit-y y-base set exit-num exit-num + 1 ; Create door frame create-exit-visuals 1 [ setxy exit-x exit-y set color brown - 2 set shape "square" set size 2 set floor-number floor1 set building-number building-number1 ] ; Create door create-exit-visuals 1 [ setxy exit-x exit-y set color brown set shape "square" set size 1.8 set floor-number floor1 set building-number building-number1 ] ; Store exit coordinates set exits lput (list exit-x exit-y floor1 building-number1) exits ] ] end ; Distance reporter for building placement to-report distance-between [x1 y1 x2 y2] report sqrt ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) end ; Distance to exit reporter to-report distance-to-exit [occupant exit-coords] let exit-x item 0 exit-coords let exit-y item 1 exit-coords report distancexy exit-x exit-y end to move-people ask building-occupants with [health > 0 and reacting?] [ ifelse in-building? [ handle-exit-movement ][ move-towards-shelter ; This will now be called once they exit ] ] end to record-decisions ask building-occupants [ ; first round if evacuation-decision = "none" [ ifelse reacting? [ ; First tick reactors are early evacuees set evacuation-decision "shelter" ifelse first-hit = false [ set evacuation-timing "early" set early-evacuees early-evacuees + 1 ][ ; Everyone else starts as stayer set evacuation-timing "late" set late-evacuees late-evacuees + 1 ] ][ set evacuation-decision "stay" set building-stayers building-stayers + 1 ] ] ; those who changed their mind after the first explosions if evacuation-decision = "stay" and reacting?[ set evacuation-decision "shelter" set evacuation-timing "late" set building-stayers building-stayers - 1 ; Reduce stayer count set late-evacuees late-evacuees + 1 ] ] end to handle-exit-movement ; Get current floor exits let current-floor-exits filter [exit -> item 2 exit = floor-number and item 3 exit = building-number ] exits if not empty? current-floor-exits [ let nearest-exit get-nearest-exit current-floor-exits if nearest-exit != nobody [ let exit-x item 0 nearest-exit let exit-y item 1 nearest-exit ; Move towards exit face patch exit-x exit-y ; Check if path is blocked let ahead-patch patch-ahead evacuation-speed ifelse ahead-patch != nobody and count building-occupants-on ahead-patch > 2 [ ; Path is blocked - try to move sideways ifelse random 2 = 0 [rt 90] [lt 90] fd 0.1 ][ ; Path is clear - move forward fd min (list evacuation-speed 0.3) ] ; Handle exit transition when close enough if distancexy exit-x exit-y < 1 [ handle-exit-transition ] ] ] end to handle-exit-transition ifelse floor-number > 0 [ ; Move to lower floor set floor-number floor-number - 1 move-to-lower-floor set next-exit nobody ; Reset exit choice for new floor ][ ; Exit building when on ground floor set in-building? false ; Place person just outside the building let exit-x xcor let building-width 16 ; from setup-buildings if building-number = 1 [ setxy (exit-x + 2) ycor ; Move right if building 1 ] if building-number = 2 [ setxy (exit-x - 2) ycor ; Move left if building 2 ] set next-exit nobody ] end ; First, get only downward exits for current floor to-report get-downward-exits [floor-exits] let downward-exits [] foreach floor-exits [ this-exit -> let exit-floor item 2 this-exit let exit-building item 3 this-exit let this-x item 0 this-exit ; Get x coordinate of current exit ifelse exit-floor = 0 [ ; If it's a ground floor exit, it leads outside - add it set downward-exits lput this-exit downward-exits ][ ; For other floors, check if there's an exit below let connected-exit nobody foreach exits [ lower-exit -> let lower-x item 0 lower-exit let lower-y item 1 lower-exit let lower-floor item 2 lower-exit let lower-building item 3 lower-exit ; If exit is directly below (same x coordinate, one floor down) if lower-building = exit-building and lower-floor = (exit-floor - 1) and abs (lower-x - this-x) < 1 [ ; Compare with this-x set connected-exit lower-exit ] ] ; If this exit connects to a lower floor, add it if connected-exit != nobody [ set downward-exits lput this-exit downward-exits ] ] ] report downward-exits end ; Then find nearest among downward exits to-report get-nearest-exit [floor-exits] ; First get only downward exits let downward-exits get-downward-exits floor-exits ; If no downward exits found, report nobody if empty? downward-exits [ report nobody ] ; Find nearest among downward exits let closest-exit nobody let min-distance 999999 foreach downward-exits [ this-exit -> let dist distance-to-exit self this-exit if dist < min-distance [ set min-distance dist set closest-exit this-exit ] ] report closest-exit end to move-towards-shelter if not in-shelter? [ ; Only move if not already waiting at a shelter if not waiting-at-shelter? [ let target-shelter ifelse-value (chosen-shelter = "top") [shelter-coordinates-top] [shelter-coordinates-bottom] let shelter-x item 0 target-shelter let shelter-y item 1 target-shelter let target-patch patch shelter-x shelter-y if target-patch != nobody [ ; If close to shelter entrance ifelse distance target-patch < 3 [ let is-full? shelter-at-capacity? chosen-shelter ifelse not is-full? [ ; Enter shelter - move to random shelter patch let shelter-patches patches with [ pcolor = gray + 2 and (ifelse-value ([chosen-shelter] of myself = "top") [pycor > 0] [pycor < 0]) ] if any? shelter-patches [ move-to one-of shelter-patches set in-shelter? true set color green ] ][ ; Shelter is full - make decision once ; Move slightly away from shelter entrance rt 90 + random 180 fd 2 set waiting-at-shelter? true set shelter-attempt-count shelter-attempt-count + 1 ; Only try other shelter if haven't tried both yet if shelter-attempt-count = 1 [ ; 50% chance to try other shelter if random 100 < 50 [ set chosen-shelter ifelse-value (chosen-shelter = "top") ["bottom"] ["top"] set color blue ; Visual indicator of shelter switch set waiting-at-shelter? false ; Allow movement to new shelter ] ] ] ][ ; Still approaching shelter face target-patch fd min (list evacuation-speed 0.3) ] ] ] ] end to move-to-lower-floor let current-building building-number ; Find exits on the new floor let new-floor-exits filter [exit -> item 2 exit = floor-number and item 3 exit = current-building ] exits if not empty? new-floor-exits [ ; Choose random exit on new floor and move near it let target-exit one-of new-floor-exits setxy (item 0 target-exit + random-float 2 - 1) (item 1 target-exit + random-float 2) ] end to move-missiles ask missiles [ ; Move toward impact point face impact-point fd speed ; Check for impact if distance impact-point < 1 [ ; Add explosion info to pending list instead of creating directly set pending-explosions lput (list xcor ycor explosion-radius) pending-explosions die ] ] ; Handle any pending explosions from observer context handle-pending-explosions end to handle-pending-explosions foreach pending-explosions [ explosion-info -> let x-pos item 0 explosion-info let y-pos item 1 explosion-info let exp-radius item 2 explosion-info ; Create the explosion effect create-explosions 1 [ setxy x-pos y-pos set shape "circle" set color 27 ; Light orange set size 2 ; Reduced from 3 to 2 set duration 10 set radius exp-radius set explosion-areas lput (list xcor ycor radius) explosion-areas ] ; Create permanent impact visualization let impact-center patch x-pos y-pos let max-distance exp-radius ask impact-center [ ask patches in-radius max-distance [ let distance-from-center distance impact-center let impact-intensity (1 - (distance-from-center / max-distance)) if impact-intensity > 0.15 [ ; Increased threshold slightly let red-component 200 + (55 * (1 - impact-intensity)) let other-components 100 * (1 - impact-intensity) set pcolor approximate-rgb red-component other-components other-components if impact-intensity > 0.8 [ set pcolor approximate-rgb (red-component * 0.7) (other-components * 0.7) (other-components * 0.7) ] ] ] ] set impact-areas lput (list x-pos y-pos exp-radius) impact-areas ] set pending-explosions [] end to create-explosion-at [x y radius1] ; Observer procedure create-explosions 1 [ setxy x y set shape "circle" set color orange set size 3 set duration 10 set radius radius1 ; Add to tracking list set explosion-areas lput (list xcor ycor radius) explosion-areas ] end to go if simulation-complete [stop] ; Check for first missile hit and update reaction percentage if not first-hit and any? explosions [ set first-hit true adjust-reaction-percentage ] record-decisions move-people handle-missiles move-missiles handle-explosions update-casualties if missiles-launched >= number-of-missiles and not any? missiles and not any? explosions [ set simulation-complete true ] tick end to handle-missiles if missile-strategy = "immediate" [ launch-immediate-missiles ] if missile-strategy = "delayed" [ launch-delayed-missiles ] end to launch-immediate-missiles if ticks = 10 and missiles-launched < number-of-missiles [ repeat number-of-missiles [ create-missile set missiles-launched missiles-launched + 1 ] ] end to launch-delayed-missiles if ticks mod missile-delay = 0 and ticks >= 10 [ if missiles-launched < number-of-missiles [ create-missile set missiles-launched missiles-launched + 1 ] ] end to create-missile create-missiles 1 [ set shape "arrow" set color red set size 2 ; Create a target point based on strategy let target-patch nobody ifelse missile-strategy = "immediate" [ ; Target buildings directly set target-patch one-of patches with [ abs pxcor < 35 and abs pycor < 15 ] ] [ ; For delayed strategy, alternate between buildings and yard ifelse count missiles mod 2 = 0 [ ; Target buildings set target-patch one-of patches with [ abs pxcor < 35 and abs pycor < 15 ] ] [ ; Target yard areas set target-patch one-of patches with [ abs pxcor < 45 and ; Wider area for yard abs pycor < 20 ; Larger area for yard ] ] ] set impact-point target-patch setxy max-pxcor random-ycor ; Start from right edge set explosion-radius 6 ; Reduced from 10 to 6 set speed 0.5 ] end to set-building-target ; For missiles breed let target-patch one-of patches with [ (abs pxcor < 35) and (abs pycor < 15) ] set impact-point target-patch end to set-yard-target ; For missiles breed let target-patch one-of patches with [ (abs pxcor < 25) and (abs pycor < 15) ] set impact-point target-patch end to handle-explosions ask explosions [ set duration duration - 1 if duration <= 0 [ die ] let current-radius radius ask building-occupants with [health > 0] in-radius current-radius [ let damage 0 ifelse in-shelter? [ ; Reduced damage in shelters ifelse chosen-shelter = "top" [ ; Top shelter might have slightly different protection based on location set damage 4 ] [ ; Bottom shelter set damage 5 ] ] [ if in-building? [ set damage 40 ] if (not in-building?) and (not in-shelter?) [ set damage 80 ] ] let distance-factor 1 - (distance myself / current-radius) set damage damage * distance-factor set health health - damage update-person-color ] set size size + 0.1 set color 27 + (1.5 * (10 - duration)) ] end ; Add to setup procedure - reset patches to background color to-report get-floor-color [floor-num] report item floor-num floor-colors end to reset-patch-colors ask patches [ ; Reset to appropriate floor color if in building let floor-num floor ((pycor - min-pycor) / 6) ; Adjust based on your floor height if floor-num >= 0 and floor-num < 4 [ set pcolor white ] ] end to update-person-color if health <= 0 [ set color black ] if health > 0 and health < 50 [ set color red ] if health >= 50 and health < 80 [ set color yellow ] if health >= 80 [ set color green ] end to update-casualties set casualties count building-occupants with [health <= 0] set injured-count count building-occupants with [health > 0 and health < 80] end to adjust-reaction-percentage ; Increase reaction percentage to 95% after first hit let new-percentage 95 ask building-occupants with [not reacting? and health > 0] [ if random 100 < new-percentage [ set reacting? true ] ] end to-report death-count report casualties end to-report injured-people report injured-count end to-report missiles-remaining report number-of-missiles - missiles-launched end to-report shelter-status report (word "Top Shelter: " shelter-top-occupants "/" shelter-capacity " | Bottom Shelter: " shelter-bottom-occupants "/" shelter-capacity) end to-report shelter-at-capacity? [shelter-type] let shelter-patches patches with [ pcolor = gray + 2 and (ifelse-value (shelter-type = "top") [pycor > 0] [pycor < 0]) ] let current-count count building-occupants with [ in-shelter? and chosen-shelter = shelter-type and member? patch-here shelter-patches ] ; Update global counters ifelse shelter-type = "top" [set shelter-top-occupants current-count] [set shelter-bottom-occupants current-count] report current-count >= shelter-capacity end ; Reporters for plotting to-report early-evacuee-casualties report count building-occupants with [ evacuation-timing = "early" and health <= 0 ] end to-report early-evacuee-injured report count building-occupants with [ evacuation-timing = "early" and health > 0 and health < 80 ] end to-report early-evacuee-intact report count building-occupants with [ evacuation-timing = "early" and health >= 80 ] end to-report late-evacuee-casualties report count building-occupants with [ evacuation-timing = "late" and health <= 0 ] end to-report late-evacuee-injured report count building-occupants with [ evacuation-timing = "late" and health > 0 and health < 80 ] end to-report late-evacuee-intact report count building-occupants with [ evacuation-timing = "late" and health >= 80 ] end to-report stayer-casualties report count building-occupants with [ evacuation-decision = "stay" and health <= 0 ] end to-report stayer-injured report count building-occupants with [ evacuation-decision = "stay" and health > 0 and health < 80 ] end to-report stayer-intact report count building-occupants with [ evacuation-decision = "stay" and health >= 80 ] end ; Calculate percentages for plotting to-report early-evacuee-casualty-percent ifelse early-evacuees > 0 [ report (early-evacuee-casualties / early-evacuees) * 100 ][ report 0 ] end to-report early-evacuee-injured-percent ifelse early-evacuees > 0 [ report (early-evacuee-injured / early-evacuees) * 100 ][ report 0 ] end to-report late-evacuee-casualty-percent ifelse late-evacuees > 0 [ report (late-evacuee-casualties / late-evacuees) * 100 ][ report 0 ] end to-report late-evacuee-injured-percent ifelse late-evacuees > 0 [ report (late-evacuee-injured / late-evacuees) * 100 ][ report 0 ] end to-report stayer-casualty-percent ifelse building-stayers > 0 [ report (stayer-casualties / building-stayers) * 100 ][ report 0 ] end to-report stayer-injured-percent ifelse building-stayers > 0 [ report (stayer-injured / building-stayers) * 100 ][ report 0 ] end
There is only one version of this model, created 2 days ago by Artem Serdyuk.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
Missile Attack Evacuation.png | preview | Preview for 'Missile Attack Evacuation' | 2 days ago, by Artem Serdyuk | Download |
missile strike evacuation.drawio (1).png | png | Agent Logic in Simulation | 1 day ago, by Artem Serdyuk | Download |
This model does not have any ancestors.
This model does not have any descendants.