Battle of Midway VS Edits

Battle of Midway VS Edits preview image

1 collaborator

Default-person Vineet Sood (Author)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by everyone
Model was written in NetLogo 7.0.3 • Viewed 28 times • Downloaded 6 times • Run 0 times
Download the 'Battle of Midway VS Edits' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


WHAT IS IT?

(a general understanding of what the model is trying to show or explain)

HOW IT WORKS

(what rules the agents use to create the overall behavior of the model)

HOW TO USE IT

(how to use the model, including a description of each of the items in the Interface tab)

THINGS TO NOTICE

(suggested things for the user to notice while running the model)

THINGS TO TRY

(suggested things for the user to try to do (move sliders, switches, etc.) with the model)

EXTENDING THE MODEL

(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)

NETLOGO FEATURES

(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)

RELATED MODELS

(models in the NetLogo Models Library and elsewhere which are of related interest)

CREDITS AND REFERENCES

(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;;==========================================================
;; BATTLE OF MIDWAY  -  Agent-Based Model
;; INTA-6742  |  Group 28
;;
;; WORLD  :  100 x 100 patches  (wrapping OFF in View settings)
;;           1 patch = 10 nautical miles
;; TIME   :  1 tick  = 15 minutes
;;
;; DESIGN PRINCIPLE:
;;   Carriers hold roughly fixed positions (historically accurate -
;;   carriers launched aircraft while steaming slowly).
;;   Only RECON and STRIKE PLANES move meaningfully across the map.
;;   This avoids all boundary / oscillation problems.
;;
;; STARTING POSITIONS:
;;   US   carriers  x=+30, spread vertically  (NE of Midway)
;;   Japan carriers  x=-30, spread vertically  (NW of Midway)
;;   Midway Atoll    x=0, y=0
;;   Distance between fleets ~ 60 patches = 600 nm
;;
;; SPEEDS (patches / tick):
;;   Recon   2.0   (~120 kts PBY Catalina)
;;   Strike  4.0   (~240 kts SBD Dauntless)
;;   Carrier 0.2   (slow drift only)
;;
;; HISTORICAL MECHANISMS:
;;   1. US INTEL  -  US recon sectors cover 170-310 deg (NW arc)
;;                   where Japan is known to approach.
;;   2. TONE DELAY - Japan recon planes 0-1 delayed 4 ticks
;;                   (Tone catapult malfunction, ~1 hr late).
;;   3. JAPAN REARM - When Japan first detects US fleet,
;;                    all Japan carriers enter REARM for 8 ticks:
;;                    yellow colour, no launches, 2x bomb damage.
;;   4. WAVES      - Strike planes return, refuel, and relaunch
;;                    continuously until their carrier sinks.
;;
;; SLIDERS (create in Interface tab, do NOT add to globals):
;;   num-us-recon     0-36   default 18
;;   num-japan-recon  0-28   default 14
;;
;; MONITORS (create in Interface tab):
;;   us-carriers-alive    japan-carriers-alive
;;   avg-us-health        avg-japan-health
;;   ticks                first-hit-tick
;;   rearm-ticker         contacts
;;==========================================================

breed [ carriers  one-carrier ]
breed [ recons    one-recon   ]
breed [ strikers  one-striker ]

carriers-own [
  fside          ;; "US" or "JAPAN"
  cname
  hp             ;; 0-100; sinks at 0
  cstate         ;; "active" "rearm" "sunk"
  rearm-timer    ;; countdown ticks for REARM state
]

recons-own [
  fside
  rstate         ;; "out" "home" "refuel" "dead"
  rfuel
  smax-fuel
  route          ;; outbound compass heading for this plane
  late-start     ;; Tone delay: ticks before this plane can fly
  spotted?       ;; has found enemy fleet
  base-x
  base-y
]

strikers-own [
  fside
  sstate         ;; "deck" "flying" "returning" "dead"
  sfuel
  smax-fuel
  home-ship      ;; home carrier agent
  target-ship    ;; current attack target
]

;; Only internal state here - slider names must NOT be listed
globals [
  us-found?        ;; US has located Japan fleet
  japan-found?     ;; Japan has located US fleet
  message-queue    ;; List of pending detection messages
  japan-in-rearm?
  rearm-length
  first-hit-tick
  contacts
]

;;==========================================================
;; SETUP
;;==========================================================

to setup
  clear-all

  set us-found?       false
  set japan-found?    false
  set japan-in-rearm? false
  set rearm-length    8
  set first-hit-tick  -1
  set contacts        0
  set message-queue []
  set recon-max-detect recon-max-detect
  set comm-delay comm-delay

  ;; Large world so agents have room to maneuver
  resize-world -50 50 -50 50
  set-patch-size 5

  ;; Ocean
  ask patches [ set pcolor 96 ]
  ;; Midway Atoll
  ask patches with [ distancexy 0 0 < 2 ] [ set pcolor 66 ]

  make-carriers
  make-recon
  make-strikers
  reset-ticks
end 

to make-carriers
  ;; US Task Force - NE of Midway, historical ambush position
  let us-names (list "Enterprise" "Hornet"   "Yorktown")
  let us-ys    (list  5            0          10       )
  let i 0
  repeat 3 [
    create-carriers 1 [
      set fside      "US"
      set cname      item i us-names
      set hp         100
      set cstate     "active"
      set rearm-timer 0
      setxy 30 (item i us-ys)
      set shape "airplane"  set color blue  set size 4
      set label cname  set label-color white
    ]
    set i i + 1
  ]

  ;; Japan Kido Butai - NW of Midway
  let jp-names (list "Akagi" "Kaga"  "Soryu" "Hiryu")
  let jp-ys    (list  8       2      14      -4     )
  set i 0
  repeat 4 [
    create-carriers 1 [
      set fside      "JAPAN"
      set cname      item i jp-names
      set hp         100
      set cstate     "active"
      set rearm-timer 0
      setxy -30 (item i jp-ys)
      set shape "airplane"  set color red  set size 4
      set label cname  set label-color white
    ]
    set i i + 1
  ]
end 

to make-recon
  ;; US PBY Catalinas - based at Midway (0,0)
  ;; Intel advantage: sectors biased 170-310 deg (NW arc toward Japan)
  if num-us-recon > 0 [
    let arc-step 140.0 / num-us-recon
    create-recons num-us-recon [
      let slot (who mod num-us-recon)
      set fside    "US"
      set rstate   "out"
      set smax-fuel 35
      set rfuel     smax-fuel
      set route     170 + (slot * arc-step)
      set late-start 0
      set spotted?  false
      set base-x    0
      set base-y    0
      setxy 0 0
      set shape "airplane"  set color 107  set size 2
    ]
  ]

  ;; Japan E13A floatplanes - launched from carriers
  if num-japan-recon > 0 [
    let arc-step 360.0 / num-japan-recon
    let jp-positions []
    ask carriers with [ fside = "JAPAN" ] [
      set jp-positions lput (list xcor ycor) jp-positions
    ]
    create-recons num-japan-recon [
      let slot (who mod num-japan-recon)
      let pos  item (slot mod length jp-positions) jp-positions
      set fside    "JAPAN"
      set rstate   "out"
      set smax-fuel 28
      set rfuel     smax-fuel
      set route     (slot * arc-step)
      ;; Tone catapult failure: first 2 planes wait 4 ticks
      set late-start ifelse-value (slot < 2) [4] [0]
      set spotted?  false
      set base-x    item 0 pos
      set base-y    item 1 pos
      setxy base-x base-y
      set shape "airplane"  set color 25  set size 2
    ]
  ]
end 

to make-strikers
  ;; Collect carrier info at observer level (create is observer-only)
  let cdata []
  ask carriers [ set cdata lput (list fside xcor ycor self) cdata ]

  foreach cdata [ row ->
    let s  item 0 row
    let cx item 1 row
    let cy item 2 row
    let c  item 3 row
    ;; 6 strike planes per carrier
    create-strikers 6 [
      set fside      s
      set sstate     "deck"
      set smax-fuel  20
      set sfuel      smax-fuel
      set home-ship  c
      set target-ship nobody
      setxy cx cy
      set shape "airplane"
      set color ifelse-value (s = "US") [97] [135]
      set size 1.5
    ]
  ]
end 

to process-messages
  let new-queue []

  foreach message-queue [ msg ->
    let side item 0 msg
    let delay item 1 msg - 1

    if delay <= 0 [
      if side = "US" [
        set us-found? true
      ]
      if side = "JAPAN" and not japan-found? [
        set japan-found? true
        start-rearm
      ]
    ]
    if delay > 0 [
      set new-queue lput (list side delay) new-queue
    ]
  ]

  set message-queue new-queue
end 

;;==========================================================
;; GO
;;==========================================================

to go
  if not any? carriers with [ fside = "US"    and hp > 0 ] [ stop ]
  if not any? carriers with [ fside = "JAPAN" and hp > 0 ] [ stop ]

  process-messages
  tick-carriers
  tick-recon
  tick-strikers
  draw
  tick
end 

;;==========================================================
;; CARRIERS
;; Carriers drift very slowly. Their main job is to exist as
;; targets and launch strike planes. They do NOT chase each other.
;;==========================================================

to tick-carriers
  ask carriers with [ hp > 0 ] [

    ;; REARM countdown
    if cstate = "rearm" [
      set rearm-timer rearm-timer - 1
      if rearm-timer <= 0 [
        set cstate "active"
        set japan-in-rearm? any? carriers with [
          fside = "JAPAN" and cstate = "rearm"
        ]
        ;; Rearm done - launch all deck planes immediately
        launch-all-deck-planes self
      ]
      ;; Slow drift while rearming
      clamp-drift 0.1
      stop
    ]

    ;; ACTIVE: slow drift toward enemy zone, launch strikes when enemy known
    ;; US holds NE position until Japan detected; then holds to launch ops
    ;; Japan advances toward Midway; turns to face US when detected
    ifelse fside = "US" [
      ;; US: hold position with tiny drift (historical - held launch position)
      set heading (270 + random 20 - 10) mod 360
      clamp-drift 0.1
      if us-found? [ launch-all-deck-planes self ]
    ] [
      ;; Japan: advance SE toward Midway until US detected
      ifelse not japan-found? [
        set heading (120 + random 20 - 10) mod 360
        clamp-drift 0.2
      ] [
        ;; Japan detected US - turn toward US fleet
        let us-fleet carriers with [ fside = "US" and hp > 0 ]
        if any? us-fleet [
          face min-one-of us-fleet [ distance myself ]
          set heading (heading + random 16 - 8) mod 360
        ]
        clamp-drift 0.2
        if cstate = "active" [ launch-all-deck-planes self ]
      ]
    ]

    ;; Direct visual detection: spot enemy fleet within 15 patches
    let enemy-side ifelse-value (fside = "US") ["JAPAN"] ["US"]
    let visible carriers in-radius 15 with [ fside = enemy-side and hp > 0 ]
    if any? visible [
      if fside = "US" [ set us-found? true ]
      if fside = "JAPAN" and not japan-found? [
        set japan-found? true
        start-rearm
      ]
    ]
  ]
end 

;; Move forward by step but never leave world bounds

to clamp-drift [ step ]
  forward step
  if xcor > 48 [ set xcor 48 ]
  if xcor < -48 [ set xcor -48 ]
  if ycor > 48 [ set ycor 48 ]
  if ycor < -48 [ set ycor -48 ]
end 

to launch-all-deck-planes [ carr ]
  let enemy-side ifelse-value ([fside] of carr = "US") ["JAPAN"] ["US"]
  let targets carriers with [ fside = enemy-side and hp > 0 ]
  if not any? targets [ stop ]
  ask strikers with [ home-ship = carr and sstate = "deck" ] [
    set target-ship min-one-of targets [ distance myself ]
    set sstate "flying"
    set sfuel smax-fuel
  ]
end 

to start-rearm
  set japan-in-rearm? true
  ask carriers with [ fside = "JAPAN" and cstate != "sunk" ] [
    set cstate     "rearm"
    set rearm-timer rearm-length
  ]
end 

to do-sink
  set cstate "sunk"
  set hp 0
  set shape "x"
  set size 5
  set color gray
  set label (word cname " SUNK")
  set label-color red
  ask strikers with [ home-ship = myself ] [
    set sstate "dead"
    set color  gray
  ]
end 

;;==========================================================
;; RECON
;;==========================================================

to tick-recon
  ask recons with [ rstate != "dead" ] [

    ;; Refueling on ground
    if rstate = "refuel" [
      set rfuel rfuel + 5
      if rfuel >= smax-fuel [
        set rfuel smax-fuel
        set spotted? false
        set rstate  "out"
        set color ifelse-value (fside = "US") [107] [25]
      ]
      stop
    ]

    ;; Tone delay: Japan planes 0 and 1 sit on deck
    if late-start > 0 [
      set late-start late-start - 1
      stop
    ]

    set rfuel rfuel - 1
    if rfuel <= 0 [ set rstate "dead"  set color gray  stop ]
    let fuel-threshold smax-fuel * 0.35
    if rfuel < fuel-threshold and rstate = "out" [ set rstate "home" ]

    if rstate = "out"  [ recon-outbound ]
    if rstate = "home" [ recon-return   ]
  ]
end 

to recon-outbound
  set heading route
  ;; Simple wall bounce - only flip heading, small margin
  if xcor > 47 or xcor < -47 [
    set heading (360 - heading) mod 360
    set xcor clamp-coord xcor -47 47
  ]
  if ycor > 47 or ycor < -47 [
    set heading (180 - heading) mod 360
    set ycor clamp-coord ycor -47 47
  ]
  forward 2.0

  ;; Scan for enemy carriers within 12 patches
  if not spotted? [
    let opp ifelse-value (fside = "US") ["JAPAN"] ["US"]
    let found-carriers carriers in-radius 12 with [ fside = opp and hp > 0 ]
    if any? found-carriers [
      let tc one-of found-carriers
      ;; Detection probability: exponential decay with distance
      let d distance tc
      let p recon-max-detect * exp(-0.012 * d * 10)
      let delay comm-delay
      if random-float 1.0 < p [
        set spotted? true
        set color    green
        set rstate   "home"
        set contacts contacts + 1
        ;; Trigger detection for this faction
        set message-queue lput (list fside delay) message-queue
        ]
      ]
    ]
end 

to recon-return
  ;; Japan recon follows its carrier home
  if fside = "JAPAN" [
    let nearest-carrier min-one-of carriers with [
      fside = "JAPAN" and hp > 0
    ] [ distance myself ]
    if nearest-carrier != nobody [
      set base-x [xcor] of nearest-carrier
      set base-y [ycor] of nearest-carrier
    ]
  ]
  facexy base-x base-y
  forward 2.0
  if distancexy base-x base-y < 2 [
    set rstate "refuel"
    set color  gray
    setxy base-x base-y
  ]
end 

to-report clamp-coord [ val lo hi ]
  if val > hi [ report hi ]
  if val < lo [ report lo ]
  report val
end 

;;==========================================================
;; STRIKE PLANES
;; Simple three-state machine: deck -> flying -> returning
;; They fly DIRECTLY to target - no wall logic needed because
;; the target is always somewhere in the middle of the world.
;;==========================================================

to tick-strikers
  ask strikers with [ sstate != "dead" ] [

    ;; On deck: just sit on carrier
    if sstate = "deck" [
      if home-ship != nobody and [hp] of home-ship > 0 [
        setxy [xcor] of home-ship [ycor] of home-ship
      ]
      stop
    ]

    ;; Fuel burn while airborne
    set sfuel sfuel - 1
    let fuel-threshold smax-fuel * 0.35
    if sfuel <= 0 [ set sstate "dead" set color gray stop ]
    if sfuel < fuel-threshold and sstate = "flying" [ set sstate "returning" ]

    if sstate = "flying"    [ striker-fly    ]
    if sstate = "returning" [ striker-return ]
  ]
end 

to striker-fly
  ;; If target sank, find next nearest
  if target-ship = nobody or [hp] of target-ship <= 0 [
    let opp ifelse-value (fside = "US") ["JAPAN"] ["US"]
    let remaining carriers with [ fside = opp and hp > 0 ]
    ifelse any? remaining [
      set target-ship min-one-of remaining [ distance myself ]
    ] [
      set sstate "returning"
      stop
    ]
  ]

  ;; Close on target - resolve attack when within 3 patches
  let dist-to-target distance target-ship
  if dist-to-target < 3 [
    resolve-attack
    stop
  ]

  face target-ship
  forward 4.0

  ;; If we overshot (moved past target), resolve attack
  if distance target-ship < 3 [
    resolve-attack
  ]
end 

to resolve-attack
  if target-ship = nobody or [hp] of target-ship <= 0 [
    set sstate "returning"
    stop
  ]

  ;; AA fire: carrier defense may shoot down attacker
  let aa ifelse-value ([fside] of target-ship = "US") [aa-fire-us] [aa-fire-japan]
  if random-float 1.0 < aa [
    set sstate "dead"
    set color  gray
    stop
  ]

  ;; Hit roll
  let hit ifelse-value (fside = "US") [hit-us] [hit-japan]
  if random-float 1.0 < hit [
    let dmg ifelse-value (fside = "US") [25] [35]

    ;; REARM VULNERABILITY: 2x damage when Japan carrier is rearming
    ;; Models Akagi/Kaga/Soryu caught with armed planes and fuel
    ;; hoses on deck - destroyed in the "fatal five minutes" 1020-1025
    if fside = "US" and [cstate] of target-ship = "rearm" [
      set dmg dmg * 2
    ]

    ask target-ship [
      set hp hp - dmg
      if hp < 0 [ set hp 0 ]
      if hp <= 0 [ do-sink ]
    ]
    if first-hit-tick = -1 [ set first-hit-tick ticks ]
  ]

  set sstate "returning"
end 

to striker-return
  if home-ship = nobody or [hp] of home-ship <= 0 [
    ;; Home carrier sunk - ditch at sea
    set sstate "dead"
    set color  gray
    stop
  ]

  face home-ship
  forward 4.0

  if distance home-ship < 2 [
    ;; Back on deck - rearm and relaunch immediately if enemy still exists
    set sfuel smax-fuel
    set sstate "deck"
    set target-ship nobody
    setxy [xcor] of home-ship [ycor] of home-ship

    let opp ifelse-value (fside = "US") ["JAPAN"] ["US"]
    let can-launch false
    if fside = "US" [ set can-launch us-found? ]
    if fside = "JAPAN" [
      set can-launch (japan-found? and [cstate] of home-ship = "active")
    ]
    if can-launch [
      let targets carriers with [ fside = opp and hp > 0 ]
      if any? targets [
        set target-ship min-one-of targets [ distance myself ]
        set sstate "flying"
      ]
    ]
  ]
end 

;;==========================================================
;; DISPLAY
;;==========================================================

to draw
  ask patches [ set pcolor 96 ]
  ask patches with [ distancexy 0 0 < 2 ] [ set pcolor 66 ]

  ask carriers with [ hp > 0 ] [
    if fside = "US" [
      set color ifelse-value (hp > 50) [blue] [
                ifelse-value (hp > 25) [105] [15]]
    ]
    if fside = "JAPAN" [
      set color ifelse-value (cstate = "rearm") [yellow] [
                ifelse-value (hp > 50) [red] [
                ifelse-value (hp > 25) [25] [15]]]
    ]
    set label (word cname "  " hp "hp")
  ]

  ask strikers [
    if sstate = "flying" [
      set color ifelse-value (fside = "US") [white] [yellow]
      set size 2
    ]
    if sstate = "deck" [ set size 1.2 ]
  ]
end 

;;==========================================================
;; MONITORS
;;==========================================================

to-report us-carriers-alive
  report count carriers with [ fside = "US" and hp > 0 ]
end 

to-report japan-carriers-alive
  report count carriers with [ fside = "JAPAN" and hp > 0 ]
end 

to-report avg-us-health
  let a carriers with [ fside = "US" and hp > 0 ]
  if not any? a [ report 0 ]
  report precision mean [hp] of a 1
end 

to-report avg-japan-health
  let a carriers with [ fside = "JAPAN" and hp > 0 ]
  if not any? a [ report 0 ]
  report precision mean [hp] of a 1
end 

to-report rearm-ticker
  let r carriers with [ fside = "JAPAN" and cstate = "rearm" ]
  if not any? r [ report 0 ]
  report max [rearm-timer] of r
end 

There are 2 versions of this model.

Uploaded by When Description Download
Vineet Sood 14 days ago Battle of Midway VS Edits Download this version
Vineet Sood 15 days ago Initial upload Download this version

Attached files

File Type Description Last updated
Battle of Midway VS Edits.png preview Preview for 'Battle of Midway VS Edits' 15 days ago, by Vineet Sood Download

This model does not have any ancestors.

This model does not have any descendants.