Aid Defense Allocation Simulator

Aid Defense Allocation Simulator preview image

1 collaborator

Default-person Artem Serdyuk (Author)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by the author
Model was written in NetLogo 6.4.0 • Viewed 15 times • Downloaded 1 time • Run 0 times
Download the 'Aid Defense Allocation Simulator' modelDownload this modelEmbed this model

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

; IADS Missile Battery Simulation
; Based on Han, Lunday & Robbins (2016)

globals [
  city-size          ; size of city patches
  initial-total-value  ; store initial total value for comparison
  total-intercepted-missiles  ; all intercepted missiles to count air defense effeciency
  attack-complete?   ; stop flag for BehaviorSpace
]

patches-own [
  coverage-intensity  ; for visualizing overlapping coverage
  damage-level        ; for visualizing city damage
]

breed [cities city]
breed [batteries battery]
breed [missiles missile]

cities-own [
  value       ; city value/population
  protected?  ; whether city is protected by battery
]

batteries-own [
  remaining-interceptors  ; number of interceptors left
]

missiles-own [
  target        ; targeted city
  intercepted?  ; whether missile has been intercepted
]

to setup
  clear-all
  setup-globals
  setup-cities
  setup-batteries
  set initial-total-value sum [value] of cities
  set total-intercepted-missiles 0
  set attack-complete? false
  update-protection-status
  update-visualizations
  reset-ticks
end 

to setup-globals
  set city-size 1
  ask patches [
    set coverage-intensity 0
    set damage-level 0
  ]
end 

to setup-cities
  ; Create cities with random locations and values
  create-cities num-cities [
    setxy random-xcor random-ycor
    set size city-size
    set shape "circle"
    set color blue
    set value 10 + random 90 ; Random value between 10-100
    set protected? false
    set label (value)
  ]
end 

to setup-batteries
  ask batteries [die]  ; Clear any existing batteries

  (ifelse
    defender-strategy = "highest-value" [
      ; Create a list of cities sorted by decreasing value
      let sorted-cities sort-on [(- value)] cities
      create-batteries num-batteries [
        ; Place each battery at one of the highest-value cities
        let target-city item (who mod length sorted-cities) sorted-cities
        move-to target-city
        initialize-battery
      ]
    ]

    defender-strategy = "max-coverage" [
      create-batteries num-batteries [
        ; For each battery, find the position that maximizes the total value of covered cities
        let best-position max-one-of patches [
          ; Sum the values of all cities within range of this position
          sum [value] of cities in-radius battery-range
        ]
        move-to best-position
        initialize-battery

        ; If batteries overlap too much, adjust position while maintaining good coverage
        while [any? other batteries in-radius (battery-range / 3)] [
          let alternative-position max-one-of patches with [
            not any? batteries in-radius (battery-range / 3)
          ][
            sum [value] of cities in-radius battery-range
          ]
          if alternative-position != nobody [move-to alternative-position]
        ]
      ]
    ]

    defender-strategy = "choke-points" [
      ; First identify strategic points that cover multiple cities
      let strategic-points patches with [
        count cities in-radius battery-range >= 2  ; Points covering at least 2 cities
      ]

      create-batteries num-batteries [
        ifelse any? strategic-points [
          ; Find the strategic point that protects the highest total city value
          let best-point max-one-of strategic-points [
            sum [value] of cities in-radius battery-range
          ]
          move-to best-point
          ; Remove this point and surrounding area from consideration
          ask strategic-points in-radius (battery-range / 2) [
            set strategic-points strategic-points with [self != myself]
          ]
        ][
          ; If no good strategic points left, fall back to highest-value strategy
          let target-city max-one-of cities [value]
          move-to target-city
        ]
        initialize-battery
      ]
    ]

 defender-strategy = "distributed" [
  create-batteries num-batteries [
    ; First try to cover uncovered cities
    let uncovered-cities cities with [
      not any? batteries in-radius battery-range
    ]

    ifelse any? uncovered-cities [
      ; Instead of checking each uncovered city, select from top valuable ones
      let target-city max-one-of (up-to-n-of 5 uncovered-cities) [value]
      move-to target-city
    ][
      ; Instead of checking all patches, only check near cities
      let potential-positions patches with [
        any? cities in-radius battery-range and
        not any? batteries in-radius (battery-range / 2)
      ]
      ifelse any? potential-positions [
        let target-position max-one-of (up-to-n-of 10 potential-positions) [
          count cities in-radius battery-range with [
            count batteries in-radius battery-range < 2
          ]
        ]
        move-to target-position
      ][
        ; If no good positions found, just move to highest value city
        move-to max-one-of cities [value]
      ]
    ]
    initialize-battery
  ]
]

  defender-strategy = "mixed" [
      ; Split total batteries among strategies
      let remaining-batteries num-batteries
      let base-strategies ["highest-value" "max-coverage" "choke-points" "distributed"]

      foreach base-strategies [strategy ->
        if remaining-batteries > 0 [
          ; Allocate some batteries to this strategy
          let strategy-batteries ceiling (remaining-batteries / (length base-strategies))
          set remaining-batteries remaining-batteries - strategy-batteries

          if strategy = "highest-value" [
            let sorted-cities sort-on [(- value)] cities
            create-batteries strategy-batteries [
              let target-city item (who mod length sorted-cities) sorted-cities
              move-to target-city
              initialize-battery
            ]
          ]

          if strategy = "max-coverage" [
            create-batteries strategy-batteries [
              let best-position max-one-of patches [
                sum [value] of cities in-radius battery-range
              ]
              move-to best-position
              initialize-battery

              while [any? other batteries in-radius (battery-range / 3)] [
                let alternative-position max-one-of patches with [
                  not any? batteries in-radius (battery-range / 3)
                ][
                  sum [value] of cities in-radius battery-range
                ]
                if alternative-position != nobody [move-to alternative-position]
              ]
            ]
          ]

          if strategy = "choke-points" [
            let strategic-points patches with [
              count cities in-radius battery-range >= 2
            ]

            create-batteries strategy-batteries [
              ifelse any? strategic-points [
                let best-point max-one-of strategic-points [
                  sum [value] of cities in-radius battery-range
                ]
                move-to best-point
                ask strategic-points in-radius (battery-range / 2) [
                  set strategic-points strategic-points with [self != myself]
                ]
              ][
                let target-city max-one-of cities [value]
                move-to target-city
              ]
              initialize-battery
            ]
          ]

          if strategy = "distributed" [
            create-batteries strategy-batteries [
              let uncovered-cities cities with [
                not any? batteries in-radius battery-range
              ]

              ifelse any? uncovered-cities [
                let target-city max-one-of uncovered-cities [value]
                move-to target-city
              ][
                let target-position max-one-of patches [
                  count cities in-radius battery-range with [
                    count batteries in-radius battery-range < 2
                  ]
                ]
                move-to target-position
              ]
              initialize-battery
            ]
          ]
        ]
      ]
    ]
  )
end 

; Helper procedure to set up individual battery properties

to initialize-battery
  set shape "triangle"
  set color red
  set size 2
  set remaining-interceptors num-interceptors
end 

to update-protection-status
  ; Reset protection status for all cities
  ask cities [
    set protected? false
  ]

  ; Mark cities as protected if they are within range of any battery with interceptors
  ask cities [
    let city-batteries batteries in-radius battery-range
    if any? city-batteries [
      if sum [remaining-interceptors] of city-batteries > 0 [
        set protected? true
        set color green
      ]
    ]
  ]
end 

to go
if not attack-complete? [    ; Only launch attack if not already done
    launch-attack
    while [any? missiles] [
      move-missiles
      intercept-missiles
      destroy-cities
      update-protection-status
      update-visualizations
      update-plots1
      tick
    ]
    set attack-complete? true  ; Set flag when attack is done
  ]
end 

to launch-attack
 (ifelse
   attacker-strategy = "highest-value" [
     ; Target the most valuable cities first
     let high-value-targets sort-on [(- value)] cities
     let missiles-remaining num-missiles

     foreach high-value-targets [target1 ->
       ; Stop if we run out of missiles
       if missiles-remaining > 0 [
         create-missiles 1 [
           setup-missile target1
           set missiles-remaining missiles-remaining - 1
         ]
       ]
     ]
   ]

   attacker-strategy = "spread-attack" [
     ; Distribute missiles evenly across as many cities as possible
     let num-targets min list num-missiles count cities
     let target-cities n-of num-targets cities

     foreach sort target-cities [target1 ->
       create-missiles 1 [
         setup-missile target1
       ]
     ]
   ]

   attacker-strategy = "minimal-breach" [
     ; Find a valuable target and concentrate enough missiles to overwhelm its defenses
     let target1 max-one-of cities [
       value * (1 + count batteries in-radius battery-range)  ; Consider both value and defense
     ]

     if target1 != nobody [
       ; Calculate missiles needed to overwhelm defenses
       let defending-batteries batteries with [distance target1 <= battery-range]
       let total-interceptors sum [remaining-interceptors] of defending-batteries
       let missiles-needed min list (total-interceptors + 1) num-missiles

       ; Launch concentrated attack
       repeat missiles-needed [
         create-missiles 1 [
           setup-missile target1
         ]
       ]
     ]
   ]

 attacker-strategy = "concentrated" [
 let primary-target max-one-of cities [value]

 if primary-target != nobody [
   let nearby-cities cities with [
     distance primary-target <= battery-range / 2 and self != primary-target
   ]

   ; Create list of all potential targets
   let target-list (list primary-target)
   if any? nearby-cities [
     set target-list sentence target-list (sort-on [(- value)] nearby-cities)
   ]

   ; Distribute missiles among targets
   let missiles-per-target ceiling (num-missiles / length target-list)
   foreach target-list [target-city ->
     let missiles-to-create min list missiles-per-target (num-missiles - count missiles)
     repeat missiles-to-create [
       create-missiles 1 [
         setup-missile target-city
       ]
     ]
   ]
 ]
]

attacker-strategy = "mixed" [
      let strategies ["highest-value" "spread-attack" "minimal-breach" "concentrated"]
      let remaining-missiles num-missiles

      ; Randomly assign missiles to different strategies
      while [remaining-missiles > 0] [
        let current-strategy one-of strategies
        let missiles-for-strategy 1 + random (min list remaining-missiles (num-missiles / 2))
        set remaining-missiles remaining-missiles - missiles-for-strategy

        ; Apply the chosen strategy for this subset of missiles
        if current-strategy = "highest-value" [
          let high-value-targets sort-on [(- value)] cities
          foreach high-value-targets [target1 ->
            if missiles-for-strategy > 0 [
              create-missiles 1 [
                setup-missile target1
                set missiles-for-strategy missiles-for-strategy - 1
              ]
            ]
          ]
        ]

        if current-strategy = "spread-attack" [
          let num-targets min list missiles-for-strategy count cities
          let target-cities n-of num-targets cities
          foreach sort target-cities [target1 ->
            if missiles-for-strategy > 0 [
              create-missiles 1 [
                setup-missile target1
                set missiles-for-strategy missiles-for-strategy - 1
              ]
            ]
          ]
        ]

        if current-strategy = "minimal-breach" [
          let target1 max-one-of cities [
            value * (1 + count batteries in-radius battery-range)
          ]
          if target1 != nobody [
            let defending-batteries batteries with [distance target1 <= battery-range]
            let total-interceptors sum [remaining-interceptors] of defending-batteries
            let missiles-needed min list (min list (total-interceptors + 1) missiles-for-strategy) missiles-for-strategy
            repeat missiles-needed [
              create-missiles 1 [
                setup-missile target1
              ]
            ]
            set missiles-for-strategy missiles-for-strategy - missiles-needed
          ]
        ]

        if current-strategy = "concentrated" [
          let primary-target max-one-of cities [value]
          if primary-target != nobody [
            let nearby-cities cities with [
              distance primary-target <= battery-range / 2 and self != primary-target
            ]
            let target-list (list primary-target)
            if any? nearby-cities [
              set target-list sentence target-list (sort-on [(- value)] nearby-cities)
            ]
            let missiles-per-target ceiling (missiles-for-strategy / length target-list)
            foreach target-list [target-city ->
              let missiles-to-create min list missiles-per-target missiles-for-strategy
              repeat missiles-to-create [
                create-missiles 1 [
                  setup-missile target-city
                ]
              ]
              set missiles-for-strategy missiles-for-strategy - missiles-to-create
            ]
          ]
        ]
      ]
    ]
    )
end 

; Helper procedure for missile setup

to setup-missile [target-city]
  setxy random-xcor max-pycor
  set target target-city
  ifelse random 2 = 0
  [ setxy random-xcor max-pycor ]  ; top of screen
  [ setxy max-pxcor random-ycor ]  ; right side
  set target target-city
  set color orange
  set size 1
  set shape "arrow"
  set intercepted? false
  set xcor xcor + random 10 - 5  ; Add some randomness to launch position
end 

to move-missiles
  ask missiles [
    face target
    forward 1
    if show-damage? [
      ask patches in-radius 0.5 [
        set pcolor orange - 2
      ]
    ]
  ]
end 

to intercept-missiles
  ask batteries [
    let nearby-missiles missiles in-radius battery-range
    foreach sort nearby-missiles [ m ->
      if remaining-interceptors > 0 and not [intercepted?] of m [
        if random-float 1 < intercept-prob [
          ask m [
            set intercepted? true
            set total-intercepted-missiles total-intercepted-missiles + 1  ; Track successful interceptions
            ; Create explosion effect
            ask patches in-radius 1 [
              set pcolor yellow
            ]
            die
          ]
        ]
        set remaining-interceptors remaining-interceptors - 1
      ]
    ]
  ]
end 

to destroy-cities
  ask missiles [
    if distance target < 1 [  ; target is single turtle not agentset
      ask target [
        set color red
        set protected? false
        set damage-level damage-level + 1
        ask patches in-radius (city-size * 2) [
          set pcolor red
          set damage-level damage-level + 1
        ]
      ]
      die
    ]
  ]
end 

to update-visualizations
  ; Clear previous visualizations
  ask patches [
    set coverage-intensity 0
    if not show-damage? [set pcolor black]
  ]

  ; Update battery coverage visualization with smoother gradients
  if show-coverage? [
    ask batteries [
      let curr-battery self
      ask patches in-radius battery-range [
        let dist distance curr-battery
        let intensity (1 - (dist / battery-range)) * 2
        set coverage-intensity coverage-intensity + intensity
        set pcolor scale-color blue coverage-intensity 2 0
      ]
    ]
  ]

  ; Update damage visualization with smoother gradients
  if show-damage? [
    ask cities [
      ifelse protected? [
        set color green
      ][
        ifelse damage-level > 0 [
          set color scale-color red damage-level 5 0
          set label (word "V:" value " D:" damage-level)
        ][
          set color blue
        ]
      ]
      ; Show damage radius with smooth gradient
      if damage-level > 0 [
        ask patches in-radius (city-size * 3) [
          let dist distance myself
          let dmg-intensity (1 - (dist / (city-size * 3))) * damage-level
          if dmg-intensity > 0 [
            set pcolor scale-color red dmg-intensity 5 0
          ]
        ]
      ]
    ]
  ]

  ; Draw range indicators for batteries with smooth edges
  ask batteries [
    ; Display remaining interceptors
    set label (word remaining-interceptors " IM")
    set label-color white
  ]

  ; Update display for missiles and effects
  ask missiles [
    set color orange
  ]
end 

; Basic value reporters

to-report total-city-value
  report sum [ifelse-value (damage-level = 0) [value] [0]] of cities
end 

to-report protected-value
  report sum [ifelse-value (protected?) [value] [0]] of cities
end 

to-report protection-percentage
  ifelse total-city-value > 0
    [ report (protected-value / total-city-value) * 100 ]
    [ report 0 ]
end 
; Strategic effectiveness reporters

to-report city-value-survival-ratio
  ifelse initial-total-value > 0
    [ report precision ((total-city-value / initial-total-value) * 100) 2 ]
    [ report 0 ]
end 

to-report defense-efficiency
  ; Measures how efficiently interceptors are being used
  let total-initial-interceptors (num-batteries * num-interceptors)
  let used-interceptors total-initial-interceptors - sum [remaining-interceptors] of batteries
  ifelse used-interceptors > 0
    [ report precision ((total-intercepted-missiles / used-interceptors) * 100) 2 ]
    [ report 0 ]
end 

to-report defense-coverage-ratio
  ; Measures what percentage of total city value is under SAM coverage
  let total-value sum [value] of cities
  let covered-value sum [value] of cities with [any? batteries in-radius battery-range]
  ifelse total-value > 0
    [  report precision  ( (covered-value / total-value) * 100) 2 ]
    [ report 0 ]
end 

to-report value-loss-percentage
  ; Measures percentage of total value lost to successful attacks
  ifelse initial-total-value > 0
    [ report ((initial-total-value - total-city-value) / initial-total-value) * 100 ]
    [ report 0 ]
end 

to-report intercept-success-rate
  ; Measures percentage of missiles successfully intercepted
  let total-launched count missiles + count missiles with [intercepted?]
  ifelse total-launched > 0
    [ report (count missiles with [intercepted?] / total-launched) * 100 ]
    [ report 0 ]
end 

to-report defense-saturation
  ; Measures how close batteries are to being overwhelmed
  let avg-interceptors mean [remaining-interceptors] of batteries
  report (avg-interceptors / 20) * 100  ; 20 is initial interceptor count
end 

to-report attack-concentration
  ; Measures how concentrated the attack is
  let targeted-cities length remove-duplicates [target] of missiles
  ifelse count missiles > 0
    [ report (targeted-cities / count missiles) * 100 ]
    [ report 0 ]
end 

to-report high-value-targeting-ratio
  ; Measures focus on high-value targets
  let top-value max [value] of cities
  let targeted-value mean [value] of cities with [any? missiles with [target = myself]]
  ifelse top-value > 0
    [ report (targeted-value / top-value) * 100 ]
    [ report 0 ]
end 

to update-plots1
  set-current-plot "Total Cities Value"
  set-current-plot-pen "Total"
  plot total-city-value
  set-current-plot-pen "Protected"
  plot protected-value

  set-current-plot "Protection Metrics"
  set-current-plot-pen "Protection %"
  plot protection-percentage
  set-current-plot-pen "Value Loss %"
  plot value-loss-percentage

  set-current-plot "Battle Status"
  set-current-plot-pen "Active Missiles"
  plot count missiles
  set-current-plot-pen "Interceptors Left"
  plot sum [remaining-interceptors] of batteries
  set-current-plot-pen "Success Rate"
  plot intercept-success-rate
end 

There are 2 versions of this model.

Uploaded by When Description Download
Artem Serdyuk 13 days ago Fixed Nowrap error Download this version
Artem Serdyuk 13 days ago Initial upload Download this version

Attached files

File Type Description Last updated
Aid Defense Allocation Simulator.png preview Preview for 'Aid Defense Allocation Simulator' 13 days ago, by Artem Serdyuk Download

This model does not have any ancestors.

This model does not have any descendants.