I don't understand why something appened in my netlogo code, but finally I found that a global variables change values from turtles to turtles, is this possible?
I noticed this because I have 2 print value in my code like this:
breed [players player]
breed [balls ball]
globals [
TURNS;
TEAM-OWNER
]
to setup
clear-all
reset-ticks
set TURNS 0
setup-players
setup-ball
end
to setup-ball
create-balls 1 [
setxy 0 0
set color orange
set shape "bug"
set size 2.5
]
end
to setup-players
create-players 5 [
setxy 0 0
set color white
set shape "bug"
set size 2.5
]
end
to go
set TURNS TURNS + 1
print word "this is the turns " TURNS
print ( word " values " TEAM-OWNER)
if ticks >= 1000 [ stop ]
ask players [
print ( word " values " TEAM-OWNER)
fd 2
set TEAM-OWNER "red"
]
ask balls [
fd 2
set TEAM-OWNER "black"
]
end
Is this possible? Global values doesn't change it values in all turtles?
This is the print that I got:
this is the turns 1
values 0
values 0
values red
values red
values red
values red
this is the turns 2
values black
values black
values red
values red
values red
values red
It has not be like black 1 times ? and red the other times? And Why I get 2 blacks?
A global variable is global - there is only ONE copy of it and all turtles retrieve and modify the same copy.
Look at this piece of your code:
ask players [
print ( word " values " TEAM-OWNER)
fd 2
set TEAM-OWNER "red"
]
ask balls [
fd 2
set TEAM-OWNER "black"
]
First, every one of your players moves forward two distance units, then sets the value of TEAM-OWNER to "red". If you have 10 players, then the global variable TEAM-OWNER is being set to red 10 times. Then every one of your balls moves forward two distance units and sets the variable TEAM-OWNER to "black". As long as you have one (or more) balls, then the global variable will be overwritten.
A global variable is used for something that is the same for every turtle in your model.
Related
I'm new to NetLogo and I'm trying to create 2 sub-breeds (denoted by different shapes) within each breed for 2 breeds total (i.e. sharks and fishes). The chunks of code work as expected when ran individually, however, when running both chunks the first sub-breed of the fishes does not seem to initialise in the interface tab. For some reason the initialisation of the shark breed seems to interfere with the initiation of the fishes breed.
Any idea what i'm doing wrong? Code below.
; Create the agents
breed [sharks shark]
breed [fishes fish]
; Create the agents' variables
fishes-own
[
x0
y0
]
globals
[
species
species-f
]
to setup
; Always start with this
clear-all
reset-ticks
; Create sharks and species
create-sharks N-sharks ; N-sharks is a slider
[
set color blue
setxy random-xcor random-ycor
set species N-sharks
ask sharks
[
set shape "default"
set size 2.5
]
ask sharks with [who >= (species * (1 / 2))]
[
set shape "square"
set size 2
]
ask sharks with [who < (species * (1 / 6))]
[
set shape "star"
set size 3
]
] ; End create sharks and species
; Create fishes
create-fishes N-fishes
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
set species-f (N-fishes * species-ratio)
ifelse who <= species-f
[
set shape "sheep"
set size 5
]
[
set shape "cow"
set size 3
]
set color white
] ; End create fishes
end
There seem to be a number of misunderstandings about what code is run when by NetLogo, and what some pieces of code do: when you use create-turtles *number* [*commands*] (or with breeds, as in your case), commands is run once by every turtle being created (first the new turtles are created, then they run the commands in turn).
That means that every time you use ask sharks within the create-sharks' command block, every new shark will ask all other sharks to set shape and size. For example, if you create 100 sharks, instead of setting the shape and size only once you are doing it 10,000 times (100 * 100).
So you need to put all those commands out of their respective create-<breed>'s command blocks; for example:
create-sharks N-sharks [
set color blue
setxy random-xcor random-ycor
]
ask sharks [
set size 2.5
]
ask sharks with [who >= (species * (1 / 2))] [
set shape "square"
set size 2
]
ask sharks with [who < (species * (1 / 6))] [
set shape "star"
set size 3
]
This is still improvable code, but it shows how to achieve exactly the same thing by doing it once and not doing it N-sharks ^ 2 times.
A better way to do it is to bring those commands back inside the create-<breed>'s command block, but letting each agent carry out the task for itself only. That is, without using ask sharks but using ifelse, so that each shark will check its own condition:
create-sharks N-sharks [
set color blue
setxy random-xcor random-ycor
(ifelse
who >= (species * (1 / 2)) ; the first condition
[set shape "square" set size 2]
who < (species * (1 / 6)) ; the second condition
[set shape "star" set size 3]
; else
[set size 2.5])
]
All of this applies to the other breed too.
It is generally said that using who is a sign that the code should be improved, but let's not focus on this now.
You will have noticed that I omitted the part where you set species N-sharks. This is because I think there is another misunderstanding here and it is not clear to me what you wanted to do: species (such as species-f for the other breed) is a global variable. You are basically asking each of the 100 sharks (again, 100 for example) to do the same thing: set the value of a global variable to equal the value of another global variable. In this case, you are asking each shark to set species 100. This seems very unnecessary, especially considering that N-sharks is a slider used for setup and thus probably won't be changed during the simulation (which means that there is probably no need to store the current value of N-sharks as a separate global variable).
Why are you basing the repartition of your sub-breeds on the value of species? What do you want species to represent? Is it correct for it to be a separate variable from N-sharks? If yes, then it is not clear what is its point; if no, then it can be eliminated.
You need to make sure that whatever you wanted to do with N-sharks & species, and with N-fishes and species-f, is better reflected in your code.
Also because I think this is the reason why your first fish sub-breed isn't showing. First of all, what is species-ratio? It is not present in your example, but it seems to be relevant for your question. In any case, if your first fish sub-breed isn't showing, it means that there is no fish who satisfies the condition who <= species-f.
This doesn't surprise me. who numbers are progressive for turtles: if you create 15 sharks and later you create 10 fish...
... the oldest shark will have who = 0
... the youngest shark will have who = 14
... the oldest fish will have who = 15
... the youngest fish will have who = 24
As you can see in this example, there is no fish for which who <= N-fishes (where N-fishes = 10). Let alone that in your case you set species-f (N-fishes * species-ratio) and, although you didn't tell what species-ratio is, I imagine it is a value between 0 and 1 - thus making the value of species-f even smaller.
The problem is that you are using who to determine your fishes. To quote the Netlogo programming guide: "Who numbers are assigned irrespective of breeds. If you already have a frog 0, then the first mouse will be mouse 1, not mouse 0, since the who number 0 is already taken."
As such, you need to take the number of sharks into account for determining the cutoff point for your fish species
set species-f (N-fishes * species-ratio) + N-sharks - 1
One other comment I have on your code is that you use the following structure:
create-sharks N-shark [
ask sharks [...]
]
Every shark executes the entire command block of create-sharks. That means that every shark asks every shark to do something. Thus follows that every shark sets their shape to default N-shark times.
It is much more efficient to use one of the following constructions
create-sharks N-shark [...]
ask sharks [...]
or
create-sharks N-shark [
if <condition> [<reshape-self>]
]
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 am trying to move the turtles one patch to the right if the value of their label is bigger than the previous value, from the previous tick.
How can I do this?
From your comment, your calculation is:
to calculate-value
ask n-of (count turtles * 0.5) turtles
[ set value value + 100
ifelse show-value?
[ set label value ]
[ set label " " ]
]
end
So, you have half the turtles increase their value (which is also their label) by 100 and the other half have no change. Since the turtles that increase their value are the same turtles as the ones that you want to move to the right, you can simply add the instructions for moving inside the code block, something like this:
to calculate-value
ask n-of (count turtles * 0.5) turtles
[ set value value + 100
set heading 90
forward 1
ifelse show-value?
[ set label value ]
[ set label " " ]
]
end
I would like to implement a part of code where agents can get a score when they pick an element from a list generated from a specific turtle.
I set
breed [playersA playerA]
breed [playersB playerB]
breed [balls ball]
playersA-own[
my-list
new_ball
score
]
playersB-own[
my-list
new_ball
score
]
to setup
clear-all
create-playersA 10
ask playerA 0 [ create-links-with other playersA ]
ask playerA 2 [ create-link-with playerA 1 ]
create-playersB 10
ask playerB 0 [ create-links-with other playersB ]
ask playerB 2 [ create-link-with playerA 1 ]
ask playersA[
set my-list []
set score 0
]
ask playersB[
set my-list []
set score 0
]
end
to go
let selected nobody
let team-player nobody
set selected one-of turtles with [breed=playersA or breed=playersB]
ifelse [breed = playersA] of selected[
ask selected [
set size [count link-neighbors] of self
show size
]
create-balls 1[
hide-turtle
]
]
[ ask selected [
set size [count link-neighbors] of self
show size
]
create-balls 1[
hide-turtle
]
]
set team-player link-neighbors with [breed = playersA]
ask team_player [
set my-list lput my-ball my-list
]
end
The above code should select on random turtle and add a new ball to its neighbours list. What I would need is probably a counter that can compute how many balls were shared between players.
Could you please help me to figure out with it?
Thanks
The code you posted has many problems that prevent it from passing error-checking in the editor. Some of these produce surprising error messages that don't even make sense, and they happen because the logic mixes contexts -- that is, some commands make sense for the "observer" level, some require being in a "turtle" context, etc.
I think you are trying to do too much at once, and trying to add a counter to code that already does not work. First you have to fix the code you have and then you can see where to add a counter.
You absolutely must understand how the unique agent id number "who" works. Each turtle has a unique who number assigned, starting with zero. It doesn't matter whether the breed of turtle is playerA or playerB or a ball, it will have a unique number. Once you create your first 10 turtles, of the PlayerA breed, they will have who numbers 0 through 9. Then, when you create the next 10 turtles, of PlayerB breed, they will get assigned who numbers of 10 through 19. If you then create a ball, say, it will have a who number of 20.
So there will never be a PlayerB with a who number of 0 or 1 or 2. Those numbers will already be used by PlayerA. Your setup will crash with the error:
playera 0 is not a PLAYERB error while observer running PLAYERB
called by Command Center
Even with just PlayerA, it is not clear what kind of network you want to build in the setup code. Why would everyone link to player 0, but then also add a single link between player 1 and player 2? Since players only "see" their linked team-mates, only player zero will see everyone else. Other players will have only one or two link-neighbors, so they will never update everyone else's my-lists.
create-playersA 10
ask playerA 0 [ create-links-with other playersA ]
ask playerA 2 [ create-link-with playerA 1 ]
Anyway, I would suggest that you get this much working correctly before trying to add counting.
I don't think you can do that by just looking at the code. You need to get rid of as much complexity as you can, and then use shapes, colors, and numerous print statements to see whether each command is doing what you think it should do. Complex working code almost always evolves from simple working code.
So get rid of PlayersB entirely ( comment out the code ), only create 5 players A, and change the colors and shapes as you process each step to confirm that it is working. The editor lets you use ctrl-; to comment out entire blocks of code, or un-comment them at once, so comment out everything you possibly can while you are getting one step to work, then uncomment the next section, get that to work, etc.
When you finally get everything working, you can comment out all your print statements that you used in development.
Anyway, I refactored your code, added many comment, and added many print statements, and finally got it to run. If you run just setup and look at the view, you will see what I mean about the network. ( I shut off wrapping in the view so the network looks right.)
Here's my revision of your code. It prints out what is in each player's my-list after each step, so you can see at a glance if it is doing what you want, or not. ( It's not.)
I added the who numbers as a label to each player in the view so you can see what I mean.
It produces helpful output like:
let's confirm that the lists have been updated. Here's the my-lists
for playersA [[5 5 5 5 10] [0 0 0 0 0] [0 8 8] [0 0] [0 9]]
Get the setup step to work correctly and generate the network you want before you even try to fix the go section.
breed [playersA playerA]
breed [playersB playerB]
breed [balls ball]
playersA-own[
my-list
new_ball
score
]
playersB-own[
my-list
new_ball
score
]
to setup
clear-all
;; for debugging, only create 3 players and inspect the results to confirm it's working as you intended
;; use labels to see player numbers in the view
create-playersA 5 [ set size 1 set color blue set shape "square" setxy random-xcor random-ycor set label who]
ask playerA 0 [ create-links-with other playersA [set color blue]]
ask playerA 2 [ create-link-with playerA 1 [set color red]]
create-playersB 5 [ set size 2 set color yellow set shape "person" setxy random-xcor random-ycor set label who]
; comment out this code until create-playersA is working properly
; ask playerB 0 [ create-links-with other playersB ]
; ask playerB 2 [ create-link-with playerA 1 ] ;; copy-and-paste error? link with playerB intended?
ask playersA[
set my-list []
set score 0
]
ask playersB[
set my-list []
set score 0
]
reset-ticks
end
to go
let selected nobody
let team-players nobody
let hot-ball nobody
set selected one-of turtles with [
breed = playersA
;; or breed = playersB ;; always select one of playersA for debugging this code
]
print ( word "At point 1, we selected turtle " [who] of selected " with breed " [breed] of selected)
;; we're still in the observer context here
ifelse [breed = playersA] of selected [ ;; by mentioning breed, we shift into a turtle context silently
print ( word " entering the TRUE part of the if-else statement " )
ask selected [
set size [count link-neighbors] of self
print ( word "at point 2 we set selected player's size to " size )
]
create-balls 1 [
set shape "circle" set size 3 set color blue set label who
set hot-ball who
; hide-turtle ;; for debugging show it so you can click on it and inspect it
print ( word "at point 3 we set created a blue hot-ball with who= " hot-ball )
]
;; it seems you want to update the selected turtle's my-ball variable here with a reference to the ball just created??
print " at point 4 we should set selected agent's my-ball to the ball we just made..."
ask selected [
set new_ball hot-ball
]
print (word " Confirming that selected player got the hot-ball " [new_ball] of selected )
;; ask ball hot-ball [ set hidden? true ]
;; this set of code seems to apply only when selected turtle is one of playersA, so it was moved INSIDE that ask-selected code
;; and put inside another ask selected [ ] context
ask selected [
set team-players link-neighbors with [breed = playersA]
print (word "At point 5, For selected player " who ", here is the team-players agent set :" )
print (sort team-players) ;; using "sort" here just to convert an agent set to a list for display
]
print " ------------- about to ask team-players to update their my-lists and change to triangles ---"
ask team-players [
set shape "triangle" set size 3 ;; to see at a glance that everyone was processed
set my-list lput new_ball my-list
print "... updated one my-list"
]
print " let's confirm that the lists have been updated. Here's the my-lists for playersA "
print map [ i -> [my-list] of i ] sort playersA ;; using "sort" to convert agent-set to a list
print (word "At the end of the go step, we have this many balls: " count balls)
]
;; else we should have breed != playersA
[
error " we should only be looking at one of playersA here for testing" ;; for debugging
]
;; tick
end
I have a dynamic number of groups of turtles (slider controlled, groups labeled with the variable group-id) which have an associated turtles-own variable (trait-1), I am attempting to randomly assign a different value to trait-1 for each group of turtles (group-id). At the moment each individual turtle has a randomly assigned trait-1 value which varies both within and among groups, but I want it to be the same for all individuals within each group, and only vary among groups. Any help would be great!
Side note, I am using a grouping variable instead of breeds as I couldn't figure out how to make the number of breeds dynamically controllable via a slider... not sure this is possible?
turtles-own [
group-id ;grouping id, each group represents a species
trait-1 ; a trait to be assigned a score from 1 - 10
]
to setup
clear-all
set-species
end
to set-species
let n_groups num_species ;create n groups of turtles based on slider value (num_species)
foreach n-values n_groups [ ? ] [
create-turtles 3 [ ;create 3 indviduals in each group
set group-id ?
set color (group-id + 19) ; give each group a different color
set trait-1 1 + random 10 ] ;set trait-1 ranging from 1 to 10
]
ask turtles [ set label group-id ] ; show group-id
ask turtles[ ; move turtles out of the center, not really important, just to help see the turtles.
fd trait-1
]
end
Just move where you set it outside of the turtle initialization:
foreach n-values n_groups [ ? ] [
let group-trait 1 + random 10 ;set it here
create-turtles 3 [ ;create 3 indviduals in each group
set group-id ?
set trait-1 group-trait
set color (group-id + 19) ; give each group a different color
;set trait-1 1 + random 10 ] ;don't set it here
]
]