Bladder Patrol

Bladder Patrol preview image

1 collaborator

Breadcrab2 Jason Bertsche (Author)

Tags

coyote 

"This model has coyotes with lasers"

Tagged by Jason Bertsche over 10 years ago

game 

"Simulation game, but not interactive"

Tagged by Jason Bertsche over 10 years ago

hell 

"You must see it to believe it"

Tagged by Jason Bertsche over 10 years ago

reality tv 

"It's like what you would see on TV"

Tagged by Jason Bertsche over 10 years ago

survival 

"It's hard to survive in this model"

Tagged by Jason Bertsche over 10 years ago

urine 

"We all have it"

Tagged by Jason Bertsche over 10 years ago

Model group Really Super Awesome Jasons | Visible to everyone | Changeable by everyone
Model was written in NetLogo 5.0.5 • Viewed 570 times • Downloaded 40 times • Run 0 times
Download the 'Bladder Patrol' 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

How do you do it? (Question)

impressed.

Posted over 10 years ago

Re: How do you do it?

This is a skill that can no more be taught than "having three arms" can be taught.

Posted over 10 years ago

Click to Run Model

breed [pretzels pretzel]
pretzels-own [
  owner-id
]

breed [water-stands water-stand]
water-stands-own [
  id
  thirsties-on-tap
]

breed [toilets toilet]
toilets-own [
  id
  is-occupied?
]

breed [puddles puddle]
breed [corpses corpse]
corpses-own [
  is-dead?
]

breed [people person]
people-own [
  id
  pretzel-count
  thirsties
  hungries
  tinkles
  money
  ticks-hungry
  ticks-thirsty
  ticks-wanting-bathroom
  occupied-toilet-id
  bex-count
  did-buy-pretzel-this-tick?
  is-drinking?
  is-dead?
  specialty-type
]

breed [lasers laser]
lasers-own [
  target-hunted
]

breed [coyotes coyote]
coyotes-own [
  target-id
  exit-dir
]

breed [pick-up-anims pick-up-anim]
pick-up-anims-own [
  ticks-alive
  j-dist
]

breed [from-bag-anims from-bag-anim]
from-bag-anims-own [
  ticks-alive
  j-dist
]

breed [drink-anims drink-anim]
drink-anims-own [
  ticks-alive
  j-dist
]

breed [eat-anims eat-anim]
eat-anims-own [
  ticks-alive
  j-dist
]

breed [money-plus-anims money-plus-anim]
money-plus-anims-own [
  ticks-alive
  j-dist
]

breed [money-minus-anims money-minus-anim]
money-minus-anims-own [
  ticks-alive
  j-dist
]

breed [bex-anims bex-anim]
bex-anims-own [
  ticks-alive
  j-dist
]

breed [tinkle-anims tinkle-anim]
tinkle-anims-own [
  ticks-alive
  j-dist
]

breed [death-anims death-anim]
death-anims-own [
  ticks-alive
  j-dist
]

globals [
    
    is-won?
    
    color-list
    player-count
    specialty-types
    toilet-troll-str
    pretzel-prot-str
    water-waster-str
    coyote-jump-dist
    coyote-laser-range
    laser-velocity
    
    anim-lifespan
    anims-list
    anim-float-rate
    ghost-float-rate
    rocket-float-rate
    anim-placement-above
    dollar-size
    default-anim-size

]

to setup
  clear-all
  initialize
  make-turtles
  reset-ticks
end 

to initialize
  
  set is-won? false
  
  set color-list [violet green red orange pink gray blue yellow brown white]
  set player-count 5
  set toilet-troll-str "toilet-troll"
  set pretzel-prot-str "pretzel-protector"
  set water-waster-str "water-waster"
  set specialty-types (list toilet-troll-str pretzel-prot-str water-waster-str)
  set coyote-jump-dist 3
  set coyote-laser-range 12
  set laser-velocity 7
  
  set anim-lifespan 5
  set anims-list (list eat-anims money-plus-anims money-minus-anims drink-anims from-bag-anims pick-up-anims bex-anims tinkle-anims death-anims)
  set anim-float-rate .5
  set ghost-float-rate 1
  set rocket-float-rate 2
  set anim-placement-above 2
  set default-anim-size 2
end 

to go
  
  handle-anims
  handle-spoilers
  handle-water-level
  
  if ((count people = 1) and not is-won?) [
    print (word (id-to-color-name ([id] of (one-of people))) " has won!")
    set is-won? true
    stop
  ]
  
  amplify-desires
  assess-desires
  
  spawn-new-pretzels
  spawn-new-coyotes
  direct-coyotes
  direct-lasers
  
  act-on-desires
  
  tick
end 

to handle-anims
  foreach anims-list [
    ask ? [
      set ticks-alive (ticks-alive + 1)
      ifelse ((ticks-alive >= anim-lifespan) or ((max-pycor - ycor) <= j-dist)) [die] [jump j-dist]
    ]
  ]
end 

to handle-spoilers
  
  ifelse (spoilers) [
    ask people with [ specialty-type = water-waster-str ] [ ifelse (water-waster) [ set shape "water-waster" ] [ set shape "person" ] ]
    ask people with [ specialty-type = toilet-troll-str ] [ ifelse (toilet-troll) [ set shape "toilet-troll" ] [ set shape "person" ] ]
    ask people with [ specialty-type = pretzel-prot-str ] [ ifelse (pretzel-protector) [ set shape "pretzel-protector" ] [ set shape "person" ] ]
  ]
  [ ask people with [ specialty-type != -1 ] [ set shape "person" ] ]
end 

to handle-water-level
  ask water-stands [
    replenish-water    
    determine-water-stand-shape
  ]
end 

to replenish-water
  let inc water-replenishment-rate
  let thirsties-until-full (water-level-max - thirsties-on-tap)
  if (water-replenishment-rate > thirsties-until-full) [ set inc thirsties-until-full ]
  set thirsties-on-tap (thirsties-on-tap + inc)
end 

; For use by water-stands only

to determine-water-stand-shape
  let percentage ((thirsties-on-tap / water-level-max) * 100)
  ifelse (percentage < 25) [ set shape "water0" ] [
    ifelse (percentage < 50) [ set shape "water25" ] [
      ifelse (percentage < 75) [ set shape "water50" ] [
        ifelse (percentage < 100) [ set shape "water75" ] [ set shape "water100" ]
      ]
    ] 
  ]
end 

to spawn-new-pretzels
  let x (random (max-new-pretzels-per-tick - min-new-pretzels-per-tick))
  let new-pretzel-count (x + min-new-pretzels-per-tick)
  create-pretzels new-pretzel-count [initialize-pretzel]
end 

to spawn-new-coyotes
  
  if (bladder-explosion-threshold > 0) [
    ask people with [ (bex-count >= bladder-explosion-threshold) and (not any? coyotes with [[id] of myself = target-id]) ] [
      
      hatch-coyotes 1 [
        
        let x -1
        let y -1
        let exit-on "null"
        let vertical (random 3)
        
        ifelse (vertical = 0) [ ; Baseline
          set x ((random (max-pxcor + (abs min-pxcor))) - (abs min-pxcor))
          set y min-pycor
          set exit-on "top"
        ]
        [
          ifelse (vertical = 1) [ ; Topline
            set x ((random (max-pxcor + (abs min-pxcor))) - (abs min-pxcor))
            set y max-pycor
            set exit-on "bottom"
          ]
          [
            let horizon (random 2)
            ifelse (horizon = 1) [
              set x max-pycor
              set y ((random (max-pycor + (abs min-pycor))) - (abs min-pycor))
              set exit-on "left"
            ]
            [
              set x min-pycor
              set y ((random (max-pycor + (abs min-pycor))) - (abs min-pycor))
              set exit-on "right"
            ]
          ]
        ]

        set target-id ([id] of myself)
        set exit-dir exit-on
        set size 4
        setxy x y
        face myself
        
      ]
        
    ]
  ]
end 

to direct-coyotes
  ask coyotes [
    let hunteds (people with [id = [target-id] of myself])
    ifelse (any? hunteds) [
      let hunted (one-of hunteds)
      move-towards hunted
      if ((distance hunted) <= coyote-laser-range) [
        hatch-lasers 1 [
          face hunted
          set size 2.5
          set target-hunted hunted
        ]
      ]
    ]
    [
      let should-die false
      ifelse (exit-dir = "right") [
        set heading 90
        set should-die (coyote-jump-dist >= (max-pxcor - xcor))
      ]
      [
        ifelse (exit-dir = "left") [
          set heading 270
          set should-die (coyote-jump-dist >= (abs (xcor - min-pxcor)))
        ]
        [
          ifelse (exit-dir = "top") [
            set heading 0
            set should-die (coyote-jump-dist >= (max-pycor - ycor))
          ]
          [
            if (exit-dir = "bottom") [
              set heading 180
              set should-die (coyote-jump-dist >= (abs (ycor - min-pycor)))
            ]
          ]
        ]
      ]
      if (should-die) [die]
      jump coyote-jump-dist
    ]
  ]
end 

to direct-lasers
  
  ask lasers [
    
    if ([is-dead?] of target-hunted) [die]
    
    let base-looks 3
    let looks base-looks
    
    while [(looks > 0) and (target-hunted != nobody)] [
      jump (laser-velocity / base-looks)
      if ((distance target-hunted) < 2) [
        ask target-hunted [
          print (word (id-to-color-name id) " died of LASERED!")
          hatch-death-anims 1 [ initialize-ghost myself ]
          set breed corpses
          set is-dead? true
        ]
        die
      ]
      set looks (looks - 1)
    ]    
  ]
end 

to place-bladder-explosion
  hatch-puddles 1 [
    set color yellow
    set ycor (ycor - 1.5)
  ]
end 

to-report id-to-color-name [thing-id]
  let color-num (item (thing-id - 1) color-list)
  if color-num = 9.9 [ report "white" ]
  report item (color-num mod 10) base-colors
end 

to amplify-desires
  ask people [
    set thirsties (thirsties + thirst-rate)
    set hungries (hungries + hunger-rate)
  ]
end 

to assess-desires
  ask people [
    
    if (hungries >= hunger-activation-threshold) [ set ticks-hungry (ticks-hungry + 1) ]
    if (thirsties >= thirst-activation-threshold) [ set ticks-thirsty (ticks-thirsty + 1) ]
    if (tinkles >= tinkle-activation-threshold) [ set ticks-wanting-bathroom (ticks-wanting-bathroom + 1) ]
    
    if (ticks-hungry >= ticks-hungry-before-death) [
      print (word (id-to-color-name id) " died of hunger")
      hatch-death-anims 1 [ initialize-ghost myself ]
      set breed corpses
      set is-dead? true
      stop
    ]
    
    if (ticks-thirsty >= ticks-thirsty-before-death) [
      print (word (id-to-color-name id) " died of thirst")
      hatch-death-anims 1 [ initialize-ghost myself ]
      set breed corpses
      set is-dead? true
      stop
    ]
    
    if (ticks-wanting-bathroom >= ticks-before-bladder-explosion) [
      place-bladder-explosion
      set bex-count (bex-count + 1)
      hatch-bex-anims 1 [ initialize-anim myself ]
      set money (money - fine-for-bladder-explosion)
      set ticks-wanting-bathroom 0
      set tinkles 0
    ]
    
  ]
end 

to act-on-desires
  ask people [
    ifelse (is-drinking?) [ do-thirst ]
    [
      ifelse (did-buy-pretzel-this-tick?) [ set did-buy-pretzel-this-tick? false ]
      [
        ifelse (occupied-toilet-id != -1) [do-use-toilet]
        [
          ifelse (hungries >= hunger-activation-threshold) [
            ifelse (thirsties >= thirst-activation-threshold) [
              ; If closer to dying of hunger than of thirst
              ifelse ((ticks-hungry-before-death - ticks-hungry) < (ticks-thirsty-before-death - ticks-thirsty)) [do-hunger] [do-thirst]
            ]
            [do-hunger]
          ]
          [
            ifelse (thirsties >= thirst-activation-threshold) [do-thirst]
            [
              ifelse ((tinkles >= tinkle-activation-threshold) and not is-water-wasting?) [do-find-toilet]
              [
                ifelse (is-toilet-trolling?) [do-find-toilet]
                [
                  ifelse (is-water-wasting?) [do-thirst]
                  [
                    ifelse (is-pretzel-protecting?) [do-scavenge-pretzels]
                    [
                      let pretzel-needer (find-nearest-pretzel-needer-with-money pretzel-selling-price)
                      ifelse ((pretzel-count > 0) and (pretzel-needer != nobody) and (is-reachable? pretzel-needer)) [ do-sell-pretzel pretzel-needer ] [do-scavenge-pretzels]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
end 

; For use by people only

to-report find-nearest [targets]
  report min-one-of targets [distance myself]
end 

to-report find-nearest-pretzel-needer-with-money [price]
  let needers (people with [(pretzel-count < 1) and (money >= price) and (myself != self)])
  ifelse (any? needers) [ report find-nearest needers ] [ report nobody ]
end 

; For use by people only

to-report is-reachable? [target]
  let dist ([distance target] of self)
  report (dist <= distance-travelable-per-tick)
end 

; For use by people only

to move-towards [target]
  move-towards-dist target distance-travelable-per-tick
end 

; For use by people only

to move-towards-dist [target dist]
  face target
  jump dist
end 

; For use by people only

to move-randomly
  set heading (random 360)
  jump distance-travelable-per-tick
end 

; For use by people only

to move-next-to [target]
  let dist-minus 2
  let dist-to-target distance target
  let moving-dist (dist-to-target - dist-minus)
  if (0 > moving-dist) [move-towards-dist target moving-dist]
end 

; For use by people only

to-report already-next-to? [target]
  report distance target <= 2
end 

; For use by people only

to consume-pretzel
  
  let bottomed-hungries 0
  let unbottomed-hungries (hungries - pretzel-hunger-reduction)
  if (unbottomed-hungries > 0) [ set bottomed-hungries unbottomed-hungries ]
  
  set pretzel-count (pretzel-count - 1)
  set hungries bottomed-hungries
  set thirsties (thirsties + thirst-incurred-by-pretzels)
  if (hungries < hunger-activation-threshold) [ set ticks-hungry 0 ]
end 

; For use by people only

to consume-water [nearest-water]
  
  let topped-on-tap water-thirst-reduction
  if (([thirsties-on-tap] of nearest-water) < water-thirst-reduction) [ set topped-on-tap ([thirsties-on-tap] of nearest-water)]
  show [thirsties-on-tap] of nearest-water
  
  let bottomed-thirsties 0
  let unbottomed-thirsties (thirsties - topped-on-tap)
  if (unbottomed-thirsties > 0) [ set bottomed-thirsties unbottomed-thirsties ]
  let water-taken (topped-on-tap - bottomed-thirsties)
  if (water-taken < 0) [ set water-taken 0 ]
  
  ask nearest-water [ set thirsties-on-tap (thirsties-on-tap - water-taken) ]
  set thirsties bottomed-thirsties
  set tinkles (tinkles + tinkles-incurred-by-water)
  
  hatch-drink-anims 1 [ initialize-anim myself ]
  
  if (thirsties < thirst-activation-threshold) [ set ticks-thirsty 0 ]
end 

; For use by people only

to do-use-toilet
  
  set tinkles (tinkles - tinkles-lost-per-tick-in-bathroom)
  hatch-tinkle-anims 1 [ initialize-rocket myself ]
  
  if (tinkles <= 0) [
    set tinkles 0
    ask toilets with [ id = [occupied-toilet-id] of myself ] [ set is-occupied? false ]
    set occupied-toilet-id -1
  ]
end 

; For use by people only

to do-hunger
  ifelse (pretzel-count > 0) [
    consume-pretzel
    hatch-from-bag-anims 1 [ initialize-anim myself ]
  ]
  [
    let nearest-pretzel (find-nearest pretzels)
    ifelse (nearest-pretzel != nobody) [
      ifelse (is-reachable? nearest-pretzel) [
        move-to nearest-pretzel
        ask nearest-pretzel [die]
        set pretzel-count (pretzel-count + 1)
        consume-pretzel
        hatch-eat-anims 1 [ initialize-anim myself ]
      ]
      [move-towards nearest-pretzel]
    ]
    [do-find-pretzel-seller]
  ]
end 

; For use by people only
; Does not accomodate for setups without water

to do-thirst
  let nearest-water (find-nearest water-stands)
  ifelse (is-reachable? nearest-water) [
    if (not already-next-to? nearest-water) [ move-next-to nearest-water ]
    consume-water nearest-water
    if (thirsties = 0) [ set is-drinking? false ]
  ]
  [ move-towards nearest-water ]
end 

; For use by people only

to do-find-toilet
  let nearest-toilet (find-nearest toilets)
  ifelse (is-reachable? nearest-toilet) [
    ifelse (not ([is-occupied?] of nearest-toilet)) [ do-occupy-toilet nearest-toilet ] [ move-next-to nearest-toilet ]
  ]
  [ move-towards nearest-toilet ]
end 

; For use by people only

to do-sell-pretzel [buyer]
  
  print (word (id-to-color-name id) " sold a pretzel to " (id-to-color-name ([id] of buyer)))
  move-next-to buyer
  set pretzel-count (pretzel-count - 1)
  set money (money + pretzel-selling-price)
  hatch-money-plus-anims 1 [ initialize-anim myself ]
  
  ask buyer [
    set pretzel-count (pretzel-count + 1)
    consume-pretzel
    hatch-money-minus-anims 1 [ initialize-anim myself ]
    set money (money - pretzel-selling-price)
  ]
end 

; For use by people only

to do-scavenge-pretzels
  let nearest-pretzel (find-nearest pretzels)
  ifelse (nearest-pretzel != nobody) [
    ifelse (is-reachable? nearest-pretzel) [
      move-to nearest-pretzel
      set pretzel-count (pretzel-count + 1)
      ask nearest-pretzel [die]
      hatch-pick-up-anims 1 [ initialize-anim myself ]
    ]
    [ move-towards nearest-pretzel ]
  ]
  [move-randomly]
end 

; For use by people only

to do-occupy-toilet [toilet]
  move-to toilet
  setxy (xcor - 0.4) (ycor + 0.6)
  set occupied-toilet-id ([id] of toilet)

  ask toilet [ set is-occupied? true ]
  do-use-toilet
end 

; For use by people only

to do-find-pretzel-seller
  let nearest-seller (min-one-of people with [pretzel-count > 0] [distance self])
  ifelse (nearest-seller != nobody) [
    ifelse (is-reachable? nearest-seller) [ move-next-to nearest-seller ] [ move-towards nearest-seller ]
  ]
  [ move-randomly ]
end 
  
; For use by people only

to-report is-toilet-trolling?
  report ((specialty-type = toilet-troll-str) and toilet-troll)
end 

; For use by people only

to-report is-pretzel-protecting?
  report ((specialty-type = pretzel-prot-str) and pretzel-protector)
end 

; For use by people only

to-report is-water-wasting?
  report ((specialty-type = water-waster-str) and water-waster)
end 
  
; Setup stuff

to make-turtles

  let color-tuple-list (zip-with-index (take color-list player-count))
  let toilet-count 1
  let water-stand-count 1
  let invalid-id -1
  
  set-default-shape people "person"
  set-default-shape pretzels "pretzel"
  set-default-shape toilets "toilet"
  set-default-shape water-stands "drop"
  set-default-shape puddles "drop"
  set-default-shape corpses "flower"
  set-default-shape coyotes "coyote"
  set-default-shape lasers "lazor"
  
  set-default-shape eat-anims "pacman"
  set-default-shape money-plus-anims "green-dollar"
  set-default-shape money-minus-anims "red-dollar"
  set-default-shape drink-anims "bottle"
  set-default-shape from-bag-anims "opened-gift"
  set-default-shape pick-up-anims "gift"
  set-default-shape bex-anims "red-dollar"
  set-default-shape tinkle-anims "red-rocket"
  set-default-shape death-anims "ghost"

  create-pretzels (3 * player-count) [
    initialize-pretzel
  ]
  
  create-toilets 1 [
    set size 5
    set heading 90
    set id -1
    set is-occupied? false
    jump 14
  ]
  
  while [toilet-count > 0] [
    ask one-of toilets with [ id = -1 ] [ set id toilet-count ]
    set toilet-count (toilet-count - 1)
  ]
  
  create-water-stands 1 [
    set color blue
    set size 4
    set heading 270
    set thirsties-on-tap starting-water-level
    set id -1
    jump 14
    determine-water-stand-shape
  ]
  
  while [water-stand-count > 0] [
    ask one-of water-stands with [ id = -1 ] [ set id water-stand-count ]
    set water-stand-count (water-stand-count - 1)
  ]
  
  create-ordered-people player-count [
    jump 1.75
    set size 2.5
    set id invalid-id
    set pretzel-count starting-pretzels
    set thirsties ((random thirst-activation-threshold) + base-thirst)
    set hungries ((random hunger-activation-threshold) + base-hunger)
    set tinkles 0
    set money starting-money
    set ticks-hungry 0
    set ticks-thirsty 0
    set ticks-wanting-bathroom 0
    set occupied-toilet-id -1
    set bex-count 0
    set did-buy-pretzel-this-tick? false
    set is-drinking? false
    set is-dead? false
    set specialty-type -1
  ]
  
  handle-specialty-types
  
  while [not (empty? color-tuple-list)] [
    let head (first color-tuple-list)
    let tail (but-first color-tuple-list)
    ask one-of people with [ id = invalid-id ] [
      set id ((first head) + 1)
      set color (first (but-first head))
    ]
    set color-tuple-list tail
  ]
end 

; For use by pretzels only

to initialize-pretzel
  set size 1.5
  let angle (random 360)
  let dist (((random 1100) / 100) + 6)
  set heading angle
  set owner-id -1
  jump dist
end 

to handle-specialty-types
  
  let max-iters (length specialty-types)
  if (player-count < max-iters) [ set max-iters player-count ]
  
  let types (shuffle specialty-types)
  handle-specialty-types-helper types 0 max-iters
end 

to handle-specialty-types-helper [types iters max-iters]
  if (iters < max-iters) [
    ask one-of people with [specialty-type = -1] [ set specialty-type (first types)]
    handle-specialty-types-helper (but-first types) (iters + 1) max-iters
  ]
end 

; For use by anims only

to initialize-anim [creator]
  initialize-anim-base creator anim-float-rate
end 

to initialize-rocket [creator]
  initialize-anim-base creator rocket-float-rate
end 

to initialize-ghost [creator]
  initialize-anim-base creator ghost-float-rate
end 

to initialize-anim-base [creator jump-dist]
  set j-dist jump-dist
  set ticks-alive 0
  set heading 0
  set size default-anim-size
  move-to creator
  let new-ycor (ycor + anim-placement-above)
  if (new-ycor < max-pycor) [ set ycor new-ycor ] 
end 

to-report zip-with-index [xs]
  let indexes (n-values (length xs) [?])
  report zip indexes xs
end 

to-report zip [xs ys]
  report (map [list ?1 ?2] xs ys)
end 

to-report take [xs num]
  report take-helper xs num []
end 

to-report take-helper [xs num acc]
  if-else num <= 0 or (empty? xs) [
    report reverse acc
  ] [
    report take-helper (but-first xs) (num - 1) (fput (first xs) acc)
  ]
end 

; +-------------------------+
; |      Plotting code      |
; +-------------------------+

to plot-people-base [x plot-type is-border?]
  
  let my-turtle (one-of people with [id = (x + 1)])
  let tx (get-true-x x)
  
  ifelse (my-turtle = nobody) [ plotxy tx 0 ] [
    ifelse (is-border?) [ plot-switchboard tx plot-type my-turtle ] [
      let i tx
      repeat (get-true-repeats x) [
        plot-switchboard i plot-type my-turtle
        set i (i + .01)
      ]
    ]
  ]
end 

to plot-switchboard [x plot-type my-turtle]
  let y (run-switchboard plot-type my-turtle)
  plotxy x y
end 

to-report run-switchboard [plot-type my-turtle]
  report [runresult plot-type] of my-turtle
end 

to plot-threshold [threshold]
  plotxy 0 threshold
end 

to-report get-true-x [x]
  ifelse (x = 0) [report 0.02] [report x]
end 

to-report get-true-repeats [x]
  ifelse x = 0 or x = player-count - 1 [report 97] [report 99]
end 

There is only one version of this model, created over 10 years ago by Jason Bertsche.

Attached files

File Type Description Last updated
Bladder Patrol.png preview Preview for 'Bladder Patrol' over 10 years ago, by Jason Bertsche Download

This model does not have any ancestors.

This model does not have any descendants.