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>]
]
Related
We have a forest and randomized initial point of the fire set up, but the code fails to "ignite" (a function). Our goal is to have a hex cell aggregated model that can spread fire. Overall we want a forest fire that is more realistic by using hex cell aggregation.
Im positive that there is an issue with the eligibility or ignite function. Any help would be greatly appreciated! :)
CODE:
globals [
initial-trees ;; how many trees (green patches) we started with
burned-trees ;; how many have burned so far
switches ;; a list containing the number of switches that are on ;;[So this is the start of the weird hex cell aggregation approach, if you don't wanna use
eligibles ;; a list of cells which are eligible to be ignited ;; it that's all good, you just gotta delete like every instance of the words eligible,
] ;; switches, and all of the read-switches stuff below and on the interface and get it to run]
;; The "switches" list is used so a cell can quickly check its live
;; neighbors count against the six switches without having to actually
;; inspect the switches one by one. If the user flips a switch,
;; the list will be out of date, which is why we ask the user to
;; press the SETUP or READ-SWITCHES buttons after changing switches.
;; ;;[I figured that I'd include this from hex cell aggregation for easy potential reference]
;; The "eligibles" list is used so that when we are trying to decide
;; what cell will become alive next, we don't have to check every
;; cell. The list contains only those cells we know are eligible.
;; Every time a cell becomes alive, we remove it from the list.
;; We must also check that cell's neighbors to see if they need
;; to be added or removed from the list.
breed [cells cell] ;; used to define cells ;;[From hexagonal model examples]
breed [fires fire] ;; bright red turtles -- the leading edge of the fire ;;[From OG model]
breed [embers ember] ;; turtles gradually fading from red to near black ;;[From OG model]
cells-own [ ;;[All of cells-own is from hexagonal model examples]
hex-neighbors ;; agentset of 6 neighboring cells
live-neighbor-count ;; used to store a count of red neighbors
eligible? ;; used to see if cells are eligible for ignition or not
]
to setup
clear-all ;; clears grid
set-default-shape turtles "hex" ;; sets turtle shape to hexagonal ;;[Make sure to import the hex turtle shape from the library in Tools>"Turtle Shape Editor" first]
;; ask turtles with [(random-float 100) < density] ;; random selection from density
;; [ set color green ] ;; sets patch color to green
ask patches with [(random-float 100) < density] [ ;;[For the density parameter]
sprout-cells 1 [ ;;[For turtle creation]
set color green ;;[Grid color like the OG model]
set eligible? false
if pxcor mod 2 = 0 [ ;; if patch column is even, ;;[For converting the square grid to hexagonal]
set ycor ycor - 0.5 ;; shift it down by 0.5
]
]
]
ask cells [ ;;[Everything from here...]
ifelse pxcor mod 2 = 0 [ ;; setup for hex-neighbor agentsets
set hex-neighbors cells-on patches at-points [[0 1] [ 1 0] [ 1 -1]
[0 -1] [-1 -1] [-1 0]]
][
set hex-neighbors cells-on patches at-points [[0 1] [ 1 1] [ 1 0]
[0 -1] [-1 0] [-1 1]]
]
] ;;[...to here for hex-neighbors]
;; set tree counts
ask one-of turtles with [color = green] [ ;;[This can be moved to the go function and scrapped for a better approach if you want,
set color red] ;; just wanted to demonstrate that a random single hex could be picked to start the fire]
set initial-trees count turtles with [color = green];; counts the number of trees ;;[I felt like keeping counters for both of these but you can always remove/change them]
set burned-trees 0 ;; counts the number of burned trees
reset-ticks
end
to go ;;[Here's truly where all the problems lie haha]
if not any? turtles ;; either fires or embers
[ stop ] ;; ends simulation
ask fires ;; otherwise, continue
[ ask hex-neighbors with [color = green] ;;[I tried a number of approaches here to no avail, there are probably tons of ways to do this]
[ ignite ] ;; burn them
set breed embers ] ;; set them to fading burnt color
fade-embers ;; calls aesthetic function
tick
end
to ignite ;; patch procedure, creates fire ;;[This also is where things kinda ground to a halt for me lol]
set eligible? false ;; changes cell state
set eligibles remove self eligibles ;; removes cell from list
ask hex-neighbors [ ;; checks neighbors
set live-neighbor-count live-neighbor-count + 1 ;; adds to live neighbor count
if live-neighbor-count = 6 [ ;; if six neighbors active
ask patches [ ;; [sprout-fires only
sprout-fires 1 ;; works for patches]
[ set color red ] ;; sets cell color to red
]
]
update-eligibility ;; call for eligibility check
]
set pcolor black ;; sets patch color to black ;;[This needs to be affecting the turtle color but that creates problems I think lol]
set burned-trees burned-trees + 1 ;; adds to count of burned trees
end
to update-eligibility ;; cell procedure
ifelse eligible?
;; case 1: currently eligible
[
if not member? live-neighbor-count switches [ ;; checks if cell is in live count
set eligible? false ;; since not, change cell state
set eligibles remove self eligibles ;; and remove cell from list
]
]
;; case 2: not currently eligible
[
;; the check for hidden? ensures the cell isn't already alive
if hidden? and member? live-neighbor-count switches [ ;; [potential need ;;[This is right where the hex cells aggregation approach became too much for me lol,
set eligible? true ;; for use of hidden] ;; when everything got into hiding cells (I don't think the model should use hide/show)]
;; The order of the list doesn't matter, but in NetLogo
;; (as in Logo and Lisp generally), FPUT is much much ;;[This is directly from the hex cells aggregation example I think]
;; faster than LPUT.
set eligibles fput self eligibles ;; puts cell at start of list
]
]
end
to read-switches ;;[Admittedly I never got around to understanding how this works too well but somehow it's
set switches [] ;; more efficient, definitely might not be necessary though]
if one-neighbor? [ set switches lput 1 switches ]
if two-neighbors? [ set switches lput 2 switches ]
if three-neighbors? [ set switches lput 3 switches ]
if four-neighbors? [ set switches lput 4 switches ]
if five-neighbors? [ set switches lput 5 switches ]
if six-neighbors? [ set switches lput 6 switches ]
ask cells [
set eligible? hidden? and member? live-neighbor-count switches
]
set eligibles [self] of cells with [eligible?]
end
;; achieve fading color effect for the fire as it burns
to fade-embers ;; function for fading color of cells to show death ;;[This would be great to keep from the OG model but if it causes any issues you can delete it]
ask embers
[ set color color - 0.3 ;; make red darker
if color < red - 3.5 ;; are we almost at black?
[ set pcolor color ;;[I think this is where there's a problem of patches versus turtles]
die ] ]
end
We tried to take out the eligibility of ignition since we really don't need it, still won't run :(
We tried to redo the code of 'to go' and 'ignite' still won't budge.
As you transitioned from a patch fire model to hex cells using turtles, in you ignite procedure, should you have cells hatching fires instead of patches sprouting fires?
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 implement a timer for each turtle in Netlogo
so I can take the minimum value, maximum and average time taken for each turtle.
Can anyone help
You haven't said what you actually want timed (or given any code attempt). Any time you need a turtle to remember anything from one tick to the next, you need a variable. The simplest code for a timer is to have a variable that you set to the current value of ticks when the process starts and subtract that start time from the current value of ticks when the process stops. Here is a complete model example:
turtles-own
[ start-time
time-taken
]
to setup
clear-all
create-turtles 20
[ set start-time 2 + random 10
set time-taken -1
]
reset-ticks
end
to go
let movers turtles with [time-taken = -1 and start-time <= ticks]
ask movers
[ set heading random 360
forward 1 + random 3
if random-float 1 < 0.05 [ set time-taken ticks - start-time ]
]
tick
end
And check out the new Time extension if you want your timers to use real time units (seconds, minutes, years...) and have non-integer values.
https://github.com/NetLogo/Time-Extension
Look at primitives such as time:difference-between
For example, you could do this coding that flags the turtle you want to monitor and increments the flag variable when an event occurs. You can then monitor it in the BehaviorSpace and analyses the results output in a csv file. For example, the following codes:
globals [ID]
turtles-own [special-turtle]
to create-turtle
crt 1 [
setxy min-pxcor 0
set heading 90
set special-turtle false
set ID who]
end
to go
;omitted
special-turtles
tick
end
to special-turtles
ask turtles-on patch 0 0 [set ID who]
ask max-one-of turtles [who] [set special-turtle true]
ask turtles with [special-turtle = true][set special-turtle (special-turtle + 1)]
end
I think there is something that none of the previous answers considered: the way you implement your timer depends on how you want to use the measurement.
1 - If you want to read the measurement only after the measurement is completed
The expression "after the measurement is completed" can mean both that you want to read it at some point later during the model, or maybe even just from some model's output.
The approach I'd take in this case is similar to what JenB suggested, but I believe you can put it a bit simpler because here I only use one extra turtle variable (apart from my-variable, that is there only to represent something that you already have in your model):
turtles-own [
my-variable ; This represents something you have in your model, to be used as a condition for the timer
my-timer
]
to setup
clear-all
reset-ticks
create-turtles 10
end
to go
; Here you have your normal code. When you need, just include
; 'start-timer' and 'stop-timer'. For simplicity, let's
; say you want to count how long does each turtle take
; to get from a value of 1 to a value of 5 for my-variable.
; You can just do:
ask turtles [
if (random 10 < 2) [
set my-variable (my-variable + 1)
]
if (my-variable = 1) [
start-timer
]
if (my-variable = 5) [
stop-timer
type "I am turtle " type who type " and it took me " type my-timer print " ticks."
die
]
]
tick
if (not any? turtles) [stop]
end
to start-timer
set my-timer ticks
end
to stop-timer
set my-timer (ticks - my-timer)
end
Note that most of the code is there only to make a full reproducible example, but the actual implementation only consists of my-timer, to start-timer and to stop-timer.
You can take this approach because the hypothesis here is that you will be interested in reading the measurement only after to stop-timer happened.
Otherwise, see point 2.
2 - If you want to be able to read the measurement at any moment during the simulation
In this case, you need to make the timer progress as time progresses (as opposed to point 1, where you could just take the initial and final time, and make the difference between the two).
I guess the easiest way to do this is to conditionally increment the timer every time there is a tick.
Taking the same example as before, it would be something like:
turtles-own [
my-variable ; This represents something you have in your model, to be used as a condition for the timer
timer-active?
my-timer
]
to setup
clear-all
reset-ticks
create-turtles 10 [
set timer-active? FALSE
]
end
to go
ask turtles [
if (random 10 < 2) [
set my-variable (my-variable + 1)
]
if (my-variable = 1) [
set timer-active? TRUE
]
if (my-variable = 5) [
set timer-active? FALSE
]
]
tick
ask turtles with [timer-active?] [
set my-timer (my-timer + 1)
]
if (count turtles with [my-variable < 5] = 0) [stop]
end
This way, you will be able to see at any moment what is the current value of my-timer for each turtle.
I'd need to pick an object in a bag containing 20 elements with attributes c (color) and s (size). Both color and size are numbers (e.g. c= {red = 256, black = 0, ... } = {256, 0, ...}).
As in Python I'd use random.choice in numpy library, I found on the web that the corresponding function in Netlogo is the extension rnd.
Struggling along a possible solution, I did
Edited:
breed[people person]
people-own
[
ball
size
color
bag
]
to setup
create-people 5
[ set color gray
setxy random-xcor random-ycor
]
ask people[
set bag [ ] ; 0 items
]
end
To create the balls:
to create-balls
set color random 300 ; color
set size random-float 5 ; size
let this-ball self
ask one-of people [ ; ask one of people to put the ball created into the bag
set bag fput this-ball bag ; add ball to the bag
]
end
The code below should include the part of drawing:
to draw
ask one-of people [
rnd:weighted-one-of bag [ ] ; I do not know what I'd write in the brackets
]
end
As you can easily see, I've many doubts about how to implement the code.
How can I select one item from the bag depending on its size (or color)?
Can you please help me out with it?
Here is a complete model that creates people and balls as turtle agents and has 30 of the balls get chosen weighted by their size. It then opens an inspect window for the person who has chosen the most balls.
extensions [rnd]
breed [people person]
people-own [ my-balls ]
breed [balls ball]
balls-own [ chosen? ]
to setup
clear-all
create-people 20
[ setxy random-xcor random-ycor
set my-balls (turtle-set nobody)
]
create-balls 50
[ hide-turtle
set size one-of [1 2 3 4 5]
set color one-of [red white blue yellow]
set chosen? false
]
repeat 30 [draw-ball]
inspect max-one-of people [count my-balls]
end
to draw-ball
ask one-of people
[ let bag-of-balls balls with [not chosen?]
let choice rnd:weighted-one-of bag-of-balls [size]
ask choice [set chosen? true]
set my-balls (turtle-set my-balls choice)
]
end
Some things to notice:
There are NO lists in this code. There are situations where you should use lists. Common uses include memory where the order is important (eg you only want to keep track of the last 5 other people seen) or where the same agent can appear multiple times. And the list commands are very powerful. However, unless you need a list then you should use agentsets.
Each person has their own bag called 'my-balls' that contains the balls they select. That is initialised as a turtle-list as part of the setup.
I used a variable called 'chosen?' that is owned by each ball to track whether it is still in the bag for the next person to choose. Then the bag-of-balls is created only as all the balls not yet chosen.
The code for weighted random choice (when choosing from agentsets) simply has the name of the variable holding the weight as the reporter, but you could use some function such as rnd:weighted-one-of bag-of-balls [size ^ 2] if you wanted a more complicated weighting scheme.
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).