I have to breeds, breed1 and breed2, and only breed1 can change a variable var if members of breed2 are close enough radius 4. However, my code does not work, see below.
This is part of a code which breed1 will execute:
let x min-one-of other breed2 with [ var >= 6 ] in-radius 4 [ distance myself ] ;check whether there is one (or more) members of breed2 with a value of or above 6 of var
ifelse (x != nobody) [ ;if there is one
ask one-of breed2 in-radius 4 with [ var >= 6 ] [ set var var + 1 ] ;change value
[right random 360 forward 1] ;else walk random
My idea is that breed1 checks for members of breed2 in its vicinity (radius 4) if there is one or many, it shall change one of them with a value above 6 of a given variable (var).
However, the above code does not change the variable var. How can I achieve what I want?
I think you have a bracketing error - your then code is not ended before starting your else code. But you also have an efficiency issue because you are constructing the nearby turtles twice. Once you have x, you can simply use it. So fixing that and the bracketing error:
ifelse (x != nobody)
[ ask x [ set var var + 1 ] ] ; x changes value
[ right random 360 forward 1 ] ; the asking turtle moves
Related
This is my first Netlogo script and I am a complete beginner and need help in setting the xy coordinates for my turtles which are boats. I wish the boats to be positioned across the top of the world (in a 30 x 30 world, with origin in the bottom left-hand corner). The number of boats is selected by a slider, ranging from 1 to 4. After looking at other questions & answers, I have tried the following code, but cannot get it to work, either "expected closing bracket" or "FOREACH expected at least 2 inputs, a list and an anonymous command" errors.
create-boats N-boats ;; create the boats
[set color red ;; give them a color, a size and shape
set size 1
set shape "arrow"
(foreach [ 0 1 2 3 ] [6 12 18 24] [28 28 28 28] [ xy -> boats [ setxy item 0 xy item 1 xy ] ] )
set heading 180]]]
I also tried "set xcor one-of [6 12]", but sometimes get the boats lined up on top of each other, so I wish to specify the exact coordinates. Many thanks.
Do they have to be equally spaced? Or just anywhere along the top? If anywhere along the top, you are better off choosing 4 random patches in that row and getting each of them to sprout a boat. Something like (not tested):
ask n-of N-boats patches with [pycor = max-pycor]
[ sprout 1
[ set color red
set heading 180
set shape "arrow"
]
]
Just as a general newbie tip with NetLogo, if you are using foreach then you should immediately think about whether what you really want is some sort of agentset. It's particularly common for people coming from some other coding background to try and do things in for loops that are better handled as agentsets in NetLogo.
First, to answer your syntax issues:
Remember that the code in brackets after CREATE-TURTLES is run by a single turtle. After all the turtles are created, each turtle runs the code, one-at-a-time. It looks like you're trying to position all the turtles. That's probably not what you meant.
Second: look at the FOREACH.
( foreach [ 0 1 2 3 ] [6 12 18 24] [28 28 28 28] [ xy -> boats [ setxy item 0 xy item 1 xy ] ] )
You've got the foreach in ( and ) -- that's good.
You've got THREE separate lists as input -- that's fine, too, but looks like maybe you meant that to be one list? Not sure.
Your anonymous procedure has only ONE input: xy. That's a problem, since you have THREE lists as input.
You are referring to ITEM 0 and ITEM 1... which doesn't make a lot of sense at that point, unless you passed a list of lists, but no... still not.
Finally, it looks like you meant to ask boats but if you did, since this is inside the create-turtles code block, this is already being excuted by a boat. So, this boat will ask all boats to do something. If this was otherwise correct, you'd just do the boat commands--you are essentially already inside an "ask".
So, this is not ideal, in any case. Let's start at the top.
Three Ways to Set Turtle Location
If you want to put turtles at specific x and y coordinates, you have a few choices. Here's three:
Use Math based on the value of WHO to calculate the coordinates.
(Or a counter, if you want to keep your model "who-agnostic")
Use a set of patches (probably created using Math, too.) The patches SPROUT the turtles.
Use a List of coordinates. Each turtle pulls its location from the list.
A Note on the Examples.
All the below examples focus on setting the position. After the boats
are created, the boats are asked to run a procedure called
apply-boat-properties, which is where things like color, heading,
size, and other properties would be set. This is to remove clutter
from the examples. It also makes it quite easy to find where the
properties are being set.
to apply-boat-properties
;; run by a boat
set heading 180
set shape "arrow"
set color gray
end
Math (aka "calculated position")
You can do this is the locations are in a pattern that can be calculated. This can be easy to do, but can also be hard and require a lot of tweaking and experimentation to get just right. The weird NetLogo world geometry can sometimes be confusing.
Simple Example of Calculated Positioning
to make-fleet [ #fleet-count ]
create-boats #fleet-count
[ setxy (min-pxcor + 6 + who * 6) max-pycor
apply-boat-properties
]
Elaborate Example of Calculated Positioning
Varies the gap between boats automatically.
The boats are located without regard to patch centers,
unless "$center-on-patches?" is set to true
WHO is not used in the calculations. This ensures the math comes out right, even if other turtles already exist in the model.
to make-fleet [ $fleet-count $center-on-patches? ]
;; requires breed [ boats boat ]
set-default-shape boats "arrow"
let $boat-size 1
;; this is the real "0" in terms of even positioning
let $far-left-edge-xcor min-pxcor - 0.5
let $total-width-of-all-boats ($boat-size * $fleet-count)
let $gap-between-boat-edges (world-width - $total-width-of-all-boats) / ($fleet-count + 1)
let $gap-between-boat-centers $gap-between-boat-edges + $boat-size
let $gap-between-left-edge-and-first-boat-center $gap-between-boat-edges + ($boat-size / 2)
;; I use boat-number, rather than who,
;;so this procedure will work even if there are other turtles
let $boat-number 0 ;; 0 to (#fleet-count - 1)
create-boats $fleet-count
[ let $x 0
if-else ( $center-on-patches? )
[ set $x min-pxcor
+ floor ( $gap-between-left-edge-and-first-boat-center )
+ ceiling ( $boat-number * $gap-between-boat-centers )
]
[ ;; position without regard to patch alignment
set $x $far-left-edge-xcor
+ $gap-between-left-edge-and-first-boat-center
+ $boat-number * $gap-between-boat-centers
]
let $y max-pycor
setxy $x $y
set $boat-number $boat-number + 1
]
ask boats [ apply-boat-properties ]
end
Using a Set of Patches
This is a lot like the previous method, but we create a set of patches, then ask the patches to make the turtles. This is useful for creating a set of turtles on a specific area of the world, like on an edge, or in a specific pattern of patches, or filling an area with a randomly scattered set of turtles.
to make-fleet [ $boat-gap ]
let $locations patches with
[
;; rules to find the patches
pycor = max-pycor ;; top row
and
(pxcor - min-pxcor) mod $boat-gap = 0
]
ask $locations [ sprout 1 [ set breed boats ] ]
ask boats [ apply-boat-properties ]
end
Using A List of Coordinates
If the required coordinates are few, or are can't be calculated, you can put the coordinates in a list. The created turtles can pull the coordinates from the list.
to make-fleet [ $fleet-count ]
;; A list of x y coordinate pairs.
;; The coordinate pairs are also in a list
let $coordinates
[
; x y ;
[ 6 0 ]
[ 12 0 ]
[ 18 0 ]
[ 24 0 ]
]
;; initialize the counter uses as the list index
let $boat-number 0
;; make boats
create-boats $fleet-count
[ ;; get the coordinate pair
let $xy item $boat-number $coordinates
;; get the x and y from the pair
let $x first $xy ;; aka item 0 $xy
let $y last $xy ;; aka item 1 $xy
;; apply the coordinate
setxy $x $y
;; increment the index number
set $boat-number $boat-number + 1
]
ask boats [ apply-boat-properties ]
Note that the above will make errors if $fleet-count is more than 4, because the coordinate list has only 4 items.
You could use FOREACH on the list, and create 1 turtle for each coordinate. This is handy when a large list of coordinates have been read from a file.
to make-fleet [ $coordinates ]
;; assume $coordinates is a list of pairs of coordinates.
;; like [ [ 1 2 ] [ 3 4 ] [ 5 6 ] ]
;; we are going to ask the patch at each of the coordinates
;; to create a turtle. Then we will set up the turtle.
( foreach $coordinates
[ [ $xy ] ->
ask patch first $xy last $xy
[ sprout 1 [ set breed boats ] ]
]
)
ask boats [ apply-boat-properties ]
end
Finally
There are other ways, too, and many other formulas for calculated positions.
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).
there is a question that I want to ask that is when I trying to type this code, I got the error that is
The > operator can only be used on two numbers, two strings, or two agents of the same type, but not on a number and a list.
What I want to ask is how can I fix this, the false happen at this line on the code :
if pri-lev > [pri-lev] of oppoint1 and pri-lev > [pri-lev] of oppoint2
I tried to change it into "cars-on" or "cars with" but they are all useless. I also try to find on the Netlogo dictionary but I found no results on the code for directing an agent on a specific path.
What I am trying to do here is when an agent comes to a specific section, it will check if any agents listed as "oppoint1"; "oppoint2"; "oppoint3"; "oppoint4" and then compare a value call pri-lev to others value for setting its decision on keeping on moving or stopping and wait for others.
These are the part of my code:
ask cars
[
let oppoint1 (cars-at (xcor + 2) (ycor + 2))
let oppoint2 (cars-at (xcor - 1) (ycor + 1))
let oppoint3 (cars-at (xcor - 2) (ycor + 1))
let oppoint4 (cars-at (xcor - 3) (ycor + 1))
ifelse oppoint1 != nobody and oppoint2 != nobody
[
if pri-lev > [pri-lev] of oppoint1 and pri-lev > [pri-lev] of oppoint2
[
set pri-lev 4
speed-up
]
]
[
if oppoint2 = nobody and oppoint3 = nobody and oppoint4 = nobody
[
set speed 1
fd speed
if turning = "Rtrue"
[
set heading heading + 90
speed-up
]
]
]
]
Sincerely, Minh
it seems that the reason you are getting this error is that you are comparing the attribute of one (the current car) to the attributes of many (the oppoint agent-sets). Your code now says something like "If my privilege is greater than the privilege of that group, do this thing..." The problem is that [pri-lev] of oppoint1 returns a list of the pri-lev of all members of the oppoint1 agentset, like [ 10 12 13 24 ], and Netlogo won't automatically iterate over that list and compare each item to the attribute of the asking turtle.
There are several ways to deal with this. For example, you could make sure that you only ever compare two turtles- maybe by making sure that you only ever have one turtle per patch at a given time. If you are going to potentially compare one agent to an agent-set, you can use the any? primitive to check if any members of the group you're looking at satisfy your conditional statement. For example, given this setup:
turtles-own [
pri-lev
]
to setup
ca
reset-ticks
crt 10 [
set pri-lev 1 + random 10
]
end
You can ask one-of your turtles to check if not any? of the turtles on the current patch have a higher pri-lev than the asking turtle. If none of them do, the current turtle will move forward. Otherwise, it will print that there is another turtle with a higher pri-lev on the current patch.
to compare-with
ask one-of turtles [
let other-turtles other turtles-here
ifelse not any? other-turtles with [ pri-lev > [pri-lev] of myself ] [
fd 1
]
[
print ("A turtle here has a higher pri-lev than I do." )
]
]
tick
end
I'm new to NetLogo and am attempting to model home range selection of subsequent colonizers. The model should follow simple steps:
Individual 1 picks a home range (a subset of patches).
When individual 1 is done picking its home range, it hatches new
individual 2.
Individual 2 picks a home range, then hatches individual 3.
Individual 3 picks a home range, and so on.
I'm having trouble figuring out how to get this to work. I can get the first turtle to pick a home range. But the offspring do not. Writing the code numerous ways has only accomplished two unintended outcomes. Either endless new individuals are hatched simultaneously, before the first turtle has a home range, and the new turtles fail to pick a home range. Or, the first turtle picks its home range and hatches a new turtle, but that new turtle doesn't pick a home range. Neither outcome is what I want.
How do I set this up to run as intended, so that hatchlings pick home ranges too? Here is one simplified version of my code:
to setup-turtles
crt 1
[setxy random-xcor random-ycor]
end
to go
ask turtles [pick-homerange]
tick
end
to pick-homerange
while [food-mine < food-required] ;; if not enough food, keep picking patches for home range
[;; code to pick home range until it has enough food; this is working okay
]
[;; when enough food, stop picking home range
hatch 1 fd 20 ;; now hatch 1, move new turtle slightly away
]
end
So it is at this last part, once the home range is built, that I want a new turtle to hatch from its parent. I then want that turtle to repeat the pick-homerange procedure. How could that be coded to happen? I've tried writing this every way I can think of; nothing is working. Thanks in advance for any assistance!
One way to do this is to have each patch equal one "food value", and have turtles grow their home range until their home range supplies them with enough food. I would set this up so that patches "know" to which turtle they belong, and so that turtles know how much food they need, which patches are part of their home range, and the food supplied by their homerange. Example patch and turtle variables would then be:
patches-own [
owned_by
]
turtles-own [
food_required
my_homerange
homerange_food
]
Then, your turtles can add patches into their home range until they hit their "food_required", whatever you set that as. For simplicity, in this example I assume that turtles are territorial and so won't "share" home ranges. Further explanation of steps is commented in the code below. This is intended just to get you started- for example, it will hang if you run pick-homerange too many times.
to setup-turtles
crt 1 [
set size 1.5
setxy random-xcor random-ycor
set food_required 5 + random 5
set homerange_food 0
set my_homerange []
]
end
to pick-homerange
ask turtles [
;; Check if the current patch is owned by anyone other than myself
if ( [owned_by] of patch-here != self ) and ( [owned_by] of patch-here != nobody ) [
;; if it is owned by someone else, move to a new patch that is not owned
let target one-of patches in-radius 10 with [ owned_by = nobody ]
if target != nobody [
move-to target
]
]
;; Now add the current patch into my homerange
ask patch-here [
set owned_by myself
]
set my_homerange patches with [ owned_by = myself ]
;; calculate the number of patches currently in my homerange
set homerange_food count patches with [owned_by = myself]
;; Now grow the homerange until there are enough patches in the homerange
;; to fulfill the "food_required" variable
while [ homerange_food < food_required ] [
let expander one-of my_homerange with [ any? neighbors with [ owned_by = nobody ] ]
if expander != nobody [
ask expander [
let expand_to one-of neighbors4 with [ owned_by = nobody ]
if expand_to != nobody[
ask expand_to [
set owned_by [owned_by] of myself
]
]
]
]
;; Reassess homerange food worth
set my_homerange patches with [ owned_by = myself ]
set homerange_food count patches with [owned_by = myself]
]
ask my_homerange [
set pcolor [color] of myself - 2
]
;; Now that my homerange has been defined, I will hatch a new turtle
hatch 1 [
set color ([color] of myself + random 4 - 2)
]
]
end
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.