Detect a certain number of turtles on neighborhood - netlogo

I have 2 kinds of mice, a normal and a special. They are eaten by the cats.
Now I want to make the special mice harder to be eaten. So I want it only to be eaten when it is surrounded by at least 2 cats.
Is there a way to check that with a if or something?

mice-own [is-special]
to step
ask mice
[
let num-surrounding-cats count neighbors4 with [count cats-here > 0]
ifelse is-special
[if num-surrounding-cats > 1 [*eaten logic*]
[ if num-surrounding-cats > 0 [*eaten logic*]]
]
end

Related

Is there a way to create a modification of Breed-On that includes specific characteristics?

I want my forager turtles to follow a path laid down by leader turtles, and this path consists of a turtle breed called trail-markers. The forager turtles also lay down trail-markers (to reinforce the trail), so I would like them to check for leader trail-markers on some patch/patches. I know Netlogo includes breeds-on to check for the presence of members of a breed, but I need the foragers to check for blue leader trail-markers. Is there a way to do this?
Here is what I had in mind:
if count (trail-markers with [color = blue]) on patch-ahead 1 > 0 [fd 1]
But I got, error:nothing named on has been defined, which makes sense, since the Netlogo primitive is breeds-on, so I modified it to:
if any? (trail-markers with [color = blue])-on patch-ahead 1 [fd 1]
However, I simply received: error:nothing named -on has been defined instead.
See the code below. I think you just want to use trail-markers-on, but you can simplify by using any? a bit. And you might want to have the custom reporter so you can just check for blue-markers-on if you find that simpler.
breed [ trail-markers trail-marker ]
to example
; I think this is what you want
if count ((trail-markers-on patch-ahead 1) with [color = blue]) > 0 [ forward 1 ]
; this is slightly simpler, using `any?` instead of `count ... > 0`
if any? (trail-markers-on patch-ahead 1) with [color = blue] [ forward 1 ]
; you could also write a custom reporter if you'll need to get this info a lot
if any? blue-markers-on patch-ahead 1 [ forward 1 ]
end
to-report blue-markers-on [p]
report (trail-markers-on p) with [ color = blue ]
end

Operator > and combining it with number and a string in NetLogo

I want a little help. I want turtles to cooperate with 50% probability if their land parcels are > 5.
I am writing as
ifelse random 1 = 0 and land > 5
[set cooperate? true]
[set cooperate? false]
But it gives error that; The > operator can only be used on two numbers, two strings, or two agents of the same type, but not on a string and a number.
how to correct it?
Thanks
There's not quite enough information to diagnose the problem. Is this code inside an ask turtles block with the variable 'land' as a turtles-own attribute? Also, you might want to print off some values of 'land' to make sure you actually have numbers in it.
As you can see from the working example below, there is no error in the code you have provided.
turtles-own [ land cooperate? ]
to testme
clear-all
create-turtles 10
[ set land random 10
ifelse random 1 = 0 and land > 5
[ set cooperate? true ]
[ set cooperate? false ]
]
type "Cooperating: " print count turtles with [cooperate?]
type "Not cooperating: " print count turtles with [not cooperate?]
end

Netlogo: Making a turtle interact with anotherone after evaluating similarity in a given variable

I have several turtles each with three variables opinion1, opinion2 and opinion3. I need them to:
identify which of these three variables has the highest value
find another turtle in their network with a value at least as high
as the one found in 1.
update its own value found in 1. with
respect to that of the turtle found in 2.
What I have done doesn't really work because it only updates looking at o1 without really having a look at which of the tree (opinion1, opinion2 or opinion3) is the highest and THEN looking for a neighbour.
to update-opinion
ask turtles [
let my-nearby-turtles nw:turtles-in-radius 1
let my-opinion1 opinion1
set neighbour one-of my-nearby-turtles with [ opinion1 > my-opinion1 ]
if neighbour != nobody [
let opinion_n [opinion1] of neighbour
set opinion1 ((opinion1 + opinion_n) / (2))
]
]
end
I don't know a simple way to do this with unique variables like opinion1 etc, but maybe having a list of opinions instead of individual variables for each opinion will work. For example, with this setup:
extensions [ nw ]
turtles-own [
opinions
]
to setup
ca
resize-world -5 5 -5 5
set-patch-size 30
crt 30 [
set shape "dot"
set opinions n-values 3 [ precision random-float 10 2]
set color scale-color blue sum opinions -5 35
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
]
ask turtles [
create-links-with turtles-on neighbors4
]
reset-ticks
end
You get something like this:
Where each turtle has an opinions list variable that is three items long. Now, you can have each turtle determine its highest opinion value using max, get that maximum values index position in the list using position, and then query that turtle's neighbors to see if any of them have a higher value in the same index position. If they do, modify your asking turtles opinions list using replace-item to be the average of the two values:
to go
ask turtles [
; Get adjacent turtles
let my-nearby-turtles nw:turtles-in-radius 1
; Identify the highest highest value variable of
; the current turtle, and get its list position
let my-opinion max opinions
let my-op-ind position my-opinion opinions
; Pick one of the turtles whose value in the same indexed
; position is higher than my-opinion
let influence one-of my-nearby-turtles with [
item my-op-ind opinions > my-opinion
]
; If that turtle exists, update my own opinions list as appropriate
if influence != nobody [
let new-opinion precision (
( [ item my-op-ind opinions ] of influence + my-opinion ) / 2
) 2
set opinions replace-item my-op-ind opinions new-opinion
]
set color scale-color blue sum opinions -5 35
]
tick
end
Hopefully that is sort of on the right track, not sure if a list will work for what you need. If you must have the variables as standalone values at each tick, I suppose you could convert them to a list then follow the procedure above. If you only need them for output, you could just update your unique variables as needed based on the values in the list (as long as you are consistent with the order).

NetLogo in-radius

i have this code and it's not clear to me what is it doing:
patches-own [ field ]
let a max-one-of patches in-radius b [field]
ifelse ([field] of a > 0.1) and ([field] of a < 0.5)
[
;; do something
]
[
;; do something else
]
Thanks,
Marco
This is apparently code to be run by a turtle or patch, it isn't apparent which.
patches in-radius b is an agentset of the circle of patches, of radius b, around the calling agent. max-one-of ... [field] finds the patch in that agentset that has the largest value for field. That patch is then stored in the new local variable a. (A better name than a might have been winner or peak or best-patch.)
[field] of a is then that maximum value of field, the same one that max-one-of found. The ifelse checks to see if that value is in a certain range or not, and does something different, depending.
Does the code inside the ifelse make any further use of a? If it does, cool. If it doesn't, well, the code could be more easily and simply written as:
let m max [field] of patches in-radius b
ifelse m > 0.1 and m < 0.5
[
;; do something
]
[
;; do something else
]
perhaps seeing it in this form will help making the meaning clear.

NetLogo - home range model works but very slow - can it be sped up?

I've been working on a NetLogo model simulating home range (I use the terms territory and home range interchangeable) dynamics of territorial animals. In the model, females select patches with the highest prey value and add those patches to their territories. That works nicely and seems pretty fast. Males are limited by females and so will try to have their home ranges overlap multiple female home ranges. In the model, a male will occupy 90% of a single female's home range (i.e., add those same patches to his territory) and then move to the next closest female's home range (in which no other male is present) to begin occupying. This process seems to work fine but it runs exceedingly slow, to the point that I'm worried I won't be able to feasibly run many simulations. Any ideas on how to speed up this process? Am I doing something stupid, like asking all patches to do something when I don't have to? The model code is getting pretty long, so I just added the part related to the male home range growth. I can provide more code to someone if the problem seems to lie elsewhere. Any help would be much appreciated!
to update-male-home-range
ask males ; the following procedure allows males to encompass 90% of a female's home range
[
let this-male self
foreach [owner-fem] of females-in-my-territory ; the number of females in male territory is set when the males are dropped onto the landscape at tick 5. This number is updated at the end of this whole process.
[
let ? [owner-fem] of females-in-my-territory ; this ensures that the male will occupy each female territory sequentially instead of jumping back and forth
while [((count patches with [(owner-fem = ?) and (owner-male = this-male)]) / (count [territory] of ?)) < 0.9] ; the male keeps adding cells to his home range from the home range of the female until he has encompassed 90% of them
[
let avail-fem-patches no-patches
let target nobody
let new-patches no-patches
ask territory
[
; Add unoccupied neighbor patches as potential targets:
set avail-fem-patches (patch-set avail-fem-patches neighbors4 with [(owner-fem = ?) and (owner-male = nobody)])
]
; Set of all potential targets:
set new-patches (patch-set new-patches avail-fem-patches)
; Only chooses unoccupied neighbors
if any? new-patches
[
ask new-patches
[
if any? avail-fem-patches
[set target one-of avail-fem-patches]
]
move-to target ; I let the animal move so you can see which patch he chose
]
if target != nobody
[
; Add target patch to territory of the current animal:
set territory (patch-set territory target) ; this is the territory of the calling animal - we are still in its context
ask target [ set owner-male myself ] ; Tell target patch that is has new owner-male:
]
ask territory
[
set pcolor ([color] of myself) - 2
if owner-male != myself [ user-message "Something wrong" ]
]
set XY [list pxcor pycor] of territory
set X map [(item 0 ?)] XY ;getting X coordinates for home range mapping later
set Y map [(item 1 ?)] XY ;getting Y coordinates for home range mapping later
let fem-patch-in-male-hr count patches with [(owner-fem = ?) and (owner-male = this-male)] ; this is for reporting purposes only.
; This shows the number of patches belonging to the female home range that has also been claimed by the male
let size-of-fem-hr (count [territory] of ?) ; this is for reporting purposes only
; This reports the total size of the female home range that the male has begun overlapping
let fem-patch-hr-size-ratio fem-patch-in-male-hr / size-of-fem-hr ; this if for reporting purposes only
; This is ratio of the number of patches claimed by the male that belongs to the home range of the female.
; This ratio is the same as that in the "while" procedure above and shows whether the male has encompassed 90% or not.
]
;set total-females count females-in-my-territory
]
] ; ask males
ask males ; After all males have encompassed their respective female home ranges, this procedure tells the males to find the closest female home range that is unoccupied and move to it to begin overlapping her home range
[
let other-females females with [not member? self ([females-in-my-territory] of myself)] ; females not in my territory
let females-with-males females with [count males-in-my-territory != 0] ; female home ranges occupied by a male including myself
let females-with-no-males females with [count males-in-my-territory = 0] ; female home ranges with no male
let other-males-females females-with-males with [not member? myself ([males-in-my-territory] of self)] ; female home ranges occupied by a male not including myself
if count females-with-no-males > 0 ; if a female home range does not have a male occupying it
[
let target-patches no-patches
set target-patches (patch-set target-patches ([territory] of females-with-no-males in-radius 10)) ; create patch-set that is all territories of females with no males occupying their home ranges
let target-fem-patch no-patches
ask territory
[
set target-fem-patch min-one-of target-patches [distance myself] ; select the patch from female home ranges with no males that is closest to my home range. This doesn't seem like it is working quite right.
if target-fem-patch != nobody
[
move-to target-fem-patch ; move the male to this patch in the female home range previously unoccupied
set territory (patch-set territory target-fem-patch) ; update the male's territory
;let old-owner-male [owner-male] of target-fem-patch
ask target-fem-patch [ set owner-male myself ] ; update the owner
ask territory ; update the color of the patch according to the owner of the territory
[
set pcolor ([color] of myself) - 2
if owner-male != myself [ user-message "Something wrong" ]
]
set females-in-my-territory females with [member? self ([owner-fem] of [territory] of myself)] ; update the number of female home ranges that the male occupies
ask females
[
set males-in-my-territory males with [member? self ([owner-male] of [territory] of myself)] ; update the number of males that occupy each female's home range
]
]
]
ask territory ; update the patch color again because some males may not have been able to add any patches from the prior procedure
[
set pcolor ([color] of myself) - 2
if owner-male != myself [ user-message "Something wrong" ]
]
set XY [list pxcor pycor] of territory ; update the XY coordinates for the male territories for the home range calculation later
set X map [(item 0 ?)] XY
set Y map [(item 1 ?)] XY
]
end ; update-male-home-range
This is an absolutely enormous chunk of code. I try not to let my procedures get longer than about 10 or 15 lines each (and that's just a ceiling, lots of good procedures just are just 1 or 3 or 5 lines each). Otherwise the complexity is just too much deal with and it becomes almost impossible to effectively understand or troubleshoot anything.
Also, if you broke this up into smaller procedures, that would enable you to use the profiler extension to measure which ones are taking all the time.
Re "asking all patches to do something when I don't have to", yes, you are. You're doing count patches with ..., which loops over all the patches, and you're doing it inside a while loop which is inside a foreach loop which is inside an ask loop...!
I don't understand your code well enough to suggest a fix, though.
First thing that can easily be optimized:
if any? new-patches
[
ask new-patches
[
if any? avail-fem-patches
[set target one-of avail-fem-patches]
]
move-to target ; I let the animal move so you can see which patch he chose
]
You're having all new-patches set target. However, they just keep overwriting the same target variable. In fact, you don't even need the new-patches to do this. Thus, you can replace the above code with:
if any? avail-fem-patches [
set target one-of avail-fem-patches
move-to target
]
Next, this:
ask territory
[
set pcolor ([color] of myself) - 2
if owner-male != myself [ user-message "Something wrong" ]
]
keeps setting the entire territory to the same color over and over (each iteration of the loop), but you only need to set the color of the target patch, right? So this can become:
ask target [ set pcolor ([color] of myself) - 2 ]
It you keep doing maps over the territory's ycors (which is expensive in a tight loop like this), but you never actually use the results: X, Y, and XY. Bare minimum, you should do that only at the very end, outside of all the loops. But you may just be able to remove it completely.
A quick side note: new-patches effectively is just set to avail-fem-patches, since it's set to no-patches at the beginning of each iteration of the while loop, is then set to (patch-set avail-fem-patches new-patches). Is this a bug?
Finally, right now you're looking at at every single neighbor of every single territory patch to add a single patch to territory. Instead you could as many patches as possible each iteration of the loop. Something like (replacing target with targets):
let needed-patches 0.9 * (count [territory] of ?) - (count patches with [(owner-fem = ?) and (owner-male = this-male)])
ifelse count new-patches < needed-patches [
set targets new-patches
] [
set targets n-of needed-patches new-patches
]
Then you'd add all the targets to the territory. This would be behaviorally different. Right now, you can little trails cut into females' territories. Here, male's territories will expand as broadly as possible so to speak. Not sure if that's bad or not.