In NetLogo, is 'with' a form of asking? - netlogo

With the following code:
breed [girls girl] ;pink
breed [boys boy] ;green
to go
clear-all
create-girls 10 [move-to one-of patches]
create-boys 10 [move-to one-of patches]
end
I was expecting the next line to have girls show the count of boys of the same colour i.e. "show the count of boys with colour equals colour of me":
ask girls [show count boys with [color = [color] of self]]
But instead this counts every boy. This is the code that does the job:
ask girls [show count boys with [color = [color] of myself]]
Why does self (me) refer to the boys and myself (the turtle that asked me) refer to the girls? Is the keyword 'with' asking the boys to do something and that's what switches it over?

Short answer: yes.
The ask and with primitives both work with a "code block" (the part delimited by [ and ]) that operate in the context of a particular agent. Inside that block, self refers to the current agent (the one from the block's context) and myself to the "outer" agent (the one in the context of which with or ask was called).
The main difference between ask and with is that ask takes a command block (one that most likely does something) and with takes a reporter block (one that just returns a value).
Note that with is not the only primitive using reporter blocks: of is another common case. Using a variation on your previous example:
ask girls [
show [color = [color] of myself] of boys
]
would have each girl show a list of boolean values (one value for each boy in the list, in random order): true if the boy was the same color as the girl, false otherwise.

Related

getting "ASK expected input to be an agent or agentset but got the list [green-players" error in netlogo

This is the code of a 2 player game that I manipulated
o play-the-game
if (any-friends-nearby?) [gain-energy]
if (any-opponents-nearby?) [fight-opponent]
end
to-report any-friends-nearby?
report (any? (turtles-on neighbors4) with [breed = [breed] of myself])
end
to-report any-opponents-nearby?
report (any? (turtles-on neighbors4) with [breed != [breed] of myself])
end
to gain-energy
set similar-nearby count ( turtles-on neighbors4 )
with
[color = [color] of myself]
set total-nearby count (turtles-on neighbors)
;
;
if (similar-nearby >= total-nearby - similar-nearby)
[set energy energy + 5]
end
to fight-opponent
let my-breed [breed] of green-players
let my-color [color] of green-players
let opponent-breed [breed] of red-players
;
;;
ask my-breed
[check-random-winner]
end
to check-random-winner
let pick random-float 2
let winner nobody
ask turtles
[if winner = nobody
[ ifelse size > pick
[set winner self ]
[set pick pick - size] ] ]
end
to change-opponent
ask red-players
[ set breed green-players
set color green ]
end
Sorry if it's a bit long but when I setup up and then press go "ASK expected input to be an agent or agentset but got the list [green-players...]"
How can I fix this?
Also I'm very new to Netlogo and StackOverflow, apologies if I haven't asked my question properly.
The error message tells you that you are passing a list (more specifically, a list of breeds) to ask, when it comes to ask my-breed.
This is because the my-breed local variable is determined by
let my-breed [breed] of green-players
Let's see what we have there:
breed is a turtles-own variable: it holds the turtle's breed, and being an agents' variable can be used as a reported in the of construct (see below).
of is a reporter: it takes a reporter (normally an agents' variable) on its left (in your case: breed) and either an agent or an agentset on its right (in your case: green-players). What of reports (i.e. what it outputs) is...
... a single value if there is an agent on the right.
... a list of values if there is an agentset on the right*.
*Think about it: if I ask the color of your eyes (you are a single person, i.e. a single agent), you will tell me a single color. But if I ask the color of your friends' eyes (your friends are a group of people, i.e. an agentset), the only way for you to answer my question is to tell me a list of colors.
green-players is an agentset: all of the agents whose breed is green-players (note that for NetLogo green-players is an agentset even if it contains 1 or 0 agents).
From this, we can see that in this case of reports a list of breeds, because it reports the breed of every agent that is part of green-players, hence it will report the list [green-players green-players green-players green-players ... ] which is as long as the number of green-players in the model. You can verify this by clicking setup and then running [breed] of green-players in the Command Center.
This is a list of breeds (which can also be seen as a list of agentsets), which is not an agent or an agentset (which are the only possible targets of ask).
((note that the exact same thing happens with let my-color [color] of green-players and let opponent-breed [breed] of red-players))
So, how do you construct an agentset based on a variable? The most common way to do it is by using with (read here why).
But how can you fix your code? I don't know because I don't understand what you want to achieve.
I am not sure how you would want to use it in the code you posted, as I'm not even sure you need to use ask in fight-opponent (let alone ask an agentset).
Your fight-opponent procedure is such that, apart from the problem we just discussed, the "my-" things (i.e. my-breed and my-color) always refer to the green players while opponent-breed always refers to the red players - even if fight-opponent is run by a red player! And also, it is not clear what you want to achieve with the check-random-winner procedure and if you want this procedure to be ran by an entire breed. These things make it quite confusing to understand how you could want to fix the fight-opponent procedure.
For example: who do you want to run the check-random-winner command?
A combination of two things would be beneficial: develop your model one step at a time and make sure that every new little piece of code does exactly what you expect it to do; also, when you ask for how to fix something it is useful that you explain what you want your code to do. By doing these two things I believe it will be a lot easier to answer your questions

NetLogo : getting turtles to direct-link if a condition is true

I'm trying to implement YOYO leader election algorithm in netlogo
first step in this algorithm is to orient links ( direct link )from the minimum to the maximumbut between neighbors only !
I tried the command
[`ask turtles with [ [ who ] of self < [who] of one-of link-neighbors ]
create-direct-to turtle [who] of one-of link-neighbors ]`
this creates direct link from min to max ( neighbors ) but also creates a direct link from max to min ( neighbors )
and I don't know what's wrong :(
here's a screenshot , if you notice theres' a direct link from 0 to 2 and also from 2 to 0 and my goal is to have only from 0 to 2
Your problem is that every time you do one-of, it randomly selects. So you test against a random link-neighbor in the first line, find it's true and then randomly select a link-neighbor to connect to.
[ ask turtles with [ [ who ] of self < [who] of one-of link-neighbors ]
create-direct-to turtle [who] of one-of link-neighbors
]
More generally, this seems an odd way to achieve your goal. To start with, link-neighbors are the turtles that the turtle is already linked to. link is the generic name for all link breeds (I think you have created a breed called direct-link).
I am not entirely clear what you mean by minimum and maximum since your code is just from smaller to larger who value, regardless of what other who values are available. If you want to create a link from every turtle to every turtle with a higher who value, here is some code:
ask turtles
[ let targets turtles with [who > [who] of myself]
create-links-to targets
]
In general, it is bad practice to use who in NetLogo code. who is a completely arbitrary identifier that simply tracks the order that turtles are created. If you have turtles that die, then your code may crash because it is referring to a turtle that no longer exists. Or perhaps at some point you will have two breeds of turtles - who doesn't care if your turtle is a person or a dog or a factory or...
This may be one of the very few exceptions, but you might want to think about what you are intending who to mean. For example, as this is a leadership model, perhaps you could have a variable called 'charisma' and all the links are from turtles with lower values of charisma to higher values of charisma.

Error: You can't use % in a turtle context, because % is observer only

I know that there are a lot of questions (and answers) about this error, but unfortunately I have not fixed the error in my code, not yet, even following the past answers. I hope you can help me on this. I know that something does not work because of ask one-of A, but I have no any other idea how implement it in a different way, in order to ask an agent to create a new object.
The error messages comes when I call the procedure create_object in go.
The breed A is owner of agenda.
The breed object is owner of att1
to go
ifelse random-float 1 < 0.5
[ ask one-of A
[
ifelse empty? agenda
[ ifelse random-float 1 < 0.5
[create_object] ;; this returns the error message
[remove_object]
]
]
]
[...]
end
The error comes from create_object.
This is defined as follows
to create_object
create-object 1[
hide-turtle
set att1 random-float 1
let this-post myself ; is it the same object that I am creating?
if (condition1= TRUE)
[set agenda fput this-post agenda] ; this should add the object in the agent A's list
]
end
I do not know if you require more code.
Feel free to comment it if you need more information.
Thanks
Are 'A' and 'object' both breeds of turtles? If so, you have a turtle (of breed A) calling a procedure in which it is trying to create a turtle (of breed object). However, if you look at the Netlogo dictionary, you will see that create-turtles (and other forms like create-object) is only valid when used by the observer, not when used by a turtle.
If you want a turtle to create a new turtle, you need the hatch command. Note that the newly hatched turtle will have the same attributes (such as position) as the parent turtle.

Adding same item to more lists

I need to know if it is possible to add the same item to more than one list a time. Specifically, I want to add items to one turtle's list and to the lists of all the turtles connected to that turtle.
Something like this:
set list lput item list (turtle's list)
set list lput item list (neighbours' lists)
The item it's supposed to be the same. You could image a graph: turtles are nodes and each turtle has its own list.
My approach was:
ask one-of turtle[
set list lput item list
foreach [in-link-neighbors] of turtles-here
[ item -> set list lput item list ]
]
Thank you for your help
Short answer - yes, it is possible.
Here is a complete model with printout so you can see what it is doing.
turtles-own [mylist]
to setup
clear-all
create-turtles 10
[ set color blue
set mylist (list random 10)
]
ask turtles [ create-links-with n-of 2 other turtles ]
layout-circle turtles 7
ask turtles [show mylist]
ask one-of turtles [add-item-egonet]
ask turtles [show mylist]
reset-ticks
end
to add-item-egonet
let new-value 3
let targets (turtle-set self link-neighbors)
ask targets
[ set color red
set mylist lput new-value mylist
]
end
You didn't say what happened when you tried your code, but you would have received an error because item and list are NetLogo keywords. You also have a logic error - when you ask a turtle, you switch perspective (or 'context' in NetLogo terminology) to that turtle, the subsequent turtles-here will pick up all turtles on that same patch.
The big difference between our approaches is that I have used agentsets rather than lists. It could be done by iterating through a list of turtles, but if you find yourself writing NetLogo code that runs foreach over a list of turtles, the first thing you should do is rethink your approach. There are specific situations where you need lists of turtles, for example if you need to track the sequence of other turtles that a turtle has met. However, unless you are in one of those situations, it is better to use agentsets and ask.
So, switching to the paradigm of agentsets, my code creates the agentset of turtles that I want to change (the selected turtle and its network neighbours) and then simply tells them to add the new value at the end of their own lists of values.
Note that within a model, this could be achieved with a single line by constructing the turtle-set at the same time as asking it, but it would be more typical to do something like (from within an ask so the perspective is that of some selected turtle):
set mylist lput new-value mylist
ask link-neighbors [ set mylist lput new-value mylist ]

Count neighbors turtles of a specific patch and report true or false

Hello i will try to be quick
I have a room with a fire that expands , and i have two exits , all i want to do is say to agents that if a door is blocked by fire then to go to the other one. i came up with something like this but not result.
to doorblock
show count neighbors with [pcolor = 77] ;; the patch color of the two doors
end
;;to go
ask smarts [ ;;smarts are the agents inside the room that need to get oout
if [ doorblock > 5 ]
[ set target one-of sexits]] ;;sexits is the other door
Anyone got a better idea? Thanks
OK, so if I understood correctly, you want your agents to take a look at the door that is their current target, check if that door has more than 5 fire agents around it, and choose another target door if that is the case.
If your fire agents are just red turtles (with no specific breed), you probably want something like this:
ask smarts [
if count ([ turtles-on neighbors ] of target) with [ color = red ] > 5 [
if-else ([ breed ] of target = sexits )
[ set target one-of nexits ]
[ set target one-of sexits ]
]
]
The key primitives here are:
neighbors, that will give you the patches around a turtle (the patches around target, in this case)
turtles-on, that will give you the turtles that are on members of a patch set (here, that will be the turtles that are on the patches that are the neighbors of target)
and finally, with allows you to get only the turtles from an agentset that satisfy some condition (here, we use it to get only the red turtles that represent the fires).
You should also try to understand the of primitive.
And I guessed you wanted to assign a new target that was of a different breed than the previous one (south if north, north if south) but that's up to you.