Henk
Henk

Reputation: 3656

recursion in NetLogo

In NetLogo 6.1.1 I have one breed (rangers) looking for another breed (snares) in green patches (bush).

The behaviour that I can't get is this:

  1. if a snare is found, remove the snare with 80% success rate; then repeat the same procedure (hotspot-search; recursive call).
  2. if the snare is not found (20% probability) then repeat the same procedure (hotspot-search; the commented out section -> causes an endless loop) 5 times.

  3. if no snares are removed in these 5 times, resume normal behaviour (move by random right turn and forward 1).

How can I do this?

;; globals =========================
breed [rangers ranger]
breed [snares snare]
rangers-own [snare-found?]

;; initialise ========================
to setup

  resize-world -4 4 -4 4

  clear-all

  create-rangers 1 [set color blue]

  ask patches [
    if random 100 < 20 [set pcolor green]]

  ask patches with [pcolor = green] [
    sprout-snares random 5]

  ask snares [
    set size 0.5 
    set shape "dot"
    fd 0.25
  ]

  reset-ticks

end

;; main ==================================
to go
  ask rangers [
    rt random 181 - 90
    fd 1
    if any? snares-here [hotspot-search]
    hotspot-search 
  ]

end

;; functions ===============================
to hotspot-search
  move-to patch-here
  let target one-of snares-here

  if (random 100 < 20) and (target != nobody) [
    ask target [die]
    set snare-found? true
    hotspot-search
  ]

  ;;if snare-found? = true [
  ;; repeat 5 [hotspot-search]
  ;;]

end

Upvotes: 1

Views: 730

Answers (1)

Jasper
Jasper

Reputation: 2780

One observation I'd make is that if you're wanting the rangers to search 5 times at a 20% chance of success, but there is no cost for searching, like lost time or energy, you can just do a single check at a 67% chance of success (1.00 - 0.80^5) = 0.67.

But if you do need have a cost or need to track the number of searches or something like that, below is how I'd write the code. Sorry for writing from scratch rather than updating yours, I was just trying to keep things as simple as possible.

breed [ rangers ranger ]
breed [ snares snare ]

to setup
  create-snares 100 [
    set shape "circle"
    set color blue
    set size 0.5
    move-to one-of patches
  ]
  create-rangers 10 [
    set color red
    move-to one-of patches 
  ]
end

to go
  ask rangers [
    move-to one-of neighbors4
    ; call our procedure with the starting limit of 5
    hunt-snares 5
  ]
end

to hunt-snares [ search-limit ]
  ; the recursive base case is search-limit of 0
  if ( search-limit > 0 ) [
    ; can only find a snare if one exists here
    ifelse random 100 < 20 and any? snares-here [
      ; found one
      ifelse random 100 < 80 [
        ; disabled
        ask one-of snares-here [ die ]
        ; restart the search 
        hunt-snares 5 
      ] [
        ; we found a snare but failed to disable it, unclear what to do?
        hunt-snares 5
      ]
    ] [
      ; failed to find one, move towards the base case
      hunt-snares (search-limit - 1)
    ]
  ]
end

Edit to add: Sorry, I thought your original code was more complicated, it actually looks relatively simple and I probably should've just modified your version. The reason your hotspot-search procedure is going into an infinite loop is because snare-found? is never set to false anywhere in your code. The typical way to handle recursion is to have one parameter of the recursive procedure progress towards a base case where the last recursive call can quit and the whole chain of calls will end, too.

In this case we have two complications: 1) an implicit base-case that isn't a parameter - that there are still snares on the patch to try to disarm, and 2) that we can reset our parameter farther from the base case, knowing that item 1 means we won't loop over.

Upvotes: 1

Related Questions