I use two types of turtles, cars and houses. both are randomly positioned.
My goal is to get a route for each car starting from a combined route vector, and have each car move and visit every home that has been assigned to it.
First i create a route for each car from the combined route vector.
I present my code below.
But now, im trying make car follow respective route...
globals [ route-vector ]
breed [carr car]
breed [hous housess]
carr-own [ route ]
to setup
clear-all
create-carros
create-casas
make-routes
end
to create-carros
create-carr cars [ set color green ]
ask carr [
set shape "car"
set size 1.5
setxy random-xcor random-ycor
]
end
to create-casas
create-hous house [ set color red ]
ask hous [
set shape "house"
set size 1.5
setxy random-xcor random-ycor
]
end
to make-routes
set route-vector [ 3 4 5 6 7 0 1 2 0 1 ] ;5 10 15 20 25
let houses sublist route-vector 0 (length route-vector / 2 )
let carlist sublist route-vector (length route-vector / 2 ) (length route-
vector)
ask carr [ set route [] ]
(foreach carlist houses
[ [the-car the-house] ->
ask carr with [who = the-car] [ set route lput the-house route ]
]
)
end
to go
ask carr [
;; if at target, choose a new random target
; if distance route = 0
; [ set route one-of route-vector
; face route ]
; ;; move towards target. once the distance is less than 1,
; ;; use move-to to land exactly on the target.
; ifelse distance route < 1
;let mylist [1 2 3]
;foreach route
face route
fd 1
;print map last filter first route
; face housess 3
; fd 1
; move-to one-of route
; fd 1
]
; move-to housess 3
;fd 1
;tick
end
I want use the route variable to actually move along the path.
but I do not know how to inform each car of their respective route and cause them to move to their homes.
I tried to use the go button with only one car
do:
ask car 1
[
face route
fd 1
but always get the error ("FACE expected input to be an agent but got the
list [4 7] instead.")
]
end
in this case I wanted to cause car 1 to move first to house 4 and second to house 7, then back to its original position ...
I've tried several ways, but I can not find a solution. I tried to do it separately, I chose the first item from the "route" list for each car but I still could not ..
If someone can help me, I really appreciate it. Thank you
Using who
numbers to index turtles can cause problems- in this case, you'll run into an issue where you can't really dynamically update the list, because hous
and carr
numbers are based solely on the order of their creation. It's far better to store the turtles directly in a list, if possible. Check out this example using a modified version of your setup:
globals [ route-vector ]
breed [carr car]
breed [hous housess]
breed [spawns spawn]
carr-own [ route route-counter spawn-target target]
to setup
clear-all
create-carros
create-casas
make-routes
reset-ticks
end
to create-carros
create-carr 3 [ set color green ]
ask carr [
set size 1.5
setxy random-xcor random-ycor
; set up a 'route-counter' to act as an index for a car's route
set route-counter 0
set target nobody
set route []
pd
]
; hatch a 'spawn-target' turtle that can be used to return
; the carr back to their starting position
ask carr [
hatch 1 [
set breed spawns
ht
]
set spawn-target one-of other turtles-here with [
xcor = [xcor] of myself
]
]
end
to create-casas
create-hous 5 [ set color red ]
ask hous [
set shape "house"
set size 1.5
setxy random-xcor random-ycor
]
end
Now, instead of relying on who
numbers to index the houses, use a list of the houses directly in your carr
routes:
to make-routes
; Just use the car-order
let car-order [ 0 1 2 0 1 ]
; Create a list of hous directly by sorting them
let houses sort hous
; Your same foreach procedure, but in this case the carr
; are storing the house in the list directly to avoid
; indexing problems
ask carr [ ]
(foreach car-order houses
[ [the-car the-house] ->
ask carr with [who = the-car] [ set route lput the-house route ]
]
)
end
Then, the carr
can just iterate over their route to select a new target based on the index value of route-counter
(with a small break for their spawn-target
).
to go
ask carr [
; If a car has no target, set the target to the
; item indexed by 'route-counter'
if target = nobody [
set target item route-counter route
]
; Movement chunk
face target
ifelse distance target > 1 [
fd 1
] [
move-to target
; Only advance the route counter if the current target
; was not the original spawn point
if target != spawn-target [
set route-counter route-counter + 1
]
set target nobody
]
; If the route counter would index outside of the
; list boundaries, reset it to 0
if route-counter > length route - 1 [
set route-counter 0
set target spawn-target
]
]
tick
end
This is still not super programmatic, as you are relying on your car-order being the same length as the count of your houses, but I'm not sure what you're actually trying to do so maybe it will work.
EDIT
As per your comment- if you must use the who
number, you can still use the "spawn target" example to have the turtles return to their starting position- just have it happen after the carr
and hous
have been spawned. Again, this is definitely not ideal as your model can 'break' if you're not careful with spawn order, number of carr
/ house
, etc.
So, basic setup
and create-casas
procedures as above, with this as your new create-carros
procedure:
to create-carros
create-carr 3 [ set color green ]
ask carr [
set size 1.5
setxy random-xcor random-ycor
; set up a 'route-counter' to act as an index for a car's route
set route-counter 0
set target nobody
set route []
pd
]
end
Now, your make-routes
can contain the spawn
target turtles (this example has the out-of-order houses from your comment):
to make-routes
set route-vector [4 7 6 3 5 0 1 2 0 1]
let houses sublist route-vector 0 (length route-vector / 2 )
let carlist sublist route-vector (length route-vector / 2 ) (length route-vector)
(foreach carlist houses
[ [the-car the-house] ->
ask car the-car [
set route lput ( housess the-house ) route
]
]
)
; hatch a 'spawn-target' turtle that can be used to return
; the carr back to their starting position
ask carr [
hatch 1 [
set breed spawns
ht
]
set spawn-target one-of other turtles-here with [
xcor = [xcor] of myself
]
]
end
Then, the go
procedure from above should work without any change.
EDIT 2
A simple way to have your carr stop is to set a logical flag so that only carr that meet a certain criteria will move. Consider this modified car-own
and create-carros
setup:
carr-own [ route route-counter spawn-target target route-complete? ]
to create-carros
create-carr 3 [ set color green ]
ask carr [
set size 1.5
setxy random-xcor random-ycor
; set up a 'route-counter' to act as an index for a car's route
set route-counter 0
set target nobody
set route []
set route-complete? false
pd
]
end
Here, we now have a boolean (logical) variable called route-complete?
, which is set to false
for all new carr. Now, you can add a line into the go
procedure that says "only cars that have route-complete?
set to false, do these actions."
to go
; ask carr with route-complete set to false
ask carr with [ not route-complete? ] [
; If a car has no target, set the target to the
; item indexed by 'route-counter'
if target = nobody [
set target item route-counter route
]
face target
ifelse distance target > 1 [
fd 1
] [
move-to target
; Only advance the route counter if the current target
; was not the original spawn point. ADDITIONALLY,
; if the target is the starting target, set route-complete?
; to true for that carr
ifelse target != spawn-target [
set route-counter route-counter + 1
] [
set route-complete? true
]
set target nobody
]
; If the route counter would index outside of the
; list boundaries, reset it to 0
if route-counter > length route - 1 [
set route-counter 0
set target spawn-target
]
]
tick
end
You'll notice that there's a modified bit in the move-to
chunk where if the carr
is moving back to its starting position, it also sets its route-complete?
to true, so that the next time
gois called, that
carr` won't move.
Note that you could change that route-complete?
to a counter instead of a true/false if you wanted carr
to run through their route a set number of times.