I´m new to NetLogo. Quite new to programming in general too. I read a lot of helpful things here. Now i hit rock bottom with my knowledge and decided to ask my first question ever. No matter how stupid i might sound:
I try to make some turtles move and avoid certain patches in NetLogo. I Tryed to archive this with the following nested ifelse:
loop [
ifelse any? Movers with [steps > 0]
[
ask Movers with [steps > 0]
[
ifelse patch-ahead 1 is-Patch? [
ifelse not any? turtles-on patch-ahead 1 [
ifelse [pcolor] of patch-ahead 1 != white [
ifelse [pcolor] of patch-ahead 1 != brown [
fd 1 set steps steps - 1][turnTurtle]
]
[turnTurtle]
]
[turnTurtle]
]
[turnTurtle]
]
]
[stop]
]
The loop should run until every Mover has moved once. Thats what I keep track of using the "steps" variable. If any condition is false it will call a procedure called "turnTurtle". The turned turtles will try to move during the next run of the loop or turn again.
I get an "Expected keyword" error when i try to run the code. Why?
ProQuestion: Is there a better way to check patches and turn turtles? This very nested setup might be a poor choice?
I get an "Expected keyword" error when i try to run the code. Why?
I don't get that error from the code snippet you posted. (In general you should try to post simplified but "complete" examples of your code that someone can paste into NetLogo and play with. Very often, just trying to create such an example will help you solve your problem.)
What I do get is the "Expected a constant" compilation error because patch-ahead 1 is-Patch? is inverted. It should be:
is-patch? patch-ahead 1
Maybe that was the source of your problem?
Is there a better way to check patches and turn turtles? This very nested setup might be a poor choice?
As you have correctly seen, deeply nested code is undesirable and can usually be avoided. In your case, that could be achieved by combining your conditions in a single expression using and:
ifelse is-patch? patch-ahead 1
and not any? turtles-on patch-ahead 1
and [ pcolor ] of patch-ahead 1 != white
and [ pcolor ] of patch-ahead 1 != brown
[
fd 1
set steps steps - 1
] [ turnTurtle ]
Some more remarks:
Instead of checking for != white and != brown in two separate expressions, you can combine them using member?:
[ not member? pcolor [ white brown ] ] of patch-ahead 1
Instead of combining loop with an if expression and a stop command, you could just use while:
while [ any? movers with [ steps > 0 ] ] [
ask movers with [ steps > 0 ] [
; rest of your code here
]
]
Finally, I don't think you need it here, but for complicated control flow code, you can use the cf extension that adds "switch" like statements to NetLogo.
Related
I have a model which is meant to interact with an api using web extension. So after each move, I will send my current location, heading to the API.
This is the code I am using:
to follow-path
let choice web:make-request "http://127.0.0.1:8000/predict_get" "GET" [] []
(ifelse
choice = 0 [
forward 1
]
choice = 1 [
right 90
]
choice = 2 [
left 90
]
; elsecommands
[
stop
])
let data web:make-request "http://127.0.0.1:8000/netlogo" "POST" [["data" (list xcor ycor heading)]] []
end
to move-agent
ask turtle (count turtles - 1) [follow-path]
end
Then when I checked, it said "Expected a literal value" at the list part. How can I post the list of data to the api correctly ?
I think you are struggling with the [[ ]] notation in NetLogo. This notation allows creating lists with only actual values but doesn't work with variables.
I recommend you to test the following explanation in the Command Center for an illustration.
Creating lists with just values:
The following code: show [ [ "name" "john"] ["surname" "doe"] ]
Would print the following outcome: [["name" "john"] ["surname" "doe"]]
This way, you can create lists with literal values. However, you cannot use variables instead of literal values. For example, the following code would give the same error you are seeing in your code:
let name "john"
let surname "doe"
show [ [ "name" name] ["surname" surname] ]
Creating lists with variables
You should use the list primitive in a nested manner to create your arguments for the web:make-request command to solve your problam.
Here's an example usage:
let name "john"
let surname "doe"
show (list (list "name" name) (list "surname" surname))
which would print:
[["name" "john"] ["surname" "doe"]]
How can I update the values in a list for the indices that are equal to everyone in the selected group agents?:
persons-own [
grouped
flockmates
]
to create-trustConnection
set nrPersons count persons
set vector []
repeat nrPersons [set vector 0.4 vector]
end
to updateVector
let alonePersons (count persons with [grouped = false])
set flockmates n-of (random alonePersons) persons
ask flockmates [
foreach vector [ i ->
set item i vector 0.6
]
]
end
You can use the replace-item reporter to update an item in a list.
Let this [ 1 2 3 4 ]
Let new-list replace-item 3 this “a”
Print new-list
Note that this does not affect the original list: it reports a new list with the specified item replaced with the given value.
Changing an item in a list of lists of similar.. but again, the entire list
Of lists is created anew.
But maybe use links?
In the case of using a list for a turtle to track its relationship with other turtles, or of groups, links are useful, and simplify managing those relationships, and enable things that are very difficult with lists.
LINKS are just another kind of agent, specifically for recording a relationship between two turtles. They have a pair of built-in variables, end1 and end2 that refer to those two turtles. The -own variables of the link can be used to record properties of the relationship. Like “anniversary” or “affinity” or whatever! Links can be directional, so the “intimacy” value can be different depending on the “direction” of the relationship.
Directed-link-breed [ relationships relationship]
Relationships-own [ intimacy ]
to setup-all-relationships
Ask protestors
[ setup-relationship ]
End
To setup-relationship
;; link with everyone else
Create-relationships-to other protestor
[ set intimacy .5 ]
End
The relationship between two turtles can be obtained in several ways.
(Link (this turtle) (that turtle))
Refers to the link from this turtle to that turtle.
Out-Link-neighbors is used to get the set of all turtles linked to from this turtle.
You can also use turtles to represent groups, and links to record membership in that group.
In that case, the members of the group are link-neighbors of the group.
While perhaps not a feature of your model, this opens up the possibility of multiple groups and of agents being members of more than one group, or of tracking things like former members.
Here is a complete, minimal reproducible example of what I think you are looking for. Note that one can just paste it into NetLogo and it compiles and runs. I've made some assumptions here - in particular that intimacy is a protesters-own variable, which it was not in the code you provided, but which your textual description seemed to indicate. Again, using who numbers is not a good idea, but that is a different question and answer. If I have time tomorrow, I might be able to provide you with an example of how one might use agentsets, but if intimacy values can vary from agent-pair to agent-pair, then links is really the way to go.
breed [protesters protester]
globals [numberOfProtesters intimacyVector]
protesters-own [
intimacy
partOfGroup ;initially set to false for all agents
myNRelatedProtesters
]
to setup
clear-all
create-protesters 10
create-intimacyRelationship
reset-ticks
end
to create-intimacyRelationship
ask protesters [
set numberOfProtesters count protesters
set intimacy []
repeat numberOfProtesters [set intimacy lput 0.2 intimacy]
set partOfGroup false
]
end
to updateIntimacy
let nrUngroupedProtesters (count protesters with [partOfGroup = false])
let NRelatedProtesters n-of (random nrUngroupedProtesters) protesters
ask NRelatedProtesters [
foreach ([who] of NRelatedProtesters) [ i -> set intimacy replace-item i intimacy 0.8 ]
set partOfGroup true
]
ask NRelatedProtesters [ show intimacy ]
end
to go
let ProportionProtestersInSubgroup (count protesters with [partOfGroup = true])/ numberOfProtesters
ifelse ((count protesters with [partOfGroup = false])/
numberOfProtesters) > ProportionProtestersInSubgroup
[
updateIntimacy
]
[
stop
]
tick
end
Hope this gets you started.
I have a problem with a NetLogo-list (V. 6.0.2) and the member? command, somehow not doing what I want it to do.
Each turtle builds its list "aware-of-who":
ask turtles [
foreach cheater-list [ x ->
if random-float 100 < 90
[set aware-of-who lput ([who] of x ) aware-of-who]
]
It builds the lists of who-numbers successfully for the turtles.
Then I ask turtles to look for those neighbors, that have their who-number in their "aware-of-who" list (i.a. are "aware of them"), with this code:
let punishers (turtles-on neighbors) with
[ member? ([who] of myself) ( [aware-of-who] of self) = true]
It does not seem to report true, even if from all I can tell it should (the respective who numbers do appear in their lists). The code also does report true if I ask for (turtles-on neighbors) with [ empty? aware-of-who = false].
Any ideas what's wrong here?
Thanx!!
It seems like a case of mixing up self and myself. In the following code:
let punishers (turtles-on neighbors) with
[ member? ([who] of myself) ( [aware-of-who] of self) = true]
The code between the square brackets is passed to the with reporter and runs in the context of the calling turtle's neighbors. So within the reporter, self is the neighbor and myself is the calling turtle. You have it the other way around.
That being said... don't do it this way! And by this, I mean: don't use lists of who numbers. It is almost never necessary to use who numbers in NetLogo. Whenever you think you need who numbers for something, come ask a question here: someone will most likely show you a better way to do it.
The way around who numbers is usually to store references to turtles directly, either in a list or an agentset. It seems like you already know how that works, since cheater-list is apparently a list of turtles.
To construct you list of cheaters that a turtle is aware of, you could just use filter:
let known-cheaters filter [ random-float 100 < 90 ] cheaters
Finding your punishers then becomes a bit nicer:
let punishers (turtles-on neighbors) with [
member? self [ known-cheaters ] of myself
]
Also note that you should almost never write = true or = false. If something is true or false, you can use it directly in an expression (with a not in front if you're interested in the case where it's false). For example, you can write:
turtles with [ not member? self cheaters ]
instead of:
turtles with [ member? self cheaters = false ]
This is relevant to the previous question just asked.
How can I convert list(which representing turtles) to a agentset?
For example, I want to make
agentset which contains 4 elements [turtle 0 turtle 3 turtle 4 turtle 7]
out of list ["turtle 0" "turtle 3" "turtle 4" "turtle 7"]
I've tried "foreach" before.
Thank you in advance~!!
I am not sure why you would need to work with a list like
["turtle 0" "turtle 3" "turtle 4" "turtle 7"]
in the first place. Storing references to agents as anything other than direct references to the agents is usually not a good idea.
That being said, you can convert such a string to an agentset with:
turtle-set map runresult ["turtle 0" "turtle 3" "turtle 4" "turtle 7"]
If any of those turtles don't exist, they will just be excluded from the resulting agentset.
Still, the whole thing strikes me as somewhat ill advised. If you tell us more about what you're trying to accomplish, maybe we could suggest a better approach altogether.
Are you constrained for some reason to working with a list of strings? If not, but you still want a list, I'd recommend just building your lists to contain agents in the first place. If you're writing this to a file later, it will be converted to string anyway. Internally it's much easier to work with the agents directly.
To make a list of agents based on a list of numbers:
globals [ turtle-list num-list]
to setup
ca
reset-ticks
crt 3
set num-list [ 0 1 2 ]
set turtle-list map [ i -> turtle i ] num-list
print turtle-list
end
Note that if the list contains a who number for a non-existent turtle, you will get a nobody in your list.
Nevermind all this, just do what #NicolasPayette says.
Then you *can* use `foreach` to easily build your agentset for your `turtle-list`:
foreach turtle-list [
t ->
set turtle-agentset (turtle-set turtle-agentset t )
]
However, if your end goal is an agentset and you don't need a list, you can skip a step and just build the agentset directly:
to setup
ca
reset-ticks
crt 3
set num-list [ 0 1 2 ]
set turtle-agentset nobody
foreach num-list [
n ->
set turtle-agentset (turtle-set turtle-agentset turtle n )
]
print turtle-agentset
end
I am trying to find a solution to do what `count neighbors with [any? turtles-here = true]' does, but instead of counting the black patches among the 8 neighboring patches to all patches that have the same y coordinate as the asking turtle.
Is there a way to implement a whole range of coordinates and ask for the number of patches with turtles within these coordinates?
You can definitely do this!
count patches with [ pycor = [ ycor ] of myself and any? turtles-here ]
myself refers to the agent that is doing the asking of other agents. In this case, it refers to the turtle that's counting the patches. Here, the turtle is asking the patches to execute the code in the reporter block. In order to get the ycor of the turtle in the context of the reporter block, you do [ ycor ] of myself.
Also, as an aside, note that the = true is unnecessary. any? turtles-here is already returning true or false, which is what you want the reporter block to return anyway!