Hello I have the following function
to calc-col [x]
ask x [set pcolor gray]
end
but I want
to calc-col [x y]
ask x y
end
is this possible?
Yes, though how you'd do it is changing between NetLogo 5.x and 6.x (which is currently in beta).
In NetLogo 5.x, you can do this using tasks:
to calc-col [ x y ]
ask x [ run y ]
end
You then call this like so: calc-col some-agent task [ set pcolor grey ]
In NetLogo 6.x, tasks have been replaced by anonymous procedures. You run them in the exact same way (with run or run-result), but you define them using the new -> syntax:
calc-col some-agent [ [] -> set pcolor grey ]
Related
I'm trying to help a student with a NetLogo homework. The gist of the homework is to load images, save the patch values to properties c1 c2 for each patch, set an alpha value 0.0 <= alpha <=1.0 and then set the patches to a linear combination of c1 and c2 under alpha.
This ought to be simple: all I want to do is code (this is pseudocode, I know this doesn't actually work) like:
to combine
ask patches [ set pcolor (c1 * alpha) + (c2 * alpha) ]
end
the problem being that c1,c2 are vectors, alpha is a scalar, and I can't figure out how to do vector multiply and vector addition in NetLogo.
Here's the code to set up a test case:
patches-own [ c1 c2]
to setup
ask patches [ set pcolor one-of [ red green blue] ]
end
to load-image
import-pcolors image
end
to set-one
ask patches [ set c1 pcolor ]
end
to set-two
ask patches [ set c2 pcolor ]
end
to return-c1
ask patches [ set pcolor c1 ]
end
I don't know what your various vectors (or lists really in NetLogo) and other numbers look like. But if the heart of the problem is that you want to multiply a 'vector' and scalar, here is a function that does so:
to-report mult-vec-num [ #vec #num ]
report map [ ii -> ii * #num] #vec
end
The map primitive is essentially an implicit foreach, with the arbitrarily named ii being used as an iterator through the provided list (named #vec) and multiplied by the provided scalar (named #num). Example use case:
show mult-vec-num [ 1 2 3 ] 5
UPDATE:
To add two lists together, again use the map primitive:
let l1 [1 2 3]
let l2 [4 5 6]
show (map + l1 l2)
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.
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.
I want to select all the patches at a randomly-generated distance eps from all turtles in a simulation and reset their color to yellow. This essentially draws a circle of patches around each turtle in the simulation. I have tried a few different options without success. Through perusing this forum I found some code that looks promising but still has some issues (posted here). I appreciate any suggestions for tweaking this code or using something else to solve this problem.
let eps2 eps
foreach [ eps2 ]
[
ask patches with
[
distance myself > eps2 - 0.5 and
distance myself < eps2 + 0.5
]
[
set pcolor yellow
]
]
eps is a turtle variable so using the let command allows me to circumvent using a turtle variable in patch context.
The foreach command does not recognize eps because it is not a constant, is there another command I could use here?
You can use list (see below), but ... why do you want a list? As it stands, there is no need to use a list.
to setup
ca
crt 1
ask turtle 0 [test]
end
to test
let eps2 10
foreach (list eps2 ) ;you can use `list`
[
ask patches with
[
distance myself > eps2 - 0.5 and
distance myself < eps2 + 0.5
]
[
set pcolor yellow
]
]
end
Addendum:
Since you indicate that you do not in fact need that list, you might try something along the lines of the following:
to test2
ca
crt 1
ask encirclingPatches turtle 0 10 1 [set pcolor yellow]
end
to-report encirclingPatches [#t #dist #width]
let _w2 (#width / 2)
report patches with [
distance #t > #dist - _w2
and
distance #t < #dist + _w2
]
end
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
]
]