Rhino Poaching

Rhino Poaching preview image

2 collaborators

Jacob van der Ploeg (Team member)

Tags

animal behavior 

Tagged by Nick van Doormaal about 7 years ago

conservation 

Tagged by Nick van Doormaal about 7 years ago

criminology 

Tagged by Nick van Doormaal about 7 years ago

law enforcement 

Tagged by Nick van Doormaal about 7 years ago

poaching 

Tagged by Nick van Doormaal about 7 years ago

wildlife crime 

Tagged by Nick van Doormaal about 7 years ago

Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.0 • Viewed 571 times • Downloaded 40 times • Run 0 times
Download the 'Rhino Poaching' modelDownload this modelEmbed this model

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


Info tab cannot be displayed because of an encoding error

Comments and Questions

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

Click to Run Model

; ctrl f: JJJJ & ????

extensions [rnd]

globals [
  max-roughness         ; highest rough terrain value
  sprout-delay-time     ; number of ticks until resources wil grow back
  rhino-activity-decay  ; how fast will signs of rhino activity disappear?
  human-signs-decay     ; how fast will signs of poachers disappear?
  carcass-decay         ; how long it takes for a carcass to dissappear
  rhino-weight          ; sum of weights for the rhino-decision
  poacher-weight        ; sum of weight for the poacher-decision
  ranger-weight         ; sum of weight for the ranger-decision
  ;population-size      ; sum of herd-size of all rhinos (i.e. rhinos * herd-size, which starts at 70 w/ herds off and 350 w/ herds on) JJJJ [OFF, see report]
]

breed [ camps camp]         ; create breed of camps
breed [ poachers poacher ]  ; create breed of poachers
breed [ rhinos rhino]       ; create breed of rhinos
breed [ rangers ranger]     ; create breed of rangers

rangers-own [
  patrol-memory     ; remember previous visited patches
  patrol-time       ; how long has the ranger been on patrol
  risky-areas       ; remember areas where the ranger found signs of poaching activity
  safe-areas        ; remember areas with no poaching activity
  off-duty-time     ; how long to wait in between patrols
  rhino-sightings   ; remember where rangers saw a rhino
  ranger-goal       ; everyone needs a goal in life
  state             ; describes if the ranger is patrolling, or heading back to camp and preparing for next patrol
  direction         ; describes the direction of ranger during fence patrol
  ticks-wait
]

poachers-own [
  time              ; How much time has the poacher spent inside the reserve?
  laylow            ; How long to wait between hunts?
  success-sites     ; remember all patches where the poacher killed a rhino
  good-sites        ; remember all patches with rhino signs and no rangers
  failure-sites     ; remember all patches where the poacher did not find anything or too many rangers
  rhinos-killed     ; total number of rhinos killed
  poacher-memory    ; remember previous visited patches
  poacher-goal      ; everyone needs a goal in life
  state             ; describes if the poacher is on the journey to, from crime or waiting and planning new trip
  ticks-wait
]

rhinos-own [
   rhino-memory     ; remember previous visited patches
   rhino-goal       ; even rhinos have a goal in life
   ticks-wait
   herd-size        ; counter for group size JJJJ
]

patches-own [
  inside?               ; represents inside / outside reserve
  resources             ; how many resources in the patch?
  roughness             ; high roughness takes more time to move through
  countdown             ; number of ticks until resources wil grow back
  recent-rhino-activity ; was there any rhino here recently?
  rhino-territory       ; to which rhino does this patch belong to?
  poacher-signs         ; signs of poaching
  patch-attractiveness  ; which patch is the most sexy?
  ranger-signs          ; signs of ranger patrols
]


;to test
;  ask ranger (1 + num-rhinos) [set color yellow set size 20]
;end

to setup-park
  clear-all
  set sprout-delay-time 100   ; resources will increase after a certain time
  set max-roughness 5                      ; highest rough terrain value
  set rhino-activity-decay 500 ;
  set rhino-weight (rhino-avoid-weight + roughness-weight + resources-weight)
  ;set population-size (sum [herd-size] of rhinos * count rhinos) ; JJJJ
  create-park
  create-rough-areas
  release-rhinos
  setup-home-range
  reset-ticks
end 

to-report population-size ; JJJJ
  report sum [herd-size] of rhinos
end 

to setup-humans
 set carcass-decay 10000                   ; carcass signs will always be visible throughout the simulation
 set human-signs-decay 200
 set poacher-weight (ranger-avoid-weight * 2) + hunt-rhino-weight + roughness-weight + resources-weight
 set ranger-weight 1 + search-rhino-weight + roughness-weight + catch-poacher-weight ; the '+1' represents avoidance of other patrols
 build-camps
 distribute-camps
 release-rangers
 release-poachers
 reset-ticks
end 

to create-park
; next create resources patches inside the reserve
  ask patches with [count neighbors = 8][    ; inside the reserve
      set rhino-territory nobody             ; no patches have been taking by rhinos yet
      set roughness 1                        ; all patches are easy to move through
      set inside? TRUE                       ; resources can increase only inside the reserve
      set resources random-float 1.1         ; amount of resources is a random number between 0 to 1
      set countdown random (sprout-delay-time + random 100) ; generate a random countdown for each patch
]
diffuse resources 0.4
; first create the reserve's border
  ask patches with [count neighbors < 8][   ; select world's border
    set roughness 1                         ; easy to move through
    set resources 0                         ; no resources means unattractive for rhinos
    set inside? FALSE                       ; no resources can grow here
    set countdown 0                         ; no resources can grow back
    set pcolor black                        ; colour the border black
]
; some patches will be sand/dirt areas. No resources is growing on these patches
let percentage-sand ((count patches with [inside? = TRUE]) / 100 ) * sandy-areas
ask n-of percentage-sand patches with [inside? = TRUE] [
  set resources 0
]
; colour the world
ask patches [color-resources]
end 

to setup-rhino
  if ticks = 1000 [ stop ]
   ask rhinos [
     rhino-goal-check                ; check for their rhino movement goal
     update-rhino-memory             ; short-term memory of rhino
     rhino-foraging-and-home-range   ; rhinos are territorial and search for food
    ]
   ask patches [
      update-resources
      update-home-range
      update-visualization
      update-activity-signs
    ]
    tick
end 

to go
; when all rhinos die and last poacher escaped the reserve, it's game over.
if (not any? rhinos) [ stop ]
; when all poachers are caught, the rhinos live happily ever after
if (not any? poachers) [ stop ]
; when "a year" has passed, stop the simulation
if ticks = 10000 [ stop ]

ask rhinos [
      rhino-goal-check                ; check for their rhino movement goal
      update-rhino-memory             ; short-term memory of rhino
      rhino-foraging-and-home-range   ; rhinos are territorial and search for food
    ]

ask poachers [
      poacher-laylow        ; if outside reserve, poacher will will prepare for their next hunt
      poacher-goal-check    ; poachers avoid rangers and search for rhinos
      ]

ask rangers [
      ranger-end-patrol         ; check if rangers have still time to patrol more.
      ranger-goal-check     ; rangers search for poachers
    ]

ask patches [
      update-resources
      update-home-range
      update-visualization
      update-activity-signs
    ]
    tick
end 

to update-visualization
  if visualization = "resources_colors" [
    color-resources
  ]
  if visualization = "rhino_home-ranges" [
    color-home-range
  ]
  if (visualization = "rough_areas") [
    color-rough-areas
  ]
end 

to color-home-range
; the colour of the patch corresponds to the same colour as the rhino it belongs to.
; when the patch belongs to nobody, it corresponds to the number of resources.
; IF - patches are inside
 ifelse inside? [
   if rhino-territory != nobody [
     set pcolor [color] of rhino-territory + 2]
   if rhino-territory = nobody and resources > 0 [
     set pcolor (scale-color green resources 1.5  0)]
   if rhino-territory = nobody and resources = 0 [
     set pcolor brown * 1.02 ]
 ]
; ELSE - patches outside the reserve
 [set pcolor black]
end 

to update-resources
set countdown (countdown - 1)        ; reduces the countdown by 1
if inside? and countdown = 0 [       ; for every fertile patch that reached 0..
  set resources (resources * 1.01)  ; ...increase resources with 1%
  set countdown sprout-delay-time + random 100    ; resources won't increase again until sprout-delay-time has passed
  if resources > 1 [set resources 1] ; 1 indicates maximum value, this cannot be exceeded
]
if not inside? [                     ; select the patches outside the reserve...
  set resources 0]                   ; ... and keep them unattractive for rhinos
if resources < 0 [
  set resources 0                    ; resources cannot have negative values
]

if (visualization = "resources_colours") [
  color-resources]                       ; colour patches based on amount of resources available
end 

to color-resources
; scale color of patch from whitish green (for low resources) to green (for high resources)
; IF - patches are inside the reserve
 ifelse inside? [
; IF - and have some resources
   ifelse resources > 0 [
     set pcolor (scale-color green resources 1.5  0)]

; ELSE - fertile but no resources
   [set pcolor brown * 1.02]]  ; colour for patches inside the reserve but with no resources
; ELSE - not fertile
 [set pcolor black]            ; colour for outside the reserve
end 

to create-rough-areas
  ask n-of rough-areas patches with [inside? = TRUE] [          ; select an x number of patches inside the reserve...
    set roughness max-roughness                                 ; and assign the maximum value of roughness to it (the peak if you like).
  ask patches in-radius ( max-roughness - 1 ) [                 ; select the patches surrounding it...
    set roughness round (max-roughness - distance myself + roughness) ; ...and increase their roughness based on how close the patch is to the "peak".
  if roughness < 1 [                                            ; minimum roughness = 1
    set roughness 1]
  if roughness > max-roughness [
    set roughness max-roughness]]                               ; maximum roughness
  ]
  if visualization = "rough_areas" [
    ask patches [
      color-rough-areas ]
  ]
end 

to color-rough-areas
; colour the patches based on their roughness. The non-rough patches will be coloured based on their resources-values.
; IF - patches are fertile
 if roughness > 1 [
   set pcolor (scale-color red roughness 1  10)
   ]
 if roughness = 1 and resources > 0 [
   set pcolor (scale-color green resources 1.5 0)
 ]
 if roughness = 1 and resources = 0 and inside? = TRUE [
   set pcolor brown * 1.02
 ]
 if roughness = 1 and resources = 0 and inside? = FALSE [
   set pcolor black
 ]
end 

to release-rhinos
  set-default-shape rhinos "mammoth"                   ; slightly modified mammoth symbol represents rhinos
  ask n-of num-rhinos patches with [inside? = TRUE and
  not any? turtles in-radius 5 ] [                     ; sprout rhinos only inside the reserve
    sprout-rhinos 1 [                                  ; create the rhinos, then initialize their variables
      set size 2] ]
  spread-rhinos                                        ; make sure rhinos won't be too close to each other
  ask rhinos [
    set rhino-memory (list patch-here)                 ; At the start, rhinos only remember their current location
    set rhino-goal patch-here                          ; Rhinos will start by creating a new goal
    ifelse herd = true [set herd-size 5] [set herd-size 1]
  ]
end 

to setup-home-range
 ask rhinos [
   ask patches in-radius 1.5 with [inside? = TRUE] [  ; select patches that are around the rhino and inside the reserve
     set rhino-territory myself                       ; those patches now belong to that rhino's territory

   if visualization = "rhino_home-ranges" [            ; home ranges will be visualised if the user strongly desires so.
     set pcolor [color] of myself + 2]                 ; colour of the patches is similar to the color of the rhino
   ]
if random-float 1 < 0.5  [                             ; 50% chance of..
  ask patch-here [                                     ; leaving rhino activity signs on the current patch
   set recent-rhino-activity rhino-activity-decay + random 500]
]
]
end 

to spread-rhinos
let spreading-rhinos rhinos with [any? other turtles in-radius 10]
if any? spreading-rhinos [
  ask one-of spreading-rhinos [
    let available-patches patches with [inside? = TRUE and not any? other turtles in-radius 10]
; IF - there are any patches without a rhino nearby, move rhino to that patch.
   ifelse any? available-patches [
      move-to one-of available-patches
      spread-rhinos
    ]
; ELSE - if no patches are available anymore, pick a random spot
    [ move-to one-of patches with [inside? = TRUE and not any? other turtles-here ] ]
   ]
]
end 

to release-poachers
set-default-shape poachers "person"                     ; person symbol represents poachers
ask n-of num-poachers patches with [inside? = FALSE] [  ; sprout poachers only on the borders
    sprout-poachers 1 [                                 ; create the poachers, then initialize their variables
      set color blue
      set size 2
      set time 0                    ; poachers have not spend time in the reserve yet
      set laylow ( poacher-time * 2 ) + random 100  ; how long to wait in between hunts
      set good-sites no-patches     ; memories of good hunting grounds
      set success-sites no-patches  ; memories of successful rhino kill sites
      set failure-sites no-patches  ; memories of unsuccessful hunts
      set poacher-memory no-patches ; memories of previous patches
      set poacher-goal patch-here   ; poacher will start by creating a new goal
      set state "journey-to-crime"  ; poacher will go hunting
    ]
]
end 

to build-camps
  set-default-shape camps "house"                                             ; house symbol represents the base camps

  if camp-placement = "random" [                                              ; distribute the camps randomly across the reserve
    ask n-of num-camps patches with [inside? = TRUE and roughness = 1] [     ; but only inside, and for easily accessible areas
      sprout-camps 1 ]
  ]

 if camp-placement = "fixed" [   ; when running model 500 times sets camp at fixed coordinates )
   let camp-coordinates (patch-set patch 0 0  patch (min-pxcor + 1 + random 10) (min-pycor + 1 + random 10)  patch (min-pxcor + 1 + random 10) (max-pycor - 1 - random 10)
     patch (max-pxcor - 1 - random 10) (max-pycor - 1 - random 10) patch (max-pxcor - 1 - random 10) (min-pycor + 1 + random 10))
   ask n-of num-camps camp-coordinates [
     sprout-camps 1]
 ]
end 

to distribute-camps
 let camps-too-close camps with [any? other camps in-radius 10]
 if any? camps-too-close [
   ask one-of camps-too-close [
     let available-patches patches with [inside? = TRUE and not any? other camps in-radius 10]
     ifelse any? available-patches [
       move-to one-of available-patches
       distribute-camps
     ]
     [ move-to one-of patches with [inside? = TRUE and not any? other turtles-here] ]
   ]
 ]
  ask camps [
    ask patches in-radius 4.5 [
      set resources 0
    color-resources]
    set size 2
    set color red]
end 

to click-camps
    if mouse-down? [
    ask patch mouse-xcor mouse-ycor [
      sprout-camps 1 ]
    stop]
end 

to release-rangers
  set-default-shape rangers "person soldier"  ; soldier symbol represents rangers
  repeat num-rangers [                        ; for N rangers, repeat the following
  ask one-of camps [                          ;
    hatch-rangers 1 [                         ; create a ranger at a random camp
      set color red
      set size 2
      set patrol-memory no-patches            ; memories of previous patches
      set patrol-time 0                       ; represents how long the poacher has been on patrol today
      set risky-areas no-patches              ; remember areas where the ranger has found evidence of poaching
      set safe-areas no-patches
      set rhino-sightings no-patches          ; remember areas where the ranger has seen a rhino
      ifelse coordinated = false [set off-duty-time (patrol-length * 2) + random 100] [set off-duty-time patrol-length * 2] ; JJJJ
      ;set off-duty-time ( patrol-length * 2 ) + random 100  ; how long to wait in between patrols
      set ranger-goal patch-here
      set state "patrolling"
      ifelse random 2 = 0 [                   ; for fence patrols...
        set direction 1 ]                     ; ... 1 follows right-hand fence
      [ set direction -1 ]                    ; ... -1 follows left-hand fence
      face one-of neighbors4
    ]
  ]
  ]
end 

to-report ticks-to-stay-on-patch [p]
  report roughness - 1
end 

to rhino-goal-check
ifelse ticks-wait > 0 [
  set ticks-wait ticks-wait - 1 ]

; IF - rhino has completed his goal in life
[ ifelse rhino-goal = patch-here [
   rhino-decision-making]                             ; do rhino stuff

; ELSE - if rhino is still moving towards goal
; IF - rhino is within reach of his goal
 [ifelse member? rhino-goal neighbors [
   move-to rhino-goal ]
 [ rhino-movement ]
 ]

if ( roughness > 1)
  [ set ticks-wait ticks-to-stay-on-patch patch-here ]
]
end 

to rhino-movement
  let surroundings neighbors with [inside? = TRUE]
  let max-goal-dist distance rhino-goal

  ask surroundings [
    let goal-dist (max-goal-dist - distance [rhino-goal] of myself) * goal-weight
    let estimated-roughness ((max-roughness - roughness) / max-roughness) * roughness-weight
    let estimated-resources resources * resources-weight
    set patch-attractiveness (goal-dist + estimated-resources + estimated-roughness + rhino-dist) / (rhino-weight + goal-weight)
    if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
  ]
  ask surroundings with [rhino-territory != myself and rhino-territory != nobody] [
    set patch-attractiveness patch-attractiveness / 2 ]

  move-to rnd:weighted-one-of surroundings [patch-attractiveness]
end 

to rhino-decision-making
  let surroundings patches in-radius 2.5 with [inside? = TRUE and not member? self [rhino-memory] of myself]

  ask surroundings [
    let estimated-roughness ((max-roughness - roughness) / max-roughness) * roughness-weight
    let estimated-resources resources * resources-weight
    set patch-attractiveness (estimated-resources + estimated-roughness + rhino-dist) / rhino-weight
  ]
  ask surroundings with [rhino-territory != myself and rhino-territory != nobody] [
    set patch-attractiveness patch-attractiveness / 10]

  set rhino-goal rnd:weighted-one-of surroundings [patch-attractiveness]
  ifelse member? rhino-goal neighbors [  ; if the goal is a neighbouring patch... ???? add intervals here?
     move-to rhino-goal]                  ; move to that patch
   [ rhino-movement ]                     ; otherwise get closer to the goal patch
end 

to-report rhino-dist
  ifelse any? other rhinos [
    let max-rhino-dist distance min-one-of other rhinos [distance myself]
    ifelse max-rhino-dist = 0 [
      report 0 ]
    [ report (distance min-one-of other rhinos [distance myself] / max-rhino-dist) * rhino-avoid-weight ]
  ]
  [ report 0 ]
end 

to update-rhino-memory
set rhino-memory lput patch-here rhino-memory               ; remember the current patch
set rhino-memory remove-duplicates rhino-memory             ; clean up the valuable memory space
if length rhino-memory > 3 [                                ; if the rhino has more than three patches in its memory
  set rhino-memory but-first rhino-memory]                  ; forget the oldest (first) one
end 

to rhino-foraging-and-home-range
ask patch-here [
  set resources (resources * ((100 - forage-amount) / 100)) ; eat some proportion of available resources
  set countdown sprout-delay-time                           ; resources will grow back after sprout delay time.
  set rhino-territory myself                                   ; include current patch to home range

 if visualization = "rhino_home-ranges"[                  ; home ranges will be visualised if the user strongly desires so.
   set pcolor [color] of myself + 2]                      ; home range colours are similar to the rhinos colour

if random-float 1 < 0.5 [                                       ; 50% chance of...
  set recent-rhino-activity rhino-activity-decay + random 500]  ; ...dropping rhino activity signs
]
end 

to update-home-range
      if visualization = "rhino_home-ranges"[
        set pcolor [pcolor] of one-of neighbors with [inside? = TRUE]
      ]
end 

to poacher-goal-check
  pen-down
; IF - poacher is moving through rough terrain
  ifelse ticks-wait > 0 [
  set ticks-wait ticks-wait - 1 ]
  [
; ELSE - poacher will move and make decisions
; IF - poacher has no horn and still time left to hunt
  ifelse state = "journey-to-crime"
  [ poacher-journey-to-crime ]            ; searching for rhinos and avoid rangers

; ELSE - no time is left or the poacher obtained a rhino horn, he will move to the nearest patch outside the reserve
  [ poacher-journey-after-crime ]

  if time >= poacher-time [               ; if no time is left to continue the hunt?
    set state "journey-after-crime" ]

  if roughness > 1 [
  set ticks-wait ticks-to-stay-on-patch patch-here]
  ]
  ask patch-here [
    if random-float 1 < 0.5 [               ; 50% chance of...
      set poacher-signs human-signs-decay ] ; ...dropping poacher activity signs
  ]
  set time time + 1
end 

to poacher-journey-after-crime
  let closest-exit min-one-of patches with [ inside? = FALSE ] [ distance myself ]
  set poacher-goal closest-exit

; IF - poacher is within reach of his goal
ifelse distance poacher-goal <= 1 [
  move-to poacher-goal]                    ; if so, move to goal

; ELSE - move closer to goal
[face poacher-goal
  forward 1]
end 

to poacher-journey-to-crime
 let target one-of rhinos in-radius poacher-vision          ; are there any rhinos around?
; IF - a rhino is nearby, the poacher will go there and kill it
  ifelse target != nobody [
    poacher-kills-rhino ]

; IF - poacher has completed his goal in life
 [ ifelse poacher-goal = patch-here [
    poacher-decision-making ]                             ; do sneaky poacher things

; ELSE - if poacher is still moving towards goal
; IF - poacher is within reach of his goal
 [ifelse member? poacher-goal neighbors [
   move-to poacher-goal ]
 [ poacher-movement ]
 ]
 ]
  set poacher-memory (patch-set poacher-memory patch-here)     ; remember the patches on the journey to crime

 if recent-rhino-activity > 0 and ranger-signs = 0 [           ; remember good hunting areas
    set good-sites (patch-set good-sites patch-here)
; IF - the good hunting site was in the failure-memory, remove that patch from failure-memory
    if (member? patch-here [good-sites] of self) and (member? patch-here [failure-sites] of self) [
      set failure-sites failure-sites with [[patch-here] of myself != self]]
    ]

  if ranger-signs > 0 [                                        ; remember areas with high ranger activity
    set failure-sites (patch-set failure-sites patch-here)
; IF - the high ranger activity site was in the good hunting site memory, remove that patch from hunting-memory
    if (member? patch-here [failure-sites] of self) and (member? patch-here [good-sites] of self) [
      set good-sites good-sites with [[patch-here] of myself != self]]
  ]
end 

to poacher-movement
  let nearby-rangers (turtle-set rangers camps)
  if any? nearby-rangers in-radius poacher-vision [                        ; look around and see if any rangers are nearby
    set failure-sites (patch-set failure-sites patches in-radius poacher-vision) ]                         ; remember this patch as failure-sites

  let max-goal-dist distance poacher-goal

  ask neighbors with [inside? = TRUE] [
    let goal-dist (max-goal-dist - distance [poacher-goal] of myself) * goal-weight
    let rhino-signs (recent-rhino-activity / (rhino-activity-decay * 2)) * hunt-rhino-weight
    let nearby-ranger-signs ((human-signs-decay - ranger-signs) / human-signs-decay) * ranger-avoid-weight
    let estimated-roughness ((max-roughness - roughness) / max-roughness) * roughness-weight
    let estimated-resources resources * resources-weight
    set patch-attractiveness (goal-dist + estimated-resources + estimated-roughness + ranger-dist + rhino-signs + nearby-ranger-signs) / (poacher-weight + goal-weight)
    if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
  ]
  let surroundings neighbors with [inside? = TRUE and not member? self [poacher-memory] of myself]
  ifelse any? surroundings [
    move-to rnd:weighted-one-of surroundings [patch-attractiveness] ]
  [ move-to rnd:weighted-one-of neighbors with [inside? = TRUE] [patch-attractiveness] ]
end 

to poacher-decision-making
 let nearby-rangers (turtle-set rangers camps)
 if any? nearby-rangers in-radius poacher-vision [                ; look around and see if any rangers are nearby
   set failure-sites (patch-set failure-sites poacher-memory)     ; remember this patch as failure-sites
   set state "journey-after-crime" ]                              ; when poacher spots a ranger or camp he will get out of reserve

let surroundings patches in-radius poacher-vision with [inside? = TRUE]
ask surroundings [
  let rhino-signs (recent-rhino-activity / (rhino-activity-decay * 2)) * hunt-rhino-weight
  let nearby-ranger-signs ((human-signs-decay - ranger-signs) / human-signs-decay) * ranger-avoid-weight
  let estimated-roughness ((max-roughness - roughness) / max-roughness) * roughness-weight
  let estimated-resources resources * resources-weight
  set patch-attractiveness (ranger-dist + rhino-signs + nearby-ranger-signs + estimated-resources + estimated-roughness) / poacher-weight
  if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
]
ask surroundings with [member? self [poacher-memory] of myself] [
  set patch-attractiveness patch-attractiveness / 10
]
set poacher-goal rnd:weighted-one-of surroundings [patch-attractiveness]       ; the higher patch attractiveness, the more likely the poacher will go there

  ifelse member? poacher-goal neighbors [  ; if the goal is a neighbouring patch...
     move-to poacher-goal]                  ; move to that patch
   [ poacher-movement ]                     ; otherwise get closer to the goal patch
end 

to-report ranger-dist
  let nearby-rangers (turtle-set rangers camps)
  ifelse any? nearby-rangers [
    let max-ranger-dist distance min-one-of nearby-rangers [distance myself]
    ifelse max-ranger-dist != 0 [
      report (distance min-one-of nearby-rangers [distance myself] / max-ranger-dist) * ranger-avoid-weight ]
  [ report 0 ]
  ]
  [ report 0 ]
end 

to-report other-patrol-dist
    let nearby-rangers (turtle-set other rangers camps)
    ifelse any? nearby-rangers [
      let max-ranger-dist distance min-one-of nearby-rangers [distance myself]
      ifelse max-ranger-dist != 0 [
        report (distance min-one-of nearby-rangers [distance myself] / max-ranger-dist) * ranger-avoid-weight ]
    [ report 0 ]
    ]
  [ report 0 ]
end 

to poacher-kills-rhino
  let target one-of rhinos in-radius 1.5
  move-to target                                           ; go to where the rhino is
  ask target  [if herd-size >= 1 [set herd-size herd-size - 1] ; JJJJ
    if herd-size = 0 [die]]
  set poacher-goal patch-here                              ; update poacher goal
  set success-sites (patch-set success-sites patch-here)   ; remember these patches as successful kill sites
  set poacher-memory no-patches                            ; no need to remember the route, only the success site matters now
  set state "journey-after-crime"
  ask patch-here [
    set poacher-signs poacher-signs + carcass-decay        ; rhino carcass is an important sign of poaching
  ]
end 

to poacher-laylow
pen-up
if poacher-goal = patch-here and state = "journey-after-crime" [  ; if the poacher has escaped the reserve and obtained a horn
  set laylow laylow - 1]                                          ; lay low and wait until it's time again

if (laylow = 0) [                                                 ; when the waiting is done or when the poacher was unsuccessful...
  poacher-plan-new-trip                                           ; try again.
]
end 

to poacher-plan-new-trip
  let good-options (patch-set success-sites good-sites)
  ; IF - no signs of rangers or rhinos, then pick a random spot along the border
  ifelse good-options = nobody or count good-options = 0 [
    move-to one-of patches with [inside? = FALSE and not member? self [failure-sites] of myself]
  ]
; ELSE - make a weighted decision on where to enter next
  [ let new-trip-weight success-weight + hunt-rhino-weight + ranger-avoid-weight

    ask good-options [
      let recent-rhino-kill (poacher-signs / carcass-decay) * success-weight
      let detected-rhino-signs (recent-rhino-activity / (rhino-activity-decay * 2)) * hunt-rhino-weight
      let detected-ranger-signs ((human-signs-decay - ranger-signs) / human-signs-decay) * ranger-avoid-weight

    set patch-attractiveness (recent-rhino-kill + detected-rhino-signs + detected-ranger-signs) / new-trip-weight

    if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
    ]

  let best-option max-one-of good-options [patch-attractiveness]
  ; this compares the best option with a random number.
  ; IF - random number is smaller than the patch-attractiveness of the best option, he will choose among the available options
  ifelse random-float 1 < [patch-attractiveness] of best-option [
    move-to rnd:weighted-one-of good-options [patch-attractiveness] move-to one-of patches in-radius 1.5
    move-to min-one-of patches with [inside? = FALSE] [distance myself]]

  ; ELSE - random number is higher than highest patch-attractiveness, and poacher will pick a random location
  [ move-to one-of patches with [inside? = FALSE] ]
  ]

  set state "journey-to-crime"
  set laylow (poacher-time * 2 ) + random 100     ; reset the poacher-own parameters
  set time 0                ;
  set poacher-memory no-patches
  set poacher-goal patch-here
end 

to ranger-goal-check
  pen-down
; IF - ranger is moving through rough terrain
  ifelse ticks-wait > 0 [
  set ticks-wait ticks-wait - 1 ]
  [
; ELSE - rangers will move and make decisions
    let target one-of poachers in-radius ranger-vision with [inside? = TRUE]   ; are there any poachers around?
    ifelse target != nobody [
      rangers-catch-poachers ]
; IF - ranger has time to patrol
[  if state = "patrolling" [
; select the type of patrol we specified in the patrol-type menu
    ifelse patrol-type = "standard-patrol" [
      ranger-patrol ]
    [ ranger-fence-patrol ]
  ]
  if state = "follow-up" [
    ranger-follow-up ]
; ELSE - no time is left he will move to the nearest patch outside the reserve or camp
 if state = "back-to-camp" [
   ranger-to-camp ]

  if patrol-time >= patrol-length [
    set state "back-to-camp"
  ]
   if roughness > 1 [
   set ticks-wait ticks-to-stay-on-patch patch-here ]
  ]
  ]

ask patch-here [
  if random-float 1 < 0.5 [               ; 50% chance of...
     set ranger-signs human-signs-decay  ; ...dropping poacher activity signs
  ]
]
if any? poachers in-radius ranger-vision with [inside? = TRUE] [
  rangers-catch-poachers ]

set patrol-time patrol-time + 1                                  ; time is passing by
set patrol-memory (patch-set patrol-memory patch-here)           ; remember the current patch

if poacher-signs > 0 [
  set risky-areas (patch-set risky-areas patch-here)
  if (member? patch-here [risky-areas] of self) and (member? patch-here [safe-areas] of self) [
      set safe-areas safe-areas with [[patch-here] of myself != self]]
]
let new-rhino-sighting any? rhinos-on neighbors
  if new-rhino-sighting = TRUE [
    set rhino-sightings (patch-set rhino-sightings neighbors)
  ]
if poacher-signs = 0 [
  set safe-areas (patch-set safe-areas patch-here)
   if (member? patch-here [safe-areas] of self) and (member? patch-here [risky-areas] of self) [
      set risky-areas risky-areas with [[patch-here] of myself != self]]
   ]
end 

to ranger-to-camp
  let closest-border min-one-of patches with [ inside? = FALSE ] [ distance myself ]  ; calculate distance to nearest border
  let closest-camp min-one-of camps [ distance myself ]                                ; calculate distance to nearest camp

  ifelse distance closest-border < distance closest-camp                               ; compare the two and set goal to the nearest
   [ set ranger-goal closest-border ]
   [ set ranger-goal closest-camp ]

  ifelse distance ranger-goal <= 1 [                                                   ; if the goal is a neighbouring patch...
     move-to ranger-goal]                                                              ; move to that patch
   [face ranger-goal                                                                   ; otherwise get closer to the patch
     forward 1]
end 

to ranger-patrol
; IF - ranger completed his goal in life
ifelse ranger-goal = patch-here [
  ranger-decision-making]                             ; do brave ranger things

; ELSE - if ranger is still moving towards goal
; IF - ranger is within reach of his goal
 [ifelse member? ranger-goal neighbors [
   move-to ranger-goal ]
 [ ranger-movement ]
 ]
end 

to rangers-catch-poachers
  let suspect one-of poachers in-radius ranger-vision with [inside? = TRUE]
  move-to suspect                                      ; go to where the poacher is
  ask suspect [ die ]                                  ; catch him
  set risky-areas (patch-set risky-areas patch-here)   ; remember these patches as risky areas
  set ranger-goal patch-here
  set state "back-to-camp"
  ask patch-here [
    set ranger-signs ranger-signs + 500 ]
  pen-up
  move-to min-one-of camps [distance myself]
end 

to ranger-movement
  if any? poachers in-radius ranger-vision with [inside? = TRUE] [  ; look around and see if any poachers are nearby
   set risky-areas (patch-set risky-areas patrol-memory)            ; remember this patch as risky-sites
 ]
 let max-goal-dist distance ranger-goal

ask neighbors with [inside? = TRUE] [
    let goal-dist (max-goal-dist - distance [ranger-goal] of myself) * goal-weight
    let rhino-signs (recent-rhino-activity / (rhino-activity-decay * 2)) * search-rhino-weight
    let nearby-poacher-signs catch-poacher-weight - ((human-signs-decay - poacher-signs) / human-signs-decay) * catch-poacher-weight ;;FIX 2-12-2017 added catch-poacher-weight - ... (3-)
    let estimated-roughness ((max-roughness - roughness) / max-roughness) * roughness-weight
    set patch-attractiveness (goal-dist +  estimated-roughness + other-patrol-dist + rhino-signs + nearby-poacher-signs) / (ranger-weight + goal-weight)
    if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
  ]
  let surroundings neighbors with [not member? self [patrol-memory] of myself]
  ifelse any? surroundings [
    move-to rnd:weighted-one-of surroundings [patch-attractiveness] ]
  [ move-to rnd:weighted-one-of neighbors [patch-attractiveness] ]
end 

to ranger-decision-making
 if any? poachers in-radius ranger-vision [                       ; look around and see if any poachers are nearby
   set risky-areas (patch-set risky-areas patrol-memory)          ; remember this patch as risky-sites
 ]
 let surroundings patches in-radius ranger-vision with [not any? camps-here and inside? = TRUE]
 ask surroundings [
   let rhino-signs (recent-rhino-activity / (rhino-activity-decay * 2)) * search-rhino-weight
   let nearby-poacher-signs catch-poacher-weight - ((human-signs-decay - poacher-signs) / human-signs-decay) * catch-poacher-weight ;;FIX 2-12-2017 added catch-poacher-weight - ... (3-)
   let estimated-roughness ((max-roughness - roughness) / max-roughness) * roughness-weight
   set patch-attractiveness (other-patrol-dist + rhino-signs + nearby-poacher-signs + estimated-roughness) / ranger-weight
   if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
]
 ask surroundings with [member? self [patrol-memory] of myself] [
  set patch-attractiveness patch-attractiveness / 10
]
set ranger-goal rnd:weighted-one-of surroundings [patch-attractiveness]       ; the higher patch attractiveness, the more likely the poacher will go there

  ifelse member? ranger-goal neighbors [   ; if the goal is a neighbouring patch...
     move-to ranger-goal]                  ; move to that patch
   [ ranger-movement ]                     ; otherwise get closer to the goal patch
end 

to-report fence? [angle]  ;; turtle procedure
  ;; note that angle may be positive or negative.  if angle is
  ;; positive, the turtle looks right.  if angle is negative,
  ;; the turtle looks left.
  report black = [pcolor] of patch-right-and-ahead angle 1
end 

to ranger-fence-patrol
  ;; turn right if necessary
  if not fence? (90 * direction) and fence? (135 * direction) [ rt 90 * direction ]
  ;; turn left if necessary (sometimes more than once)
  while [fence? 0] [ lt 90 * direction ]
  ;; move forward
  fd 1
  if poacher-signs > 0 [
   ranger-follow-up
  set patrol-time 0
  set state "follow-up"]
end 

to ranger-follow-up
; follow poacher spoor, otherwise look around for spoor
  let poacher-spoor neighbors with [poacher-signs >= 1 and inside? = TRUE]
  ifelse any? poacher-spoor with [not member? self [patrol-memory] of myself] [
    move-to max-one-of poacher-spoor [poacher-signs]]
  [ ranger-movement ]
end 

to ranger-end-patrol
; rangers will rest for a certain amount of time before starting a new patrol ???? add intervals at ranger-time. Give each a varying wait buffer?
pen-up
if state = "back-to-camp" and ranger-goal = patch-here or ranger-goal = one-of camps in-radius 1 [
  set off-duty-time off-duty-time - 1 ]

if off-duty-time = 0 [ ;;???? add intervals by letting some of them start with off-duty time >1!!! (how to do this for each turtle specifically though, and does it work at 1st patrol? Also have to change state of some at start ctrl f in desctription)
  ranger-new-patrol ]
end 

to ranger-new-patrol
  let options rhino-sightings with [not member? self [safe-areas] of myself]
  let good-options (patch-set options risky-areas)
  ; IF - no signs of poachers or rhinos, then pick a random spot along the border
  ifelse good-options = nobody or count good-options = 0 [
    move-to one-of patches with [not member? self [safe-areas] of myself]
    ranger-start-location
  ]
; ELSE - make a weighted decision on where to enter next
  [ let new-patrol-weight search-rhino-weight + catch-poacher-weight

    ask good-options [
      let detected-rhino-signs (recent-rhino-activity / (rhino-activity-decay * 2)) * search-rhino-weight
      let detected-poacher-signs ((human-signs-decay - poacher-signs) / human-signs-decay) * catch-poacher-weight

    set patch-attractiveness (detected-rhino-signs + detected-poacher-signs) / new-patrol-weight
    if patch-attractiveness < 0 [
      set patch-attractiveness 0 ]
  ]
  let best-option max-one-of good-options [patch-attractiveness]
  ; this compares the best option with a random number.
  ; IF - random number is smaller than the patch-attractiveness of the best option, he will choose among the available options
  ifelse random-float 1 < [patch-attractiveness] of best-option [
    move-to rnd:weighted-one-of good-options [patch-attractiveness] move-to one-of patches in-radius 1.5
    ranger-start-location]

  ; ELSE - random number is higher than highest patch-attractiveness, and poacher will pick a random location
  [ move-to one-of patches with [not member? self [safe-areas] of myself]
    ranger-start-location]
  ]
end 

to ranger-start-location
   ; IF - the nearest border is closer than the nearest camp
      let closest-border min-one-of patches with [ inside? = FALSE ] [ distance myself ]
      let closest-camp min-one-of camps [ distance myself ]

      ifelse patrol-type = "fence-patrol"
      [ move-to closest-border
        move-to one-of neighbors with [inside? = TRUE] ]
      [ ifelse distance closest-border < distance closest-camp [
         move-to closest-border ]

; ELSE - move to the nearest camp when nearest border is too far
     [ move-to closest-camp]
      ]

   set patrol-time 0
   set patrol-memory no-patches
   ifelse coordinated = false [set off-duty-time (patrol-length * 2) + random 100] [set off-duty-time patrol-length * 2] ; JJJJ
   ;set off-duty-time ( patrol-length * 2 ) + random 100
   set ranger-goal patch-here
   set state "patrolling"
    ifelse random 2 = 0 [
        set direction 1 ]
      [ set direction -1 ]
    face one-of neighbors4
end 

to update-activity-signs
; after every 12 ticks, remove decrease signs of rhinos, poachers, and rangers
if recent-rhino-activity > 0
 [set recent-rhino-activity recent-rhino-activity - 1]

if ranger-signs > 0
 [set ranger-signs ranger-signs - 1 ]

if poacher-signs > 0
 [set poacher-signs poacher-signs - 1 ]
end 


;****CHECKLIST****

;["poacher-vision" 1.5]
;["rough-areas" 2]
;["success-weight" 2]
;["forage-amount" 1]
;["num-rhinos" 70]
;["num-poachers" 1]
;["goal-weight" 2]
;["hunt-rhino-weight" 2]
;["ranger-avoid-weight" 3]
;["catch-poacher-weight" 3]
;["roughness-weight" 2]
;["num-camps" 1]
;["resources-weight" 3]
;["patrol-length" 50]
;["rhino-avoid-weight" 2]
;["sandy-areas" 5]
;["num-rangers" 2 4]
;["visualization" "resources_colors"]
;["search-rhino-weight" 2]
;["ranger-vision" 1.5]
;["camp-placement" "random"]
;["poacher-time" 50]
;["patrol-type" "standard-patrol"]

;repetitions: 100

;Run combinations in sequential order: checked

;Measure:
;count rhinos                ???? [No herds this starts out with 70, so x/70 killed. With herds this starts out at 350, so x/350 killed. Or compare 70 indivs with 70/5=14 herds? Many more locations for indivs in that case]
;count poachers

;Measure runs at each step: checked

;Setup commands:
;setup-park
;setup-rhino
;setup-humans

;Go commands:
;go

;Stop condition:
;count rhinos = 0 or
;count poachers = 0

;Time limit: 10000

; ASK NICK BURN IN ????

There are 3 versions of this model.

Uploaded by When Description Download
Nick van Doormaal over 6 years ago fixed ranger-movement and ranger-decision-making procedures. Code was not working as expected. Download this version
Nick van Doormaal over 6 years ago Adding poacher count to plot Download this version
Nick van Doormaal about 7 years ago Initial upload Download this version

Attached files

File Type Description Last updated
Exploring Anti-poaching Strategies for Wildlife Crime with a Simple and General Agent-Based Model _ SpringerLink.html html Published Article using this Model over 6 years ago, by Nick van Doormaal Download
Indepth Model Guide and Explanation - Rhino Poaching.pdf pdf In-depth Model Guide and Explanation for Rhino Poaching over 6 years ago, by Nick van Doormaal Download
Rhino Poaching.png preview Preview for 'Rhino Poaching' about 7 years ago, by Nick van Doormaal Download

This model does not have any ancestors.

This model does not have any descendants.