Can I modify NetLogo commands with variables? - netlogo

To start with example:
to make-new-car [freq x y head ]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-cars 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
yet I want to have more breeds for cars - not just one car breed. I also want to keep it simple and insted of doing this(first function is the same as one above):
to make-new-car [freq x y head ]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-cars 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
to make-new-carSE [freq x y head ]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-carsSE 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
and being redundant by repeating the same procedure just with different breed name I wan to do something like this(put breed-name as an argument and use it with create- command):
to make-new-car [freq x y head breed-name]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-breed-name 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
However Netlogo is complaining that create-breed-name is not defined. Any ideas ?

Easiest way to do this is to do create-turtles then set breed breed-name. Here's an example.
breed [ testers tester ]
to make-turtles [ breed-name ]
create-turtles 1 [ set breed breed-name ]
end
to setup
make-turtles testers
end
You can also do probably do something with run after constructing an appropriate string, but I think the above is more straightforward.

Go with Jen's answer. It is, by far, the most straightforward way to accomplish what you need.
Just for the sake of it, however, here is one way to do it with run:
to make-new-car [freq x y head breed-name]
let commands [ ->
setxy x y
set heading head
set color one-of base-colors
]
if (random-float 100 < freq) and not any? turtles-on patch x y [
run (word "create-" breed-name " 1 [ run commands ]")
]
end
Notice that I put the commands that should be executed by the newly created turtle inside an anonymous procedure (using NetLogo 6.0.1 syntax) and then run that inside the string passed to run. You could also put everything in one big string, but then you would loose compiler checking, syntax highlighting, speed, etc.
But, anyway, don't do any of this. Use Jen's method.

Related

calculate steps of turtles among neighbors

In the world, the two types of agents, individuals and messages, are randomly positioned in the two-dimensional attitudinal space.
If an individual believes the messages, he or she creates links with the messages.
Then, an individual adjusts his or her attitudinal position based on the calculation of distances from oneself to the messages.
Here, I have a problem.
I would like to make an individual move twice more when exposed to a message with a high value than when exposed to one with a low value.
But what I can do right now is just averaging the distance among the messages.
Here's what I've done so far
breed [individuals individual]
breed [messages message]
messages-own [value]
undirected-link-breed [messagelinks messagelink]
to setup
ca
create-individuals 100 [initiate-individuals]
reset-ticks
end
to go
new-messages
end
to initiate-messages
ifelse random-float 1 < value-p [ set value "H" ] [set value "L"]
end
to initiate-individuals
setxy random-xcor random-ycor
end
to new-messages
create-messages 30 [
initiate-messages
ask individuals [
integrate-messages myself
]
]
end
to integrate-messages [newmessages]
if random-float 1 < 0.3
[create-messagelink-with newmessages
setxy mean [xcor] of messagelink-neighbors mean [ycor] of messagelink-neighbors]
end
I am making the assumption that integrate-messages is intended to handle a set of messages, even though when a receiver executes it in your code it is only the newly created message itself, not all newly created messages. There are likely several ways to handle the problem of giving "H" messages more influence than "L" messages, but perhaps the most straightforward to simply to use a weighted average of the messages' xcors and ycors. I've written a short model that does that in integrate-messages.
breed [messages message]
breed [receivers receiver]
undirected-link-breed [messagelinks messagelink]
messages-own [value]
to setup
clear-all
create-receivers 1 [
setxy random-xcor random-ycor
set color green
]
create-messages 5 [
setxy random-xcor random-ycor
set value ifelse-value (random-float 1 < 0.5) ["H"] ["L"]
set color blue
set label value
]
reset-ticks
end
to go
ask one-of receivers [
integrate-messages n-of 3 messages
]
end
to integrate-messages [newmessages]
;to indicate which messages are being received.
ask newmessages [set color red ]
create-messagelinks-with newmessages [set color red]
;now calculate the weighted position relative to ALL linked messages.
let mssgs [other-end] of my-messagelinks
let wghts map [x -> ifelse-value ([value] of x = "H") [2] [1]] mssgs
let xc sum (map [[m w] -> w * [xcor] of m ] mssgs wghts)
let yc sum (map [[m w] -> w * [ycor] of m ] mssgs wghts)
set xcor xc / sum wghts
set ycor yc / sum wghts
;to show where the receiver ends up.
set color red
end

Netlogo Help - neighbors function

I am a beginner with Netlogo and I am attempting to make a simple model so that when an individual is created, it must be placed in a patch that is neighboring the parent (in one of the 8 spaces). I think I need to use the one-of neighbours command and sprout but I am not sure how to do this.
Currently, I have something this in my code:
to birth-death
set npop count turtles
ask turtles [
if random-float 1.0 < dt * r [
set i random-pxcor
set j random-pycor
ask patch i j [set lpop count turtles-here]
if lpop = 0 [
hatch 1 [
set color green
set xcor i
set ycor j
]
]
]
if random-float 1.0 < dt [ die ]
]
end
Which sets a turtle at a random location, but I am not sure what to write so that when an individual is born it knows to select one of the eight neighbors of the parent site to add a new turtle.
You are close. When a turtle is born (created with the hatch command) it is created at the same patch as the parent. So you just need to move it to one of the neighbouring patches from where it already is. Instead of:
hatch 1
[ set color green
set xcor i
set ycor j
]
Use:
hatch 1
[ set color green
move-to one-of neighbors
]

Divide regions accordingly to physical features

I'm working on a smaller project and got stuck on an issue, I'm not really sure if it's possible to solve it in NetLogo but I want to give StackOverflow a go!
I got a model that divides the world into different parts and randomly add physical features (such as rivers). If a feature goes through the whole region, I want it to separate the region and make into two regions. As an example, in the picture below, I want to separate the purple region into two unique regions accordingly to the physical feature (black).
The code I used to generate the picture above, can be found below.
to setup
ca
;Setting world.
resize-world 0 19 0 19
;Creating regions.
let x 5
let y 5
let col 45
while [y <= max-pycor + 1][
while [x <= max-pxcor + 1 ][
ask patches with [pxcor < x and pxcor >= x - 5 and pycor < y and pycor >= y - 5][
set pcolor col
]
set x x + 5
set col col + 10
]
set x 5
set y y + 5
]
;Generating physical features.
ask n-of 5 patches[ sprout 1[
set pcolor black]
]
let i 0
while [ i < (max-pycor * 2 )][
ask turtles [
fd 1
set pcolor black
ifelse (random 20 <= 1)
[
rt one-of [-90 0 90]
forward 1
]
[
fd 1
set pcolor black
fd 1
set pcolor black
]
set pcolor black
set i i + 1]
]
ask turtles [die]
end
My strategy for handling this is to realize that all we really need to do is "flood" a patch out by color and tag all the found adjacent patches, then repeat for any un-tagged, non-black patches until they are all done.
NetLogo does not have a "flood" command to get all patches adjacent to a patch meeting a criteria, so we make a special reporter of our own to handle it, patches-adjacent. Then it's just easy to ask those patches-adjacent to set their region to the currently chosen region.
I don't love this code, it's a little finicky and would be prone to infinite loops if tweaked incorrectly, but it should work. I bet there is a cleaner way to do this that I'm not thinking of at the moment.
; add a variable to track the different regions
; the default value will be `0` for each patch when `clear-all` is called
patches-own [ region ]
to set-regions
let current-region 1
; only act on non-black patches that haven't yet been assigned a region
let untagged patches with [ region = 0 and pcolor != black ]
while [any? untagged] [
ask one-of untagged [
ask patches-adjacent [
set region current-region
]
]
; update the region and the untagged patches we have left to process
set current-region current-region + 1
set untagged patches with [ region = 0 and pcolor != black ]
]
; this is just to get a view of the regions to quickly see if our code worked, it can be removed
ask patches [ set plabel region ]
end
to-report patches-adjacent
report patches-adjacent-ex (patch-set self) pcolor
end
to-report patches-adjacent-ex [found pc]
let newly-found neighbors4 with [ (not member? self found) and pcolor = pc and region = 0 and pcolor != black ]
set found (patch-set found newly-found)
ask newly-found [
; use recursion to find the patches adjacent to each newly-found one
; relying on updating the `found` agentset as we go to avoid duplicates
; or looping forwarder
set found (patches-adjacent-ex found pc)
]
report found
end
I solved this by using the Patch Clusters model that can be found in the NetLogo model library.

NetLogo - turtle to go to the closest concentration of turtles

I would like a turtle to go to the closest patches with most turtles if a threshold of a given variable is met for 5 ticks.
My code is:
to move
let count-tick 5
if var >= 9.5 [
set count-tick count-tick - 1
if count-tick = 0 [
ask turtle [
let nearest-group min-one-of (patches with [sum turtles >= 3] in-radius 3 ) [ distance myself ]
move-to nearest-group ;; go to the biggest crowd near you
ask turtle [ ;; once there do the following
set shape "star"
set color red
]
]
]
]
end
The issue I have is that a) I am unsure how to say the patch with >= 3 turtles closest to you at the given range of 3 (attempted code above) and b) how to say once there, change your shape.
Revised to keep a permanent variable to track whether the variable is high enough 5 times in a row.
turtles-own
[ count-tick
]
; wherever you create the turtles, you need to `set count-tick 5`
to move
ifelse var >= 9.5
[ set count-tick count-tick - 1 ]
[ set count-tick 5 ]
if count-tick = 0
[ let nearest-group min-one-of (patches with [count turtles >= 3] in-radius 3 ) [ distance myself ]
move-to nearest-group ;; go to the biggest crowd near you
set shape "star"
set color red
]
end
First, you are already within an ask turtles code block from the procedure calling this move procedure. So you don't need the additional ask turtles. Look up ask in the NetLogo Dictionary, it iterates through the turtles, running all the code for each turtle in turn.
Second, you need count turtles rather than sum turtles as sum is to add up values.
Note that there is no error checking in this, you may have problems if there are no patches within radius of 3 that have at least 3 turtles.

How can I use a variable that is defined in a turtle context in a patch context?

How can I use a variable that is defined in a turtle context in a patch context ?
This is my code (I simplified it) :
turtles-own [a]
patches-own [b]
to add-turtles
create-turtles 2 [ set shape "turtle" set color gray set size 2 ]
ask turtles [
setxy random-xcor random-ycor
set a random 10 ]
end
to function
let beta0 0.4
let beta1 0.9
ask turtles [
ask patches in-radius 8 [
set pcolor red
set b beta0 + beta1 + a ] ]
end
In this code, each of two turtles has a value of "a". I would like that patches in a radius of 8 around the first turtle obtain the value of "a" specific at this turtle + beta0 + beta1. It's the same thing for the second turtle.
I have a error message : you can't use A in a patch context, because A is turtle-only
Try with myself : [a] of myself
Now that I've seen Marine's answer, and after your updates, this is making more sense to me now.
Marine suggests using [a] of myself. That works, and is probably what I would suggest too. But here's another option, using let:
ask turtles [
let center-a a
ask patches in-radius 8 [
set b beta0 + beta1 + center-a
]
]