Search code examples
netlogotarget

Setting new target patch but excluding current in Netlogo


I am creating a simulation which copies shoplifter behaviour. Turtles are split between "professional" and "novice" shoplifters and if "professionals" are apprehended by store security they might (1/2) want to select a new store to target "new-store-required".

"professional" shoplifters target the store with the lowest "security" value in a certain radius, all values are set as they are created.

I am trying to set a new "target-store", a "store" in-radius 10 with the second lowest "security", i.e. excluding the current "target-store" but I am having difficulty.

So far I have attempted to made several additions to the following code to exclude the current target store, this includes variations of "member? my patches" as the "store" where the shoplifter has been apprehended is added to this "patch-set" which will inform a later command. Also I have made a list of ascending "security" values to tell the "shoplifter" to target the "store" with "security" (the value which determines store vulnerability) the same as item 1 on the list, but I fear this might not work because their original target-store might not necessarily be item 0 as they target the store with the lowest "security" in a 10 unit radius.

These are the lines of code I am working with at the moment, any suggestions would be greatly appreciated.

***Edit: I could ideally like the code to make use of "mypatches" so each time a professional shoplifter is apprehended at a store that store can be added to mypatches and the subsequent target-store can exclude all stores which are members of mypatches.

to new-target-store
ask turtles [ if
new-store-required = 1 and professional = 1 and    (random-float 1 < 0.5) [  
set target-store min-one-of store in-radius 10 [security]
]
]

end

Edit 2: I've fixed what was wrong.


Solution

  • You may want to include your setup code, or a stripped-down version of it if it's really long, to make sure that answers conform to the structure you've used. I would approach this by having a turtles-own variable to store their current target, which they can try to fill if it is empty (rather than using an extra boolean for that purpose). Also, you may want to convert your 1/0 options to true/false for cleaner code. Check out this example setup:

    globals [ stores ]
    
    patches-own [ security ]
    
    turtles-own [ 
      current-target 
      professional?
      mypatches 
    ]
    
    to setup
      ca
      ask n-of 20 patches [
        set pcolor green
        set security 1 + random 10
      ]
      set stores patches with [ pcolor = green ]
    
      crt 5 [
        setxy random-xcor random-ycor
        pd
        set professional? one-of [ true false ]
        set current-target nobody
        set mypatches ( patch-set )
      ]
      reset-ticks
    end
    

    This sets up a world with some green patches that are grouped into the patch-set called stores. Also, you have some turtles that have the boolean professional? set to either true or false. They initialize with no current-target store, and an empty mypatches patch-set variable.

    Now, you can have turtles check if their current-target exists. If it does not, they can assign a store to that variable from the set of stores (possible-targets, here) that are not equal to the patch-here of the asking turtle. Professional thieves can further refine possible-targets to exclude any stores at which they have been apprehended, by excluding any stores that are a member of their mypatches patch-set variable. More details in comments:

    to go
      ask turtles [
        ; if you have no target currently
        if current-target = nobody [
          ; Create a temporary patch set made up of all stores except for
          ; the one that I'm currently in
          let possible-targets stores with [ self != [patch-here] of myself ]
          ifelse professional? [
            ; Have professional thieves revise their possible targets to exclude
            ; any in the patchset mypatches, then choose a possible target
            set possible-targets possible-targets with [ not member? self [mypatches] of myself ]
            set current-target min-one-of possible-targets in-radius 10 [ security ]
          ] [
            ; Have amateur thieves choose randomly from the possible targets
            set current-target one-of possible-targets 
          ]
        ]
        ; move closer to your current target, or
        ; move to it exactly if you're near enough
        ifelse current-target != nobody [
          face current-target 
          ifelse distance current-target > 1 [
            fd 1 
          ] [ 
            move-to current-target
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            ; *** do your shoplifting attempt/check here ***
            ; For this example, just have professional thieves sometimes
            ; add this patch to their mypatches patchset
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            if professional? and random-float 1 < 0.5 [
              set mypatches ( patch-set mypatches patch-here )
            ]        
            ; Reset current-target to nobody
            set current-target nobody
          ]
        ] [
          ; if no suitable nearby targets, wander randomly
          rt random 61 - 30
          fd 1
        ]
      ]
      tick        
    end
    

    If you run that long enough, eventually your professional thieves will stop being able to find target stores as they have added all stores to their mypatches variable.