Netlogo: Turtle checking if it can move into a valid target - if-statement

I am trying to simulate a neighbourhood visiting local businesses. There are two breeds of patches (home and businesses) and turtles (people and owners). The plan is to have people be able to visit a shop if an owner is on the business patch, and considered closed otherwise.
A day is split into three ticks: morning, afternoon, and evening. All shops are often in the morning and the afternoon, but a random number of owners go home in the evening. If shops are unavailable, owners will just go home.
After a while of running, I get the error MOVE-TO expected input to be an agent but got NOBODY instead. Pointing to the "ifelse" section of the evening-move command.
Thank you for the help!
to go
morning-move ;Morning movement (First shopping phase)
tick
afternoon-move ;Afternoon movement (Second shopping phase)
tick
evening-move ;Evening movement (Return home)
tick
end
to morning-move
ask owners [move-to work-xy] ;make owners open their businesses
ask people [ifelse any? open-busi-patches with [any? owners-here and count people-here < MaxCapacity] ;This checks if there are open businesses
[ask people [move-to one-of open-busi-patches with [any? owners-here and count people-here < MaxCapacity]]] ;move people to businesses under capacity
[ask people [move-to home-xy]]]
ask open-busi-patches [set OpsProfit OpsProfit + count people-here] ;cumulative count of patrons
end
to afternoon-move
ask people [ifelse any? open-busi-patches with [count owners-here > 0 and count people-here < MaxCapacity] ;This checks
[ask people [move-to one-of open-busi-patches with [any? owners-here and count people-here < MaxCapacity]]] ;move people to businesses under capacity
[ask people [move-to home-xy]]]
ask open-busi-patches [set OpsProfit OpsProfit + count people-here] ;cumulative count of patrons
end
to evening-move
ask n-of random count owners owners [move-to home-xy] ;This choses a random number of owners to stay open in the evening.
ask people [ifelse any? open-busi-patches with [any? owners-here and count people-here < MaxCapacity] ;This checks
[ask people [move-to one-of open-busi-patches with [any? owners-here and count people-here < MaxCapacity]]] ;move people to businesses under capacity
[ask people [move-to home-xy]]]
ask open-busi-patches [set OpsProfit OpsProfit + count people-here] ;cumulative count of patrons
end

So this is the code that is giving you the error (reformatted)
to afternoon-move
ask people
[ ifelse any? open-busi-patches with [count owners-here > 0 and count people-here < MaxCapacity ]
[ ask people ;;;; THIS LINE
[ move-to one-of open-busi-patches with [any? owners-here and count people-here < MaxCapacity]
]
]
[ ask people
[ move-to home-xy]
]
]
ask open-busi-patches [set OpsProfit OpsProfit + count people-here]
end
The basic problem is that the line I have marked is actually moving people and using up the open businesses. So the first condition tests whether there are businesses with space initially and it never gets retested.

Related

Let agents follow its neighbour but got the error "FACE expected input to be an agent but got NOBODY instead."

I try to move each agents to its related agents (defined by high trust connection and in my view) if there are any such agents, and else move the agent to one of its neighbours. However, I get the error "FACE expected input to be an agent but got NOBODY instead." and I don't know how to solve it. I think the use != nobody might cause the error. Any suggestions on how to solve this?
This is my code:
breed [ persons a-person ]
undirected-link-breed [ connections connection ]
connections-own [ trust ]
persons-own [ neighbours ]
to setup
clear-all
create-persons 10
[ setxy random-xcor random-ycor ]
setup-connections
reset-ticks
end
to setup-connections
ask persons
[
create-connections-with other persons
[ set trust 0.6 ]
]
end
to go
setNeighbours
movePersons
tick
end
to setNeighbours
ask persons [ set neighbours other persons in-cone 4 360 ]
end
to movePersons
ask persons
[
let highlyRelatedPersons (turtle-set [other-end] of my-out-connections with [trust = 0.6]) in-cone 4 360
let relatedPersons (turtle-set [other-end] of my-out-connections with [trust = 0.6])
ifelse any? highlyRelatedPersons
[
face one-of highlyRelatedPersons
]
[
let weaklyRelatedNeighbour one-of neighbours with [not member? self highlyRelatedPersons] ;select one of my neighbours that is not a highlyRelatedPerson
ifelse weaklyRelatedNeighbour != nobody
[
face weaklyRelatedNeighbour
]
[
face one-of relatedPersons
]
]
]
end
You are correct in what is causing the error
highlyRelatedPersons is an agentset and while an agentset can be empty, an agentset can never be nobody. one-of highlyRelatedPersons however, will be nobody if the agentset is empty, so you could use ifelse (one-of highlyRelatedPersons != nobody).
That said, is easier to just check if the agentset is empty by using any?:
ifelse any? highlyRelatedPersons
Your code also never actually creates any links for highlyRelatedPersons and relatedPersons is always empty. This means that the code will always return false on the first ifelse and move on to the second. Generally most turtles will have neighbours they can face, but sometimes there are none so they try to face one-of relatedPersons, which again causes a crash since relatedPersons is an empty agentset.

Netlogo: Edit link attribute based on lists of linked agents

I have a model with banks. Each bank is linked to all other banks by a special breed of undirected link called "riskshares". Each bank also has links to other types of agents.
Each bank has a list of countries where it operates. The list is called "op-countries-list", which does not have a fixed length, and both its length and countries are randomly picked. For example, one bank might have "op-countries-list" of length 5 = "Australia, Italy, Spain, Canada, Brazil", and another bank might have "op-countries-list" of length 2= "Italy, France".
Now: I need to change to "TRUE" one boolean attribute of the "riskshare" link, depending on whether there is one common country in the "op-countries-list" of the two banks linked by the "riskshare".
I have (among other things):
banks-own
[op-country-list]
riskshares-own
[same-country-op?]
And I am trying this approach:
ask banks
[
foreach op-country-list
ifelse member? op-country-list of other-end
[set same-country-op? of my-out-riskshare true]
]
With this, I get an "OF expected input to be a reporter" error. I think I should come up with a to-report procedure and then use it, but I am not sure how to do it in this case. In addition, I am not sure how to specify that I want other-end to look into the "riskshare" kind of link, and not all other links that the bank has.
Do you have any suggestions?
There is definitely a way to do it with foreach as you're getting at, but you might find map a little more appropriate in this case. map will iterate over items in a list and do "something"- in this case, you could check for membership in the list of interest. More detail in comments below:
breed [ banks bank ]
undirected-link-breed [ riskshares riskshare ]
banks-own [ op-country-list ]
riskshares-own [ same-country-op? ]
to setup
ca
random-seed 1
let possible-countries [ "CANADA" "USA" "FRANCE" "JAPAN" "AUSTRALIA" "SPAIN" "RUSSIA" ]
create-banks 5 [
; Pick some random countries
let n-countries random 3 + 1
set op-country-list n-of n-countries possible-countries
]
layout-circle turtles 8
ask banks [
set label op-country-list
; Build the links
create-riskshares-with other banks [
; Determine if the banks share an operating country
; Pull the country lists from each bank associated with the link
let bank-1-countries [op-country-list] of end1
let bank-2-countries [op-country-list] of end2
; Use map to iterate over each country of one bank and check its
; membership in the op-country-list of the other bank. Check if 'true'
; is found in the list
let any-true? member? true map [ cur_bank -> member? cur_bank bank-2-countries ] bank-1-countries
print member? true map [ cur_bank -> member? cur_bank bank-2-countries ] bank-1-countries
; Set same-country-op? according to the any-true condition
ifelse any-true? [
set same-country-op? true
set color blue
] [
set same-country-op? false
set color red
]
]
]
reset-ticks
end
This toy model (with the random-seed as is) gives an output like:
Which I think meets the conditions you outline. Hopefully that gets you pointed in the right direction!

How incorporate random-float into a command? NETLOGO

To eat ;to kill prey and eat it
let kill one-of prey-here in-radius smell
;need to code in a variable for success too
if kill != nobody
[ask kill [ die ]
set energy energy + 10000]
end
At present this is my command for my turtle to eat prey when they run into them on the map.
I want to add a variable so that there is a chance they don't get to eat. I know I need to use random-float 1
if random float is > .4 [what happens]
but i do not know where to add it into my eat commands so that it works.
can someone please advise?
I think you want if random-float 1 > .4 [do something]

Netlogo: How can I add some conditions by using the with, if statement or else?

I would like to count the number of turtles stopped on the road, and I want to take that X coordinate information and let it be the queue length. The following is the sample program.
ask turtles with [ not right-end ] ;a flag "right-end" to the red turtle for differentiation to the other blue turtles
[
ask turtles with [ speed = 0 ] ;the speed is 0 means stopped
[
set top max-one-of turtles [who] ;get a turtle with biggest id
set topx [xcor] of top
set L count turtles with [xcor > topx] ; L is the queue length of Little's Law
]
]
I am having trouble understanding exactly what you want to do, but I think it is something like this:
to-report countRightmost ;global context
let ts (turtles with [speed = 0 and not right-end] )
let top max-one-of turtles [who]
let topx [xcor] of top
report count ts with [xcor > topx]
end

Error using "n-of" in NetLogo to select specific patches

I am new to NetLogo and I am working on a deforestation model, where farmers are my agents. They have a ID variable (lotid-farmer) that matches a ID in the patches (lotid-patch) that they own. Basically, farmers check how much money and labor they have to deforest some forest patches or abandon some of their agricultural patches (pcolor = red) in their farms. By the end of the latter procedure, farmers have a "n-aband" value calculated, which is the number of patched they will abandon (randomly) within their farms (pcolor = yellow). This is the piece of code that was supposed to do that:
ask farmers [
...
if pcolor = red and lotid-patch = [ lotid-farmer ] of self [ ; Asks the farmer to randomly convert a # of the agricultural patches without maintenance to regrowth...
ask n-of n-aband patches [ set pcolor yellow ] ; ... among all agricultural patches own by the farmer
]
...
However, when I run the code, farmers start "abandoning" patches that they do not own. I think that is because I am not setting up a proper "restriction" when I use "ask n-of n-aband patches" but I thought that that should be implicit in the "if" statement I have in the line above, no? I have also tried:
ask n-of n-aband patches with [ pcolor = red and lotid-patch = [ lotid-farmer ] of self ] [ set pcolor yellow ]
But I run into a error:
A patch can't access a turtle variable without specifying which turtle.
error while patch 390 414 running OF
called by procedure CALCULATE-DEFORESTATION
called by procedure GO
called by Button 'Go'
Any suggestions on how to get this piece working? Thank you in advance.
To do this, you need to consider only patches owned by the farmer.
ask farmers [
let _id lotid-farmer
let _candidates (patches with [lotid-patch = _id and pcolor = red])
let _n-aband min (list n-aband count _candidates)
ask n-of _n-aband _candidates [set pcolor yellow]
]
But ... don't work with ids. Work with agents. Let each patch have an owner,
which is a farmer or nobody. Let each farmer maintain a list (or agentset)
of patches that it owns.