If I assign a value to each patch, where most patches will share the same value to that attribute, is it possible to sprout just 1 turtle within that group of patches? Where each group of patches will have only 1 turtle? What would the syntax of that look like?
Doesn't matter which patch of the group gets the turtle, so long as that group of patches only has 1 turtle associated with it.
Sure you can. Just have those patches be part of a temporary group using the let command like this:
let targetedGroup patches with [someValue = true]
Then, just ask a certain number of those patches to do something using n-of like this:
ask n-of 1 targetedGroup [
sprout 1 [
set color blue]]
*A warning: if you ask more patches than there are in the group, you'll get an error. Try to use an ifelse statement to get around that if it is an issue for you.
Related
I have a model where there are multiple animals in a den
patches-own [den-ID]
where the dens are pink and the number of dens is controlled with a slider global var
ask patches with [pcolor = pink] [set den-ID random n-dens]
Now, I want agents that spawn on that patch to set their own parameter "family" to a value equal to the den-ID that they spawn on - therefore having a group of animals that can be traced back to a den site and all share a home range.
I have tried many solutions but cant get anything to work.
basically something like
set family (family = den-id of patch-here)
thanks
The answer: ask turtles [ set family patch-here ]
Down below is how we arrived there
You seem a bit confused in your Netlogo syntax.
= is only used for logical expressions in Netlogo, not for setting variables. For that you use set.
If you want to use of to access variables of another agent, you need to encase the variable in square brackets: [den-id] of patch-here.
The solution you are looking for looks something like the following:
ask turtles [ set family [den-id] of patch-here ]
It can be made even easier. A turtle can directly access the variables of a patch that they are on without needing to name that patch.
ask turtles [ set family den-id ]
I noticed another thing in your code. Nothing in set den-ID random n-dens prevents multiple dens of having the same number. There are numerous ways of doing it, for example with a while loop where you increment the current-ID each time.
set current-ID 1
while [any? patches with [pcolor = pink and den-ID = 0]] [
ask one-of patches with [pcolor = pink and den-ID = 0] [set den-ID current-ID]
set current-ID current-ID + 1
]
You could even opt to forget about den-id and just let the turtles remember their den itself:
ask turtles [ set family patch-here ]
I have N groups of turtles which own the variable group-id (1 to N, N is defined at setup, each group has 25 turtles).
At the beginning each group of turtles spawns on a random patch with variable patch-group-id that matches the turtle group-id, like so:
let i 0
while [ i < n_groups ] [
let x random 100
let y random 100
ask patch x y [ set patch-group-id i set pcolor gray ]
create-turtles 25 [
set group-id i
setxy x y
]
set i i + 1
]
The turtles move around but at a later step in the process I would like them to move back to their ‘home’ patch. Other turtles may also change their group-id and therefore their home patch and I would like them to move there too.
Is there any way to do a comparison along the lines of…
Ask turtles [
Let target one-of patches with [patch-group-id = group-id]
]
And then ask the turtle to move-to or jump to the target?
NetLogo doesn’t like this (‘Min-one-of expected this input to be a number block, but got a true/false block instead’) and I think there are probably other issues too.
patch-group-id is a variable owned by patches and group-id is owned by turtles. So you need to tell NetLogo which group-id the patches are trying to match to. Try this:
ask turtles
[ let target one-of patches with [patch-group-id = [group-id] of myself]
]
Another way to do this is to drop the idea of group-id and simply have each turtle remember its home patch. Conceptually, this implements the idea that a group is entirely defined by its home patch. So your setup would look something like:
turtles-own
[ my-home
]
to setup
clear-all
ask n-of n-groups patches
[ sprout turtles 25
[ set my-home patch-here
]
set pcolor gray
]
end
Then you never need to construct the target, you simply get then to go to their variable my-home.
If you went down this path, you would also need to change the code that uses group-id. For example, you said that sometimes the turtles change their group-id, instead of set group-id [group-id] of ... you would have set my-home [my-home] of ...
I want to have my turtles move back and forth between a central area and their starting location. I have set the central area (patch 0 0, and its neighbouring patches). I have set these turtles to begin from random locations on setup.
Now I need them to move to the central area and be able to remember and return to their respective starting positions. Here is my attempt, but one that is not working.
ask patches
[ set target-patch patch 0 0
ask target-patch
[ set pcolor green
ask neighbors [set pcolor green]
set hold-time 5
]
]
create-turtles 10
[ set shape "car"
set size 1
set color white
setxy random-xcor random-ycor
if (patches != patches with [pcolor = green])
[ set start-position (random-xcor random-ycor)] ;; line with error
]
to go
ask turtles
[ set heading target-patch move-to target-patch
set hold-time hold-time + 5
]
ask turtles
[ if hold-time >= 10
[ set heading start-position move-to start-position]
]
end
There are several problems with your code. I strongly suggest that you code in smaller pieces. That is, add some code and make sure it works before writing the next piece. Making sure it works is not just making it through without error messages, it needs to do what you expect it to do.
On your specific question. The line if (patches != patches with [pcolor = green]) is causing an error. First, patches is the set of all patches, not just a particular patch. So you are (sort of) asking whether the set of all patches is not equal to the set of patches that are green. Is that really what you intended? If so, it is easier to simply ask whether there is any patch that is not green:
if any? patches with [pcolor != green]
or to check whether they are all green and continue if not:
if not all? patches [pcolor = green]
However, since you are asking about moving back and forth to and from the central green patches, I think you really want to have the turtle check whether the patch they happen to be located on is green. This code looks at the patch where the turtle is located (patch-here) and checks whether the color (pcolor) is green:
if [pcolor] of patch-here = green [ ]
However, one of the tricks of NetLogo is that turtles can access the variables of the patch they are on directly. Note that a patch cannot access a turtle's variables because there may be multiple turtles on the patch so the patch doesn't know which turtle you want. But a turtle can only ever be on one patch at once. So you could write:
if pcolor = green [ ]
You also need to rethink this code:
ask patches
[ set target-patch patch 0 0
ask target-patch
[ set pcolor green
ask neighbors [set pcolor green]
set hold-time 5
]
]
This suggests to me that you have misunderstood something very fundamental to NetLogo programming. You need to think from the perspective of an individual agent. Looking at this code, you first do ask turtles, so that is going to run through all the turtles in random order. Let's call them A, then B, then C and so on.
What is each turtle going to do? Everything in the [ ]. So, A sets the value of the global variable named "target-patch" to patch 0 0. Then A asks that patch to turn green, have the 8 surrounding patches to turn green, and to set the variable "hold-time" to the value 5.
So far, so good. But then turtle B does exactly the same thing - it assigns "target-patch", turns it and its neighbors green etc. Then turtle C. If you have 100 turtles, this block of code will run 100 times and do exactly the same thing each time.
I'm working on a land-use model featuring a forested World where turtles (smallholders and companies) have the ability to convert forest into crop-land. I would like to introduce a feature that turtles 'own' the patches they convert and are able to revisit them later to get these patches certified. The main issue is that when turtles move-to crop-land patches to get them certified, they do not only move to those they 'own' but also jump across the world to other turtles' crop-land patches and certify those. I've tried a few different workarounds, but I seem to run into the same two issues eventually:
#1 - error: can't use who in a patch context
I wanted to use the 'who' variable to mark crop-land patches as belonging to the turtle that converted the patch, e.g., turtle 0 goes to the forest, converts it to crop-land and that patch of cropland should be 'owned' by turtle 0, i.e., the patches owned-by variable should be equivalent to the turtle's 'who'. The issue here is that 'who' is a turtles-own variable. So, when I use it in a patch-context it produces an error. For example, ask smallholders [move-to one-of patches with [[owner = who]] --> error.
#2 - can't manage to set a global variable = 'who'
Two, I tried to work around this by using a proxy variable: a globals-variable called 'owner-ID'. I would use set owner-ID who to imprint the turtles individual number to the owner-ID. This seems to work to some extent, namely that the patches' 'owner' variable corresponds to the turtle that converted the patch. It also works when counting how many patches of certified and conventional crop-land turtles own (see set-land-ownership command below). However, when the smallholders-certify-crop-land commands are triggered, turtles don't stick to the patches they own, but 'jump' across the world. When prompting turtles through the command-center ask turtles [print owner-ID] they all return the same owner-ID value. I feel there might be a mistake in my move-to command-line but I just can't find it.
Summary & Question
I want crop-land patches to be 'owned by' the turtles that converted them, and want turtles to move only to the patches they 'own' when certifying crop-land patches, not to patches they don't own. I guess my questions revolve around whether it's possible to somehow use the 'who' variable in a patch-context. And, if not, what a good workaround for the problem could look like.
Relevant code is below (I hope)!
globals [owner-ID]
turtles-own [conventional-land-ownership certified-land-ownership]
patches-own [owned-by owner certified?]
to setup [
ask patches [
set pcolor green ;; green = forest
set certified? "no"
set owner "nobody"
]
]
to go
ask turtles [set-land-ownership]
ask smallholders [check-smallholder-status]
tick
end
to set-land-ownership
ask smallholders [
set owner-ID who
set conventional-land-ownership count patches with [owner = owner-ID and certified? = "no"]
set certified-land-ownership count patches with [owner = owner-ID and certified? = "yes"]
]
end
to check-smallholder-status
if wealth >= 0 and (conventional-land-ownership + certified-land-ownership) < SH_max-land-ownership [
smallholders-choose-activity
]
if wealth < 0 [
set color red
set shape "cow skull"
]
if (conventional-land-ownership + certified-land-ownership) >= SH_max-land-ownership [
set color orange + 2
]
end
;; smallholders-choose-activities is a reporter-based command where turtles choose the most economical option available. One of the outcomes is: smallholders-certify-crop-land
to smallholders-certify-crop-land
let available-patch max-one-of patches with [owner = owner-ID and certified? = "no"] [count neighbors with [certified? = "yes"]]
ifelse not any? turtles-on available-patch [
move-to available-patch
]
[]
set wealth wealth - smallholder-certification-cost
set pcolor brown + 1
set certified? "yes"
end
Your first approach is definitely the way to go and could be fixed with one small adjustment.
ask smallholders [move-to one-of patches with [owner = who]]
should be
ask smallholders [move-to one-of patches with [owner = [who] of myself]]
Within the block after with, variables are in the context of patches, but myself refers to the agent that asked the patches to check their owner, in this case, each smallholder. The global variable owner-ID is then unnecessary. If you carry this through the rest of the code, your second problem may solve itself.
BUT, in general it is best not to use who numbers at all, but rather refer to the agent directly. (You have actually taken that approach implicitly when you initialize owner to nobody, which is "no agent".) I don't see where you ask a patch to set its owner, but if a smallholder is on a patch, the smallholder would
ask patch-here [set owner myself]
and the line above would now read
ask smallholders [move-to one-of patches with [owner = myself]]
The NetLogo gurus suggest that we use who numbers only when there is no other approach.
I'd like to have patches count the number of turtles that have stood on them. What would be ideal is a event such as:
if turtle-lands-on-me [add one to count]
because a turtles could leave and come back and be counted twice (which is what I want) and it would avoid counting turtles who stand still twice or more (which I don't want). Is there any way to achieve this?
Thank you!
What you need is a variable for each patch (I am calling it 'landed' below). The following code assumes you want to know about the patch it lands on each time step, but ignores the ones it passes over. It also updates the counts only where the turtle changes the patch, as requested, and labels the patch with the count.
patches-own [landed]
to setup
create-turtles 20
[ setxy random-xcor random-ycor
]
end
to go
ask turtles
[ let old-patch patch-here
set heading random 360
forward one-of [0 0.5 1 3]
if old-patch != patch-here
[ ask patch-here
[ set landed landed + 1
]
]
]
ask patches [set plabel landed]
end
The problem is that a turtle can pass over multiple patches during one time step. You can see this in the example model for those turtles that move 3. If you also want them, you will need to do something like the 'Line of Sight' model in the NetLogo models library.