Set different heading according to rules - range

What I want to do is to create agents that move randomly in NetLogo world so that it will be quite similar as in real world (since these agents are based on animals, so there shouldn't be any specific codes saying they need to do this or that, most living things move randomly.)
Here is what I plan, I will give a percentage on which direction they will choose, but mostly they will walk straight, here is how I plan it:
if percentage <= 85, heading should be in range 315 - 45
if percentage <= 90, heading should be in range 45 - 315
if percentage <= 95, heading should be in range 315 - 225
if percentage <= 100, heading should be in range 225 - 315
Here is image of what I plan to do, p = percentage,
(I am bad at explaining in words)
here is my code
to random-behave
let p random-float 100
if-else p <= 85
[ set heading heading + 45
set heading heading - 45]
[ if-else p <= 90
[ set heading heading + 45
set heading heading + 135]
[ if-else p <= 95
[ set heading heading + 135
set heading heading + 225]
[set heading heading + 225
set heading heading + 315]
]
]
if not can-move? 1 [ rt 180 ]
fd 1
end
I have some serious error while coding for heading since I don't know how to implement the range that I need.
And is there overlapping heading range happen if I used the one I mention above? Since 315 - 45, 45 - 135
Thank you in advance.

It might be helpful to explain in words what your code is doing- there are definitely some problems with your approach to headings here. For a breakdown of what the ifelse statements are being evaluated, have a look at the comments I've inserted into your version. You'll notice that you're adding or subtracting to a turtle heading multiple times in a single code chunk:
to random-behave-old
let p random-float 100
if-else p <= 85 [
; if p is less than or equal to 85,
; add 45 to heading, then subtract 45 from heading
set heading heading + 45
set heading heading - 45
] [
if-else p <= 90 [
; if p is greater than 85, but less than
; or equal to 90, add 45 to heading, then
; add another 135 to heading
set heading heading + 45
set heading heading + 135
] [
if-else p <= 95 [
; if p is greater than 90, but less than
; or equal to 95, add 135 to heading,
; then add 225 to heading
set heading heading + 135
set heading heading + 225
] [
; if p is greater than 95, add 225 to heading
; then add 315 to the heading.
set heading heading + 225
set heading heading + 315
]
]
]
if not can-move? 1 [ rt 180 ]
fd 1
end
Now, if I understand you correctly, you want your turtles to mostly move forward the direction they are facing, is that true? Or do you want them to mostly move towards heading 0 (more or less north in the NetLogo world). Assuming the former, have a look at this version of your code. Here, rather than adding to a heading, the turtles just use right-turn (rt) to change their heading.
to random-behave
let p random-float 100
if-else p <= 85 [
; if p is less than or equal to 85,
; right-turn a random value from -45 to 45
rt random 91 - 45
] [
if-else p <= 90 [
; if p is greater than 85, but less than
; or equal to 90, right-turn 90, then
; right-turn a further -45 to 45
rt 90 + random 91 - 45
print "Turning right!"
] [
if-else p <= 95 [
; if p is greater than 90, but less than
; or equal to 95, right-turn 180, then
; right-turn a further -45 to 45
rt 180 + random 91 - 45
print "Turning around!"
] [
; if p is greater than 95, right-turn 270, then
; right-turn a further -45 to 45
rt 270 + random 91 - 45
print "Turning left!"
]
]
]
if not can-move? 1 [ rt 180 ]
fd 1
end
If in fact you want them to move mostly a specific direction, you can modify the above. For example, to move mostly north, use something like set heading 0 + random 91 - 45; to move mostly east, something like set heading 90 + random 91 - 45.

Related

The in-radius works different in Netlogo 6.1.0 than in previous version

I have the following code which creates a grid of agents and place links between pairs if they are in a distance of interference.
breed [ readers reader ]
undirected-link-breed [ rris rri ]
globals [
interf-rri-radius
num-readers
distance-var-x
distance-var-y
readers-per-row
readers-per-column
num-checkouts
]
to setup
ca
setup-globals
ask patches [ set pcolor blue - 3 ]
spawn-by-row-col
reset-ticks
end
to setup-globals
set interf-rri-radius 1005
set num-readers 40
set distance-var-x 12
set distance-var-y 22
set readers-per-row 8
set readers-per-column 5
set num-checkouts 0
end
to spawn-by-row-col
let half-step 0.5 * distance-var-x
let d-vals ( range ( min-pxcor + half-step ) ( min-pxcor + (readers-per-row * distance-var-x)) distance-var-x )
let dc-vals ( range ( min-pxcor + half-step ) ( min-pycor + (readers-per-column * distance-var-y)) distance-var-y )
show dc-vals
; Create an empty list to build into
let possible-coords []
; For each possible vertical value, map all horizontal values in order and
; combine these into an ordered list starting at the lowest px and py coords
foreach dc-vals [
d ->
set possible-coords ( sentence possible-coords map [ i -> (list i d) ] d-vals )
]
show (word "possible-coords = " possible-coords)
; Use the number of readers to sublist the possible coordinates, and
; create a turtle at each of the coordinate combinations left.
let max-positions length possible-coords
if max-positions > (num-readers + num-checkouts) [ set max-positions (num-readers + num-checkouts) ]
let use-coords sublist possible-coords num-checkouts max-positions
foreach use-coords [
coords ->
create-readers 1 [
setxy item 0 coords item 1 coords
set shape "square 2"
set size 2
set color 15
]
]
ask readers [ create-rris-with other readers in-radius (interf-rri-radius / 10) ]
end
The neighbors of reader 0 are
show [sort [who] of rri-neighbors] of reader 0
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39]
However, the distance between reader 0 and reader 39 is
show [distance reader 0] of reader 39
121.6552506059644
and the connection radius is 1005/10= 100.5 so they should not be connected with an rri link.
Notice, I use a origin-centered world of -50 to 50 in X and Y dimensions.
I have tested the code in previous Netlogo version 6.0.4 and the reader 39 is not a neighbour of the reader 0.
I do not know what can be the problem. I believe is the new version but I would like to be sure.
In case anyone else runs into this, there is a confirmed bug with in-radius in the NetLogo 6.1.0 release, and the details are in the bug report on GitHub.
The issue only affects in-radius when used in a non-wrapped world, and only when used on turtles, and only when used with a radius that's a significant % of the world width. If you're using a world with wrapping, or using in-radius with patches, or using a small radius relative to the world size, your data will be correct and you don't need the below workaround.
As a workaround if your model is affected, you can use a simple user-defined NetLogo procedure in your model until the fix is published. It's not going to be super-fast if your having turtles calculate in-radius many times per tick, but if you have few turtles or are just using it during setup, it should be okay:
to-report temp-in-radius [agentset r]
report agentset with [ distance myself <= r ]
end
Then, instead of create-rris-with other readers in-radius (interf-rri-radius / 10) you would do create-rris-with (temp-in-radius other readers (interf-rri-radius / 10)).
Or more generally, instead of something like count other turtles in-radius 5 would become count temp-in-radius (other turtles) 5.

Draw a semicircle in Netlogo

I want to create a semicircle, the center of my semicircle is at the end of the world, for example I want that the center of my semicircle is in the 50,20 position, and goes from 20 to -20.
I try with this, but I got an exception:
The point [ 60 , 20 ] is outside of the boundaries of the world and
wrapping is not permitted in one or both directions.
to mysemicircle
let cx 50 ;; x coordinate of patch you want to circle
let cy 20 ;; y coordinate of patch you want to circle
let r 10 ;; radius of the circle you want
let p2r ( 2 * pi * r ) ;; get circumference of the circle
let step p2r / 360 ;; make step lengths 1/360th of the circumference
crt 1 [ ;; create a single drawing turtle
setxy cx + r cy ;; move it to the highlight patch + the radius
pd ;; put the pen down
set heading 0 ;; make it face along the tangent
while [ p2r > 0 ] [ ;; make the turtle continue to move until the circle is drawn
lt 1
fd step
set p2r p2r - step
set color white
]
]
end
And If i use cx 40 and cy 20 the circle is not from y -20 to y 20, but is only from y 0 to y 20.
How Can I do that?
Maybe a procedure with arguments would be better for this, something like:
to setup
ca
resize-world -20 20 -20 20
draw-semi-circle 0 0 15 45 blue
draw-semi-circle 5 5 5 270 red
draw-semi-circle -10 -10 8 135 green
reset-ticks
end
to draw-semi-circle [ x y r a col ]
; Give arguments for x, y, radius, and angle of the semicircle
let half-p ( pi * r )
let step half-p / 180
ask patch x y [
set pcolor col
]
crt 1 [
setxy x y
set heading a
lt 90
set color col
back r
pd
fd 2 * r
rt 90
while [ half-p > step ] [
rt 1
fd step
set half-p half-p - step
]
]
end
To get an output like:

Set probability range for heading in Netlogo

My problem consists of 2 things:
how to code 4 different range for heading
a. 315 - 45
b. 46 - 135
c. 136 - 225
d. 226- 314
2.how to code probability on choosing this range.
(I have attached image below to make it clear)
What I wish to do is:
a) for heading a; the probability of turtles choose any of this range should be 85%
b) for heading b,c, and b, there will be 5% of turtles choosing any side of this heading
Since I'm quite bad at explaining in words, I have attached image on what I plan to do
here is my code
to random-behave
let p random-float 100
if (p >= 85)
[set heading heading + 45
set heading heading - 45]
if (p >= 15)
[set heading other heading + 45
set heading other heading - 45]
if not can-move? 1 [ rt 180 ]
fd 1
]
end
I tried to implement rnd extension but I can't see where should I put it. And if possible, instead of if (p >=15), is there any way to code the heading according to its degree? Since other can't be use here.
Thank you in advance.
You don't need the rnd extension, your approach with random-float is fine. However, you need to use if-else rather than if because a returned random number 'p' that is >85 will also be >15. Instead, you need to break up the interval from 0 to 100 into pieces that are the appropriate length. This is not tested.
to random-behave
let p random-float 100
if-else p <= 85
[ print "got up to 85" ]
[ if-else p <= 90
[ print "got 85 to 90"]
[ if-else p <= 95
[ print "got 90 to 95" ]
[ print "got 95 to 100" ]
]
]
if not can-move? 1 [ rt 180 ]
fd 1
end
You also have errors in your heading calculation. I only answered the probability part since that's what you specifically asked. But you should ask a new question if you need help with your heading.

how to lineup the agents in the ascending or descending order of their who number in netlogo?

I am creating an patient-surgeon-operation bed model, wherein I need to show surgeons lined up on the left side of patch awaiting to enter operation room in the center and the patients awaiting in the queue from the right side.
I want the surgeons and patients to be located on the patch as per their who number
S1 S2 S3 --> Operation room < -- P1 P2 P3
I use the below query, I am not sure where to incorporate the who number
to lineup-patients
LET gapp 10
LET directions
[45 90 230 180 45 90 230 180 45 90 45 90 230 180 45 90 230 180 45 90 45 90 ]
LET jj 0 ; counter / index
REPEAT initial-number-patients
[ create-PATIENTS 1
[ SETXY (0 + jj * gapp) 20
set shape "person"
SET size 1.2
SET label who
SET label-color black
SET heading item jj directions
]
SET jj jj + 1
ASK patients [
MOVE-TO ONE-OF PATCHES WITH [ PCOLOR = yellow ]
] ]
END
You have a move-to after you line them up. And it always moves all existing patients. To keep things cleaner, write a separate lineup proc.
to lineup [#patients #patch #gap]
let _x ([pxcor] of #patch)
let _y ([pycor] of #patch)
let _xqs n-values (count #patients) [[n] -> _x + n * #gap]
(foreach sort #patients _xqs [
[p x] -> ask p [setxy x _y]
])
end
You can test this with a new instance of NetLogo as follows:
to test
ca
crt 20
lineup turtles one-of patches 0.5
end

Netlogo: how to round heading into 90 180 270 360 only

I am currently building a model for people walking on a certain path (road patches, color = white). The agents' movement will only be limited on the white patch and when they encounter black patch they will rotate 180 deg.
The problem I found was when I tried to set the heading of the agents. I want the heading to walk to the nearest red patch (destination), but when I use:
1
set heading towards min-one-of patches with [pcolor = red ] [ distance myself ] <
the agents wont move from their patch. It turned out that the "heading" generated by the above code has the value of -360 to 360 with decimals in it. The walking procedure that I have built only allows heading with multiplies of 90 (-360, -180 ... 90, 180, 270, 360). This is the full code for my walking procedure:
2
globals [ flagl flagr ]
ask agents [
;reset flag
set flagr 0
set flagl 0
; check and note if there is a path on the left or the right
ask patch-left-and-ahead 90 1 [if (pcolor = white ) [set flagl 1]]
ask patch-right-and-ahead 90 1 [if (pcolor = white ) [set flagr 1]
]
;in T-junction, decide to turn left or right (random)
if((flagl = 1) and (flagr = 1))
[
ifelse random 100 > 50
[set heading heading - 90]
[set heading heading + 90]
]
;if it's only applicable to turn right, then turn right
if((flagl = 0) and (flagr = 1)) [set heading heading + 90]
;if it's only applicable to turn left, then turn right
if((flagl = 1) and (flagr = 0)) [set heading heading - 90]
;return if there's no mor path
if [pcolor] of patch-at-heading-and-distance heading 1 = black [rt 180]
;agent movement
**;face min-one-of patches with [pcolor = red ] [ distance myself ]**
fd 1
;stopping procedure
if [pcolor] of patch-here = red [fd 0]
]]
I tried to round the heading generated by #1 like this:
let direction heading towards min-one-of patches with [pcolor = red ] [ distance myself ]
if direction != mod 90
set direction 90 * round(arah/ 90)
However it gives error notice since "let" command cannot take that kind of input.
This is the screenshot of the map I have built:
Map
Any help to solve this problem is hugely appreciated. Thank you!
This might get you started- with minimal checking it seems to do the trick, but you will probably want to check for exceptions.
The cardinal-4 reporter takes whatever input is given and checks if the modulo is equal to 0. If not, it will check if modulo is less than/equal to 45- if so, subtracts that value from the direction (dir). If modulo is greater than 45, the subtract the modulo from the direction and add 90.
The check procedure just prints the reporter output for the values listed.
to setup
ca
reset-ticks
end
to-report cardinal-4 [ heading-input ]
let dir heading-input
let remain dir mod 90
if remain != 0 [
ifelse remain <= 45 [
set dir dir - remain
]
[
set dir dir - remain + 90
]
]
report dir
end
Edit: improved check procedure:
to check
let testVals [ -361 -359 -271 -269 -181 -179 -91 -89 -1 0 1 89 91 179 181 269 271 359 360 361 ]
print map [ i -> ( word i " becomes " cardinal-4 i "\n" ) ] testVals
end