The orientation (heading) of turtles must be set randomly when wandering but must be limited to a range of 40 degrees (20 to the left and 20 to the right) per step taken, the only exception to this is when avoiding other agents, in this instance a maximum turn of 90 degrees is permitted.
I am new to netlogo. I want these movements with my turtles.
to move-turtles
ask turtles[
if who = ticks[
stop]
let agent-ahead one-of turtles-on patch-ahead 1
ifelse agent-ahead != nobody [
??????
][
rt random 20
lt random 20
]
fd 0.2
]
As stated in the comments you can just use rt and lt with random 45 to achieve what you want.
to setup
clear-all
reset-ticks
crt 5 [set color red]
end
to go
ask turtles[
if who = ticks[
stop]
fd 1
let agent-ahead one-of turtles-on patch-ahead 1
ifelse agent-ahead != nobody [
set color blue
ifelse random 2 = 1 [rt random 45] [lt random 45]
][set color red
rt random 20
lt random 20
]
fd 0.2
]
tick
end
I am building an evacuation model for my university lecture hall. The problem I am facing is that the people always walk over the gray patch that is not supposed to be walked over even though I have included the procedure to avoid walls in the code. This is the current code for my evacuation model. Also is it possible for the turtles to stop moving when arrived at the exit which in this case is the green patch?
breed [people person]
to setup
clear-all
reset-ticks
setup-patches
setup-people
end
to setup-people
set-default-shape people "person"
ask n-of n-people (patches with [pcolor = white]) [sprout-people 1]
ask people [set color cyan]
end
to setup-patches
draw-wall
draw-exit
;change the color of the floor for better visibility
ask patches[
if pcolor = black [set pcolor white ]
]
end
to draw-wall
; Make 4 boundary walls
ask patches with [ pycor >= -25 and pycor >= 25][ set pcolor gray ]
ask patches with [ pycor <= -25 and pycor <= 25][ set pcolor gray ]
ask patches with [ pxcor >= -25 and pxcor >= 25][ set pcolor gray ]
ask patches with [ pxcor <= -25 and pxcor <= 25][ set pcolor gray ]
; make rows of walls inside that look like seats in a lecture hall
; left rows of chairs
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 20][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 18][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 16][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 14][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 12][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 10][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 8][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 6][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 4][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 2][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = 0][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = -2][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = -4][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = -6][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = -8][set pcolor gray]
ask patches with [pxcor <= 21 and pxcor >= 13 and pycor = -10][set pcolor gray]
; middle rows of chairs
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 20][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 18][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 16][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 14][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 12][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 10][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 8][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 6][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 4][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 2][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = 0][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = -2][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = -4][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = -6][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = -8][set pcolor gray]
ask patches with [pxcor >= -9 and pxcor <= 9 and pycor = -10][set pcolor gray]
; right rows of chairs
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 20][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 18][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 16][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 14][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 12][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 10][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 8][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 6][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 4][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 2][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = 0][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = -2][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = -4][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = -6][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = -8][set pcolor gray]
ask patches with [pxcor >= -21 and pxcor <= -13 and pycor = -10][set pcolor gray]
end
to draw-exit
; Setting 4 exits assuming all UTAR lecture halls have 4 exits
; two at the top left and right and two at the bottom left and right
ask patches with [pxcor <= 23 and pxcor >= 21 and pycor = 25][set pcolor green]
ask patches with [pxcor >= -23 and pxcor <= -21 and pycor = 25][set pcolor green]
ask patches with [pxcor <= 23 and pxcor >= 21 and pycor = -25][set pcolor green]
ask patches with [pxcor >= -23 and pxcor <= -21 and pycor = -25][set pcolor green]
end
to go
let hall patches with [pycor <= 0 and pycor >= -25 and pxcor <= 0 and pxcor >= -25 ]
ask people[
move-people
avoid-walls
]
tick
end
to move-people
face min-one-of patches with [pcolor = green ] [distance myself ]
fd 0.1
end
to avoid-walls
ifelse [pcolor] of patch-ahead 1 = gray
[lt random-float 360 ] ;; we see a gray patch ahead of us. We turn a random amount
[fd 0.1] ;; otherwise, it is safe to move forward
end
This will be a long answer but I want to guide you step by step.
Let's start from why you are facing an unwanted behaviour.
In go, first you ask people to move (move-people) and only later you ask them to avoid walls (avoid-walls).
Even looking at it more closely, you can see that your avoid-walls procedure is not having any effect on your people's walk. Let's read your code from the point of view of your agents:
I am a person and I enter the move-people procedure, which makes me face the nearest exit. There is a wall in front of me, but nothing in the code is telling me that I should care about it: in fact the next line of code is forward 0.1, so I just move forward.
Now I enter the avoid-walls procedure. As I said, there is a wall in front of me, so I randomly change my heading. Ah, there is no wall in front of me anymore! However I will not move forward in this new direction, because there is no line of code telling me to do it now that I changed my heading.
I exit avoid-walls and this means that I also need to exit the ask people [...] command block in go. I have finished my actions for this iteration.
Here we are in the next iteration. I am now heading towards a patch without walls (because I randomly selected this heading from avoid-walls in the previous iteration)... however, before I can move in this correct direction, I am again in move-people, and I am asked again to change my heading to face the nearest green patch. This means that I am back to the initial situation, when I had a wall in front of me! The next line of code is asking me to move forward 0.1, so I continue moving on the wall...
and on, and on, and on...
So let's see, step by step, how you can solve this.
First of all, let's tidy up a couple of things:
Your people are the agents executing the move-people procedure, so a better name for this procedure would be just move so that you can have ask people [move].
In order to have agents stop moving when they reached the exit, you can simply make sure that only those agents who are not on a green patch will be asked to move: ask people with [pcolor != green] [move] (note that turtles can directly read and modify patches-own variables of the patch they are standing on, this is why we are able to use pcolor in the context of a turtle).
You will also probably want to have your model stop when everyone reached an exit, so you can add a stop condition at the beginning of the go procedure: if (not any? people with [pcolor != green]) [stop].
The result of the three points above will be the following go procedure:
to go
if (not any? people with [pcolor != green]) [stop]
ask people with [pcolor != green] [
move
]
tick
end
Now, back to the content of move.
As you can see, I only have move inside go (i.e. I removed any procedure that is specific to the goal of avoiding walls). This is because, following the journey of a person as we described it above, it is essential that the actions for avoiding walls are not carried out after moving, but upon choosing where to move.
An equally important thing is to make sure that when a person finds a direction where there are no walls, it has to move in that direction before being asked to face the exit again.
Therefore, a first idea could be to do:
to move
face min-one-of patches with [pcolor = green] [distance myself]
while [[pcolor] of patch-ahead 1 = gray] [
right random 360
]
forward 1
end
This way, we make sure that at each iteration of go people will:
Face the nearest exit.
If the patch ahead of them is clear, they will ignore the while loop and jump directly to forward 1.
If the patch ahead of them has a wall, they will enter the loop and only exit it when they found a clear direction (i.e. when the condition of the while loop evaluates as false).
In any case, on each iteration of go every turtle will move exactly by 1 in a direction without walls. On the next iteration of go each turtle will simply start again by facing the nearest exit and testing the wall condition again.
This works, and it is similar to the Look Ahead Example model in the NetLogo library (with the difference that, here, the while loop makes it possible that every turtle moves at every iteration of go, instead of having to spend a full iteration only to change heading if they need to). However, if you try it, you will see that the result is that people who find themselves between the lines of walls will move randomly until they find a way out. This is not very realistic, but we can make it more realistic.
For example, we can make sure that people who find a wall will not move completely randomly to find a way away from the wall, but instead will lean somewhat towards the direction of the nearest exit.
An idea could be to divide the 360° spectrum into four quadrants (0°-89°; 90°-179°; 180°-269°; 270°-359°), so that each person facing a wall can:
Keep note of the quadrant in which the nearest exit is;
If there is a wall in front of them, look for a new direction in the same quadrant.
This way, the wandering of people will be less randomic (i.e. we will see less back and forth, and more going around obstacles).
For this purpose, let's create a new reporter called new-direction. To use this we can create a people-own variable called target (to avoid repeating min-one-of patches with [pcolor = green] [distance myself]):
people-own [
target
]
to move
set target min-one-of patches with [pcolor = green] [distance myself]
face target
while [[pcolor] of patch-ahead 1 = gray] [
set heading new-direction
]
forward 1
end
to-report new-direction
let direction-quadrant ceiling (towards target / 90)
if (direction-quadrant = 0) [
set direction-quadrant 1
]
report random 91 + (90 * (direction-quadrant - 1))
end
You can work out the maths yourself and see that new-direction always reports a new heading that is in the same quadrant (including its borders) as the direction towards the nearest exit. Given that this happens inside the while loop, each agent will then exit the loop only once they found a direction that is more or less towards the nearest exit and that can avoid the wall. Once they found it, they move forward.
However you will also see that sometimes people get stuck in a loop: this happens when they find themselves in a location where another step forward causes the nearest exit to change quadrant (as we defined quadrants from the point of view of turtles), and the subsequent step forward causes the nearest exit to go back to the previous quadrant.
We can solve this by making sure that people remember what was the exact patch they were standing on in the previous step (I call it last-patch in the code below). If such patch is the same as the one they are planning to go to now (checked with (patch-ahead 1 = last-patch)), it means that they are stuck in a loop. In that case, instead of executing forward 1 they execute forward -1 which basically means "go backwards by 1". Considering that at this point forward refers to the heading the turtle has acquired after exiting the while block, this means that in this way the turtle is forced outside the loop:
to move
let last-patch patch-at-heading-and-distance (heading) (-1)
set target min-one-of patches with [pcolor = green] [distance myself]
face target
while [[pcolor] of patch-ahead 1 = gray] [
set heading new-direction
]
ifelse (patch-ahead 1 = last-patch)
[forward -1]
[forward 1]
end
Note that this solution is improvable: it works in your scenario but it may not be sufficient with more complicated designs of the hall and walls.
You run "move" in which the turtles face a direction, then move.
Then you run "avoid" in which the turtles look for gray and turn.
So your turtles have already moved before they look for gray.
My advice: aim, then correct, then move. Note that this very simple navigation rule will not move like a person would move.
to aim
;; face nearest green patch
face min-one-of patches with [pcolor = green ] [distance myself ]
end
to correct
;;if about to step on a gray patch, turn away from it
if ([ pcolor ] of patch-ahead .1 = gray)
[ ;; where is the center of the next patch?
let towards-patch-center towards patch-ahead .1
;; calculate a direction away from the center of the patch
let diff subtract-headings towards-patch-center heading
;; turn left (CCW) or right (CW)
if (diff >= 0 ) ;; it's ahead or clockwise
[ set heading heading - 1 ] ;; turn counter-clockwise
if (diff < 0 ) ;; its counter-clockwise
[ set heading heading + 1 ] ;; turn clockwise
]
end
to walk
jump .1
end
to navigate
aim
correct
walk
end
I write a code that evacuates turtles to the only exit door. But as I noticed that the turtles are divided into several groups. There are turtles that walk toward the exit door and the others walk to the nearest wall. I want to create a simulation that all the turtles will go to the exit doors. Here's my code. Can anyone advise, please?
globals [
;wall
door
goal-x goal-y
n
]
patches-own [ path? ]
turtles-own [
direction
fast?
other-nearby
]
to setup
clear-all
setup-patches
set-default-shape turtles "person"
ask n-of number-room1 patches with [pxcor < 47 and pxcor > 0 and pycor < 45 and pycor > 0 and pcolor = black]
[
sprout 1 [
facexy 41 45
set direction 1
set color yellow
]
]
reset-ticks
end
to setup-patches
draw-wall
draw-exit
ask patch 21 41 [
set plabel-color white
set plabel "Room1"
]
end
to draw-wall
ask patches with [pxcor <= 38 and pxcor >= 0 and pycor = 45]
[set pcolor blue]
ask patches with [pxcor <= 47 and pxcor >= 44 and pycor = 45]
[set pcolor blue]
ask patches with [pxcor <= 47 and pxcor >= 0 and pycor = 0]
[set pcolor blue]
ask patches with [pxcor = 0 and pycor <= 45 and pycor >= 0]
[set pcolor blue]
ask patches with [pxcor = 47 and pycor <= 45 and pycor >= 0]
[set pcolor blue]
end
to draw-exit
ask patches with [pxcor <= 43 and pxcor >= 39 and pycor = 45]
[set pcolor green]
end
to go
if ticks >= 100 [stop]
ask turtles [walk]
tick
end
to walk
let room1 patches with [pxcor < 47 and pxcor > 0 and pycor < 45 and pycor > 0]
;let exitpoint patches with [pxcor < 46 and pxcor > 33 and pycor < 45 and pycor > 32]
ask turtles-on room1
[face one-of patches with [pxcor <= 43 and pxcor >= 39 and pycor = 47]
fd 0.01
]
;ask turtles-on exitpoint
;[face one-of patches with [pxcor <= 42 and pxcor >= 38 and pycor = 47]
; fd 0.01
;]
end
You can try these 2 steps to make it work:
Check the setting of your simulation (besides the simulation speed slider on the top right side), make sure to uncheck world wrap horizontally & world wrap vertically. If it is still checked, it means that the turtles can go beyond your vertical/horizontal boundary and appear on the other side. That's why some group of turtles is moving towards the wall, they assume they can pass the boundary and arrive at the exit, while they will be stuck there because of your code constraint.
After making sure that the setting is okay, if you still have some of them stuck in the upper side of the wall near the exit, you can try to replace your to walk code with this:
to walk
set heading towards one-of patches with [pcolor = green]
fd 1
end
Hopefully, this will help you solve the problem
I'm writing code to make a race between 5 turtles. I have to show who wins the race through the use of ticks. I think I can use the ticks to count how much time it takes each turtle to move then compare them. However, I can't figure out where to put the "tick" in my code. Here's my code:
to finish
ask patches
;sets finish line pattern
[ifelse (pxcor + pycor) mod 2 = 0
;if true do this
[set pcolor pink]
;if false do this
[set pcolor yellow]
]
ask patches
;sets background black other than the finish line
[if pxcor < 12 [set pcolor black]
]
end
to lanes
ask patches
;sets the lanes
[ if pycor = 3 and pxcor < 12 [set pcolor white]
if pycor = 9 and pxcor < 12 [set pcolor white]
if pycor = -3 and pxcor < 12 [set pcolor white]
if pycor = -9 and pxcor < 12 [set pcolor white] ]
;setup for the turtle positions
cro 5
ask turtle 0 [setxy -15 0]
ask turtle 1 [setxy -15 6]
ask turtle 2 [setxy -15 12]
ask turtle 3 [setxy -15 -6]
ask turtle 4 [setxy -15 -12]
ask turtles [set heading 90] ;set heading 90 means moving the head of the turtle right 90 degrees
reset-ticks
end
to setup
finish
lanes
end
to movecars
every .1
[fd random 10 / 10]
end
to endrace
movecars
if xcor >= 12 [die]
end
to go
endrace
end
Almost always, tick goes as the last command in the go procedure. Certainly that's what you should be doing while you are new to NetLogo. Having said that, it won't make your code work.
Think of ticks as a time step counter. Each loop through the go procedure should do all the actions that need one time step to do and also advances the time step counter. So you don't need the every command, you just have the movecars procedure called by the go procedure and have ask turtles [forward random 10 / 10] in the movecars procedure.
This is a fairly fundamental conceptual gap and I suggest you look through some of the models in the NetLogo models library, focusing on the link between the go procedure and the moving procedure and the passage of time. Or perhaps do the tutorials again. Also, start your model more simply. Just create one car and get it to move, then worry about multiple cars, colours and seeing who wins. Add a little piece of your model and make it work before adding the next piece.
Try this:
to go
movecars
endrace
tick
end
to movecars
ask turtles [ fd random 10 / 10]
end
to endrace
ask turtles [ if xcor >= 12 [die] ]
end
I want to make diagonal bases (Perfet square), but it only work until size 2 more then 2 i start to lose the squares.
My code is:
to setup-patches
set-patch-size 15
ask patches[
if (distancexy 20 20) < base-size [set pcolor yellow]
if (distancexy -20 -20) < base-size [set pcolor yellow]
if (distancexy -20 20) < base-size [set pcolor pink]
if (distancexy 20 -20) < base-size [set pcolor pink]
]
end
Please check the picture to see what i am talking about.
Look at two examples in the Models Library: Moore and Von Neumann, and Neighborhoods Example. You want the box (Moore) neighborhood, and you should use at-points to get it. However, sticking close to your coded setup, you can also try this:
to-report linf [#p1 #p2]
let _xdist abs ([pxcor] of #p1 - [pxcor] of #p2)
let _ydist abs ([pycor] of #p1 - [pycor] of #p2)
report max (list _xdist _ydist)
end
to setup-patches [base-size]
clear-all
set-patch-size 15
let diag1 (patch-set patch 20 20 patch -20 -20)
ask diag1 [ask patches with [linf self myself < base-size] [set pcolor yellow]]
let diag2 (patch-set patch -20 20 patch 20 -20)
ask diag2 [ask patches with [linf self myself < base-size] [set pcolor pink]]
end