How to set global variable as pxcor or pycor of a patch? - netlogo

I want to save the location of the next patch to use as a global variable so I can refer back to it, like in position-shift so I can alter it in case it is near the edge of the world. However, the code I am using to execute whatever the patch does is in observer mode with set-position and position-shift incorporated in it.
An error shows that patch-at is in turtle/patch-only context while set-position in observer context.
(Not sure but would similar error come up for position-shift?)
to set-position
set nextXcor [pxcor] of patch-at 0 -5
set nextYcor [pycor] of patch-at 0 -5
position-shift
end
to position-shift
if nextYcor = -15
[set nextXcor [pxcor] of patch-at 3 30
set nextYcor [pycor] of patch-at 3 30]
if nextXcor = 15 and nextYcor = -15
[user-message "Space limit reached. Press Halt to continue." stop]
end
Q: How should I approach fixing the code for set-position and potentially position-shift so global variables nextXcor and nextYcor can save the location of the next patch to use?

It is generally preferable to work directly with patches when that is feasible.
globals [nextPatch]
to test
;first test
set nextPatch one-of patches
position-shift
;second test
set nextPatch (patch 0 -15)
position-shift
;third test
set nextPatch (patch 15 -15)
position-shift
end
to position-shift
if ([pycor] of nextPatch = -15) [
if ([pxcor] of nextPatch = 15) [
user-message "Space limit reached. Press 'OK' to continue or 'Halt' to stop."
]
set nextPatch (patch 3 10)
]
;remove the next line
print nextPatch
end

Related

How to make a turtle go one step at a time to another turtle?

I am trying to write a program which simulates drones picking up packets and delivering them to certain platforms. Once the packets have been delivered, they die. Right now, if a "single step" is performed, the drones move immediately from a packet location to a platform and again to a packet location. However, I'd like the drones to move in actual steps, such that I can include proper waiting times of packets and get a better view of how long it takes to deliver one package.
I have tried to implement "fd 1" in multiple locations (for example immediately in the "to go" function, but also separately in "to fly" or both in "to fly-empty" and "fly-loaded". If I implement the "fd 1" in any of these locations, the drones still jump in (for me seeming to be) random jump sizes and the system stops functioning, as it does not actually pick up any packages. It would be great if someone could help me with this!! Thanks in advance.
enter code here
breed [platforms platform]
breed [packets packet ]
breed [drones drone ]
drones-own [charge
mypacket
status
consumption
target
dropoff
capacity
transportedpackets
]
packets-own [destination
waitingtime
pickups
mydrone
lastdrone
]
globals [delivered
faults
nrdrones
deliverydrones
colorize
pickedup
destinationlist
dronewithpackets]
to setup
ca
clear-all-plots
setup-globals
setup-platforms
setup-drones
setup-packets
reset-ticks
end
to setup-globals
set delivered 0
set faults 0
set deliverydrones (list)
set destinationlist(list)
set colorize color?
end
to setup-platforms
create-platforms 1 [setxy -15 6 set color green set shape "circle" set label "Platform 0"]
create-platforms 1 [setxy -2 10 set color green set shape "circle" set label "Platform 1"]
create-platforms 1 [setxy 18 -7 set color green set shape "circle" set label "Platform 2"]
create-platforms 1 [setxy 9 -2 set color green set shape "circle" set label "Platform 3"]
end
to setup-drones
create-drones 3 [
setxy 0 0
set color red
set mypacket nobody
set status "ready"
set charge MaxCharge
set label who
set transportedpackets (list)
]
end
to setup-packets
create-packets 10 [
setxy 10 10
set color yellow
set shape "circle"
set size .5
set destination platform 1
set waitingtime 0
set pickups 0
set mydrone nobody
]
create-packets 4 [
setxy -10 -10
set color yellow
set shape "circle"
set size .5
set destination platform 3
set waitingtime 0
set pickups 0
set mydrone nobody
]
create-packets 10 [
setxy 9 -2
set color yellow
set shape "circle"
set size .5
set destination platform 1
set waitingtime 0
set pickups 0
set mydrone nobody
]
create-packets 10 [
setxy -2 -10
set color yellow
set shape "circle"
set size .5
set destination platform 0
set waitingtime 0
set pickups 0
set mydrone nobody
]
end
to go
ask drones with [status = "flying" ] [fly ]
ask drones with [status = "charging" ] [recharge ]
ask drones with [status = "ready" ] [pickup ]
ask packets with [mydrone = nobody ] [countwaitingtime ]
ask drones with [status = "waiting for new packets"] [packetstopickup ]
end
to fly
set charge charge - consumption
;print (word "Drone " who "has this much charge left: " charge)
if charge < 0 [if capacity != 0 [ask packets with [mydrone = dronewithpackets] [die] die]]
ifelse mypacket = nobody [fly-empty] [fly-loaded]
end
to fly-loaded
ask packets with [mydrone = dronewithpackets]
[print (word "Thanks drone" dronewithpackets " for dropping me, packet number " who " of at platform " position max destinationlist destinationlist) die]
move-to dropoff
if distance dropoff = 0
[land]
end
to fly-empty
ifelse any? packets with [mydrone = nobody]
[set target one-of packets with [mydrone = nobody]
move-to target
if distance target = 0
[pickup]]
[set status "waiting for new packets"
print "No more packets to transport at the moment"]
end
to land
set delivered delivered + capacity
set status "charging"
end
to pickup
ifelse any? packets-here with [mydrone = nobody]
[ set destinationlist (list)
set destinationlist lput (count packets-here with [destination = platform 0 and mydrone = nobody]) destinationlist
set destinationlist lput (count packets-here with [destination = platform 1 and mydrone = nobody]) destinationlist
set destinationlist lput (count packets-here with [destination = platform 2 and mydrone = nobody]) destinationlist
set destinationlist lput (count packets-here with [destination = platform 3 and mydrone = nobody]) destinationlist
;print destinationlist
;print (word "Platform " position max destinationlist destinationlist "is my next destination")
ifelse max destinationlist >= 5 [set capacity 4][set capacity max destinationlist]
set dronewithpackets who
ask n-of capacity packets-here with [destination = platform (position max destinationlist destinationlist) and mydrone = nobody] [
set mydrone dronewithpackets
print (word "I am packet " who "and I am transported by drone " mydrone "to platform " position max destinationlist destinationlist)
;print (word "I have been waiting to be pickedup for " waitingtime )
]
set dropoff platform (position max destinationlist destinationlist)
set mypacket capacity
set consumption capacity
set pickedup pickedup + capacity
;print (word "I picked up " capacity " packet(s)")
set transportedpackets lput capacity transportedpackets
;print (word "I am drone " who " and I have transported " sum transportedpackets " packets today" )
set status "flying"
]
[set mypacket nobody set consumption 1]
set status "flying"
end
to recharge
set charge charge + RechargePower
if charge > MaxCharge [set status "ready" ]
end
to countwaitingtime
set waitingtime waitingtime + 1
end
to packetstopickup
ifelse any? packets with [mydrone = nobody]
[pickup] [fly-empty]
end
Replace all your move-to with something like:
face dropoff
forward 1
The face tells the turtle to change heading to go in the direction towards where it is trying to get to. This will move it forwards one unit distance each iteration through the go procedure.
You should consider adding time to your model by adding tick at the end of the go procedure, which advances the internal counter. You use time implicitly by, for example, increasing the waitingtime counter, but you don't actually have time progressing.
Once you have both tick and forward then the turtles will move 1 unit each tick and everything that happens simultaneously can occur during one tick. If you have a go button, that button instructs the model to run the go procedure once and you can edit the button to check 'forever' so that it keeps on calling the go procedure.
The code below should do it. The ifelse statement in the while loop incorporates JenB comment, that the target is never reached with a step size of one, while the distance is lower than one.
Please check the ifelse below: if the distance is lower than one, the drone moves to the target. In case the distance is greater, it moves a step towards the target, waits 0.1 seconds (to show discrete steps) and the while loop is executed again until the drone reaches the target.
breed [targets target]
breed [drones drons]
to setup
ca
create-targets 5 [
set shape "circle"
set color white
setxy random-xcor random-ycor
]
create-drones 1 [
set color red
]
end
to go
ask one-of drones [
;; assuming you have multiple targets to choose from
;; if there is just one target, remove the line below
let temp-target one-of targets
face temp-target
while [distance temp-target != 0] [
ifelse distance temp-target < 1
[ move-to temp-target ]
[ wait 0.1 fd 1 ]
]
show "target reached"
]
end

Seed dispersal around a tree provokes an infinite loop?

I've just started a project in which I intend to simulate (among other things) the seed dispersal around trees (named zsps). Neighboring patches can already be settled or unable for seeding due to low fertility.
I wrote code that runs (at the begining of simulation) but that made the code enter into an infinite loop (I think) because some trees attempt to spread seeds but cannot find any available place.
Does anyone have a solution to escape from this trap (in case the number of places is < the number of seeds or in case there are no places at all)?
Here is the procedure I wrote :
to check-seed-dispersal
ask zsps[
let nb-seeds 0
ifelse (age > 4) [set NFemFlowers 100]
[set NFemFlowers 0]
let temp-color color
if Tot_pol > 0
[set nb-seeds round ((NFemFlowers / Tot_pol) * 6 ) ]
if (nb-seeds > 0 )[
ask patches in-radius 5 with [fertility > 8 and not any? zsps-here]
[sprout-zsps nb-seeds
[ifelse (temp-color = yellow)
[set color gray set age 0 ]
[set color red set age 0 ]
]
]
]
]
end

How do I make turtle face in an organized manner like the "cro" command but in turtle context?

I am trying to make a turret that will fire 8 bullets in 8 directions. In the command I have, they all spawn with heading 0 how do I make them face the right direction. Each turtle should face in a multiple of 45. Just like it would with the cro command in observer context.
to fire-tacks
ask ttacks with [alive?] [
set attackSpeed attackSpeed + .5
if any? turtles with [is-bloon?] in-radius 5 and attackSpeed >= 12
[set attackSpeed 0
hatch-btacks 8 [set alive? false set is-turret? false
set size 1 set damage 1 set color black set is-dart? true set bullet-
speed 4
]]]
end
You could use range and foreach to do this (check the links for more detail on how they work). range can generate a sequence of the headings you would like, and foreach can iterate over that sequence to sprout new turtles with each heading. Have a look at this simplified example:
breed [ turrets turret ]
breed [ btacks btack ]
to setup
ca
create-turrets 1 [
setxy random-xcor random-ycor
]
reset-ticks
end
to go
ask turrets [
foreach ( range 0 360 45 ) [
new_heading ->
hatch-btacks 1 [
set heading new_heading
fd 1
]
]
]
end

Netlogo I want to convert turtles-own variable to global's variable, and run them as "counter" of turtles-own variable without any error

I want to convert turtles-own's variable (nb-of-turtles, nb-dead) to global's variable (number-of-turtles, number-dead) in order to compile with BehaviorSpace. nb-of-turtles is a decrement-counter (In the beginning of the model, I use this as increment counter. The counter counts the number of turtle in the road. This counter does not count as cumulative value. Therefore I puts "set nb-of-turtles nb-of-turtles - 1"). nb-dead are increment- counter (This counter needs to count as cumulative value of number of dead turtles totally). However, these counters do not count well. When the turtle at the end of the road dies, increment nb-dead by one. Similarly, when the turtle at the end of the road dies, it decrements nb-of-turtles by one. In my model, when the turtle dies at the end of the road, I use the flag (onend). The following is sample code. Please give me advice.(Some codes have already been consulted and discussed, then solved in the following link.the link Thank you very much.
globals [ number-of-turtles number-dead A ]
turtles-own [ onend? nb-of-turtles nb-dead ]
let numle count [turtles-at 0 0] of patch min-pxcor 0
if numle = 0 [
create-car
set number-of-turtles number-of-turtles + 1
]
to create-car
crt 1 [
set onend? FALSE
]
end
ask turtles with [onend?]
[ if gamma-A = 0 [
die
set nb-dead nb-dead + 1 ;;This does not count.
set nb-of-turtles nb-of-turtles - 1 ;;This does not count well.
]
]
ask (turtles-on patch max-pxcor 0) with [not onend?]
[
set number-of-turtles nb-of-turtles
set number-dead nb-dead
set gamma-A precision (random-gamma (α) (β))0
set speed 0
set color red
set onend? TRUE
]
tick
end
You may be mixing up the use of global and turtles-own variables. It doesn't really make sense in this context to use a turtles-own variable as a counter, since every new turtle created will have its "nb-dead" or "nb-of-turtles" variable start at 0. It's better in this case to have the turtles access the global counter directly when they die, for example. Additionally, you can just use count turtles to get the current number of turtles- no need to have the turtles manually add to that value. For an example, please see below:
globals [ number-of-turtles number-dead gamma-A start-patch end-patch]
turtles-own [ onend? speed ]
to setup
ca
reset-ticks
set start-patch patch min-pxcor 0
set end-patch patch max-pxcor 0
set gamma-A random-gamma 10 1
end
to create-car
ask start-patch [
sprout 1 [
set heading 90
set shape "car"
set color green
set onend? false
set speed 1
]
]
end
to go
;; If start patch has no turtles, it has a 10% chance
; of spawning a new turtle.
if [ count turtles-here ] of start-patch = 0 and random 100 < 10 [
create-car
set number-of-turtles number-of-turtles + 1
]
;; Ask any turtles not on the end patch to move fd
; at their speed, if they get to the end-patch
; set their speed to 0
ask turtles with [ not onend? ] [
fd speed
if patch-here = end-patch [
set speed 0
set color red
set onend? true
]
]
;; Decrease the GLOBAL variable of gamma-A by 0.1
set gamma-A gamma-A - 0.1
;; Ask turtles that are at the end,
; if gamma-A is less or equal to 0,
; increase the number-dead variable by one
; and then die
ask turtles with [onend?]
[
if gamma-A <= 0 [
set number-dead number-dead + 1
die
]
]
;; Use count to set the number-of-turtles
set number-of-turtles count turtles
;; If gamma-A has dropped to 0 or below,
; reset it to its new higher value
if gamma-A <= 0 [
set gamma-A random-gamma 10 1
]
tick
end

Running a model several times with BehaviorSpace

From BehaviorSpace, I would like to run a model 100 times by varying two variables as follows:
["x-area" 1 ] and ["y-area" [1 1 100]].
A model is built as follows:
create landscape
add-turtles
go-simulation
By using the two variables, I would like that my 100 models run as follows:
;;; Model 1 ;;
"x-area" = 1
"y-area" = 1
clear-all
create landscape
add-turtles
go-simulation
;;; Model 2 ;;
"x-area" = 1
"y-area" = 2
add-turtles
go-simulation
;;; Model 3 ;;
"x-area" = 1
"y-area" = 3
add-turtles
go-simulation
....
;;; Model 100 ;;
"x-area" = 1
"y-area" = 100
add-turtles
go-simulation
To do this, I built 100 experiments and this method worked. Is there a faster way to run automatically 100 models without doing 100 experiments ? I tried to build 1 experiment like this
But I have this error message:
OF expected input to be a turtle agentset or patch agentset or turtle or patch but got NOBODY instead.
org.nlogo.nvm.ArgumentTypeException: OF expected input to be a turtle agentset or patch agentset or turtle or patch but got NOBODY instead.
at org.nlogo.prim._asm_proceduremovewithinpolygon_ifelse_86.perform(:4)
at org.nlogo.nvm.Context.runExclusive(Context.java:119)
at org.nlogo.nvm.ExclusiveJob.run(ExclusiveJob.java:57)
at org.nlogo.nvm.Context.runExclusiveJob(Context.java:162)
at org.nlogo.prim._asm_procedurestartsimulation_ask_69.perform(:1)
at org.nlogo.nvm.Context.stepConcurrent(Context.java:91)
at org.nlogo.nvm.ConcurrentJob.step(ConcurrentJob.java:82)
at org.nlogo.job.JobThread.org$nlogo$job$JobThread$$runPrimaryJobs(JobThread.scala:143)
at org.nlogo.job.JobThread$$anonfun$run$1.apply$mcV$sp(JobThread.scala:78)
at org.nlogo.job.JobThread$$anonfun$run$1.apply(JobThread.scala:76)
at org.nlogo.job.JobThread$$anonfun$run$1.apply(JobThread.scala:76)
at scala.util.control.Exception$Catch.apply(Exception.scala:88)
at org.nlogo.util.Exceptions$.handling(Exceptions.scala:41)
at org.nlogo.job.JobThread.run(JobThread.scala:75)
The problem is that my models continue to run with this error. So it is difficult to see where is the problem. Given the following message:
"at org.nlogo.prim._asm_proceduremovewithinpolygon_ifelse_86.perform(:4)" in the error message,
maybe that the problem is in the procedure "move-within-polygon".
Here is my procedure "move-within-polygon" for a given color of polygons:
if [pcolor] of patch-here = green [
set list-angles-in-green item 0 table-angles
loop [
let angle-in-green one-of list-angles-in-green
ifelse [pxcor] of (patch-right-and-ahead angle-in-green 1) = max-pxcor or [pycor] of (patch-right-and-ahead angle-in-green 1) = max-pycor [
print "die"
die
stop ]
[ ifelse (patch-right-and-ahead angle-in-green 1) != nobody and [pcolor] of (patch-right-and-ahead angle-in-green 1) = green [
print "move"
move-to patch-right-and-ahead angle-in-green 1
[ if not any? neighbors with [pcolor = green] [
print "no neighbors"
move-to patch-here
stop ] ] ] ] ]
Thanks for your help.
If a turtle ends up on the edge of the world, then patch-right-and-ahead angle-in-green 1 might point outside the world (depending on what angle-in-green is), so [pxcor] of in [pxcor] of (patch-right-and-ahead angle-in-green 1) = max-pxcor would ask for the coordinate of nobody. The same thing could happen for pycor later in the same line.
Question: Can a turtle ever get to the edge of the world in your model? It looks to me like the code that you displayed could lead to that result.
If so, then one way to prevent the error would be to replace
[pxcor] of (patch-right-and-ahead angle-in-green 1) = max-pxcor
with
xcor = max-pxcor
That's true when a turtle reaches the last column of patches. If you also want turtles to die when they're close to the edge, you could use both of these expressions in the if-else:
(xcor = max-pxcor) or ([pxcor] of (patch-right-and-ahead angle-in-green 1) = max-pxcor)
(I added parentheses simply for clarity.)
However, I wonder whether this would serve the same purpose:
xcor = max-pxcor or xcor = max-pxcor - 1
If any of these methods are right for your application, then you can obviously do the same thing for the y coordinates.
Your experiment setup appears correct to me, except that you should remove the "Stop condition" of TRUE, because if the stop condition is always true, your runs will never run the go commands even once.
The error you're getting is coming from code that you haven't shown us, so I can't help you there. You'll need to show us the code in which the error is occurring.
Also, at the time the error occurs, what are the values of x-area and y-area? And does the same error occur if you set x-area and y-area to the same values outside BehaviorSpace? If so, then the error doesn't really have anything to do with BehaviorSpace.
Finally, a note on terminology: there is only one model here, not 100, and only one experiment here, not 100. You're attempting to run one experiment on your model, and that experiment consists of 100 model runs. Using the standard terminology will help you communicate your issue clearly.