Netlogo is honestly very weird for me, but I've been trying to make Space Invaders for a project. I need to be able to check the distance between multiple turtles of the same breed in order to run a collision check. How do I do this?
to shoot
ask turtle 0 [
hatch 1
[
set shape "dot"
set size 2
set color red
set ctrl "projectile"
set xcor [xcor] of turtle 0
set ycor [ycor] of turtle 0 + 2
repeat 40
[
ifelse ycor < 15 and distancexy [xcor] of turtle 1 [ycor] of turtle 1 > 0.5
[
set ycor ycor + 1
]
[
ifelse distancexy [xcor] of turtle 1 [ycor] of turtle 1 < 0.5
[
ask turtle 1 [die]die][die]
]
wait .01
]
]
]
end
So you want something like a 'hero' turtle to shoot all the turtles within some distance. I have modified your code a little but the basic idea is sound. You didn't really have a step for identifying the targets. I also simplified the movement by using face and used a while because there is no guarantee it will take 40 steps to get to the target.
to shoot
let shooter turtle 0 ; or however the shooter is selected
ask shooter
[ let targets other turtles with [distance myself < 0.5 ; finds the targets
if any? targets
[ let this-target one-of targets
face this-target ; so shooter is facing the target so trail better
; do the shooting
[ hatch 1
[ set shape "dot"
set size 2
set color red
set ctrl "projectile"
let step-distance 0.02
while distance this-target > step-distance
[ face this-target ; you don't need to worry about coordinates
forward step-distance
wait .01
]
die ; once close enough, projectile dies
]
ask this-target [ die ] ; and kills the target
]
]
]
end
This code is completely untested and needs another loop to get all the targets. Usually you don't use loops much in NetLogo, but an ask would change this into the perspective of the target rather than the shooter.
Related
I am doing boarding processes model with anti-Covid measures. I would like to know if any of you could help me.
I would like to enforce that the minimum distance between turtles will be 4 patches.
I would like to identify if there is an interference, that is, that a previous turtle occupies a seat that prevents a new agent from passing through.
I don't know how to insert this in my code:
to go
; stop when all the pessengers have found a seat
if not any? turtles with [seated? = false]
[stop]
set counter counter + 1
(foreach (sort turtles with [seated? = false] ) [a ->
ask a [
; check if we have reached the correct row of seats
ifelse [seat-row] of patch-at 1 -1 = assigned-seat-row
[
; only seat the passenger if he/she has stored the luggage OR if we don't take luggages into account
ifelse luggage-store-ticks = 0 or storing-luggage-takes-time = false
[
let seat patch-at 1 -1
set xcor [pxcor] of seat
set ycor assigned-seat-number
set seated? true
]
[
set luggage-store-ticks luggage-store-ticks - 1
]
]
[
let passenger-ahead one-of turtles-on patch-ahead 1
ifelse passenger-ahead != nobody
[
set speed [speed] of passenger-ahead
if xcor != airplane-door-x-cor
[fd speed]
]
[
set speed default-speed
fd speed
]
]
]
])
end
You could extend your existing patch-ahead 1 to also look at the patches 2, 3 and 4 ahead. But I think it would be easiest to use in-cone 5 10 or similar. That will look ahead in a cone shape, 10 degrees on either side of the heading and a distance of 5. So you could do something like:
let potential-blockers turtles in-cone 5 10
let blocker min-one-of potential-blockers [distance myself]
That should (not tested) find the closest turtle approximately in front and name it "blocker" so that you can do things like check if it's far enough away, match speed (see the basic traffic model in the NetLogo models library)
I am teaching myself how to create ABMs in Netlogo using the book of Railsback & Grimm 2012. I am having trouble with one book exercise which is on butterflies following "virtual" corridors. Basic idea is that butterflies go uphill for mating using the differences in height as guide. I need to calculate the width of the corridors dividing the number of patches used by the butterflies over the average distance the butterflies fly from the start patch to the end patch. I am
struggling with plotting this corridor width, which I am coding like this:
to-report corridor-width
let patches-visited count patches with [used?]
let mean-distance mean [distance start-patch] of turtles
report patches-visited / mean-distance
I then created a plot in the interface with the command:
plot corridor-width
The error message I get reads:
Division by zero. error while observer running / called by procedure
CORRIDOR-WIDTH called by plot 'Corridor width' pen 'default' update
code called by procedure SETUP called by Button 'setup'
I believe there is something wrong with the way I am coding distance start-patch but I have surfed the web and looked at several codes and I cannot spot my mistake. My whole code looks like this:
globals [ q ] ;; q is the probability that butterfly moves directly to highest patch
turtles-own [ start-patch ]
patches-own [ elevation used? ] ;; patches property of elevation and whether the patch has been used by butterfly or not.
to setup
ca
;; Let's create patches and asign them an elevation and color by using ask patches statement
ask patches
[
;; Elevation decreases linearly with distance from the center of hills. Hills are at (30,30) and
;; (120,120) coordinates. The first hill is 100 units high whereas the second one is 50
let elev1 100 - distancexy 30 30
let elev2 50 - distancexy 120 100
ifelse elev1 > elev2
[ set elevation elev1 ]
[ set elevation elev2 ]
set pcolor scale-color green elevation 0 100
set used? false
]
;; Create 50 butterflies
crt 50
ask turtles [
set size 6
;; set their initial location as their initial patch
setxy random-pxcor random-pycor
set start-patch patch-here
;; have the butterfly draw its path with the pen-down statement
pen-down
]
reset-ticks
;; Initialize the q parameter
set q 0.4
end
;; The master schedule
to go
ask turtles [ move ]
plot corridor-width
tick
if ticks >= 1000
[
let final-corridor-width corridor-width
write "Corridor width: " print final-corridor-width
;export-plot "Corridor width" (word "Corridor-width-output-for-q-" q ".csv")
stop
]
end
;; let's code the butterfly procedure of movement
to move
if elevation >=
[ elevation ] of max-one-of neighbors [ elevation ]
[ stop ]
ifelse random-float 1 < q ;; Decide whether to move to the highest sorrounding
;; patch with p=q
[ uphill elevation ] ;; move deterministically uphill
[ move-to one-of neighbors ] ;; or move randomly
set used? true
end
to-report corridor-width
let patches-visited count patches with [used?]
let mean-distance mean [distance start-patch] of turtles
report patches-visited / mean-distance
end
What happens when the mean-distance is 0?
let mean-distance mean [distance start-patch] of turtles
Essentially, in your setup, you set all the turtle's start-patch to their current patch. So, if you ask all the turtles how far away they are from their start patch, they will all tell you 0 units away.
So, [distance start-patch] of turtles is filled with a list of all 0's.
Thus, a mean of a list of all 0s is 0 causing your divide by 0 error.
Maybe in this situation, you want to report 0 instead...so
ifelse mean-distance = 0
[ report 0]
[report patches-visited / mean-distance]
If any one please give some time.
I have an area(say a colony) with boundary wall as black patches and at some point within the boundary there is one building with building wall as blue patches. People(breed) are normally moving inside boundary and the building as well. Also they are entering and going out of the boundary. Due to some reason (suppose rumor) and after certain condition (if more than 15 person hears the rumor) they starts moving randomly with any of the headings 0, 90, 180 and 270. So, the problem I am unable is, to apply check on the turtles(people) randomly moving to change their heading or turn back if they sense the boundary or wall a patch ahead.
I tried following ways but not working, they simple passes form these patches
1) Asked the turtles if heard-rumor? and times-heard > 1 [
if [pcolor] of patch-ahead 1 = blue [set heading [heading] of self - 180]
if [pcolor] of patch-ahead 1 = black [set heading [heading] of self - 180] ]
2) set patches with boundary-wall [set pcolor black] and building-wall [set pcolor blue] and then set patch variables boundary-wall? And building-wall? true on these patches. Further asked the turtles
if heard-rumor? and times-heard > 1 [
if boundary-wall? or building-wall? [ set heading [heading] of self - 180 ] ]
The procedure sequence is
to go
ask people [ ;breed
fd speed
spread-rumor
people-wander ]
end
So after spread-rumor function,
to people-wander
if heard-rumor? and times-heard > 1 and inside-boundary?
[
if people-heard-rumor > 10 [ set heading one-of (list 0 90 180 270) ] ];random 360
;people-heard-rumor is a count how many have received rumor
if heard-rumor? or fear-worst? [
; if [pcolor] of patch-ahead 1 = blue [set heading [heading] of self - 180]]
; if [pcolor] of patch-ahead 1 = black [set heading [heading] of self - 180]]
boundary-wall? or temple-wall? [set i? true set heading [heading] of self - 180 show 5] ]
end
I don’t know what wrong I am doing. But surely I am not using proper way. Any help is deeply thankful.
You start out with fd speed so your people will go right through the barriers on that command without ever testing for a barrier. Note that even if you were to test 1 patch ahead before doing that, if speed can be greater than 1, you could still go right through the barriers. Furthermore, in a corner a person might have a barrier both in front of it and behind it, so reversing course can also be a problem.
Btw, [heading] of self is the same as heading, and to turn around it is more natural to say rt 180.
EDIT (in response to comment):
Here is a simple example of moving step by step, checking along the way:
to fd-with-checks [#speed]
repeat #speed [
ifelse (isbarrier? patch-ahead 1) [
stop
] [
fd 1
]
]
end
to-report isbarrier? [#patch]
report pcolor = blue or pcolor = black
end
to setup
ca
reset-ticks
ask patches [
set inside? (abs pycor < 10 and abs pxcor < 10)
set exit? false
ask patch 11 0 [ set pcolor lime set exit? true]
]
repeat initial-population [ ; start condition turtles with any other turtles on neighbors
ask one-of patches with [
inside? and (not any? other turtles-here) and (not any? turtles-on neighbors)] [
sprout 1 [
set color blue
set size 1
]]]
end
to go
tick
define-neighbors-radius-2
move
end
to define-neighbors-radius-2
ask turtles [
set neighbors-ahead2 patches at-points [[2 1] [2 0] [2 -1]]
set neighbors-for-y-up2 patches at-points [[2 0] [2 -1] [1 -2] [0 -2] [-1 -2]] with [inside?]
set neighbors-for-y-down2 patches at-points [[-1 2] [0 2] [1 2] [2 1] [2 0]] with [inside?]
]
end
to move
;; my intent to move turtles to exit without their neighbors are occupied by other turtles, ;;that is the 8 patches around turtles are empty until exit?
ask turtles[
ifelse inside? [
if ycor = 0 [ ;strategy to turtles with in front exit
ifelse exit? [
set heading 90
fd .5
]
[
facexy 11 0
if (not any? turtles-on neighbors) and (not any? turtles-on neighbors-ahead2) [
fd .5
]
]
]
if ycor > 0 [ ; strategy to turtles occupied "bottom-side" of inside?
facexy 11 0
if (not any? turtles-on neighbors) and (not any? turtles-on neighbors-for-y-up2) [
fd .5
]
]
if ycor < 0 [ ; strategy to turtles occupied "down-side" of inside?
facexy 11 0
if (not any? turtles-on neighbors) and (not any? turtles-on neighbors-for-y-down2) [
fd .5
]
]
]
[
set heading 90
fd .5
]
]
end
I try to move turtles to exit but not all turtles move, why?
also, turtles must go out with ycor = 0, that is obliques direction don't allow because neighbors will occupied patches aren't inside!
Can't public this question because "looks like my post is mostly code", so talk about of my life:
seriously my intent is to create a crowd in front of exit and set some rules to delay the turtles flow exit, for this I need the neighbors empty to show interaction between agents.
(also accept some suggest to set this interaction) but at the moment turtles reach exit!
thanks
One problem with this code is that have you three ifs where it appears you only want one of them to run each time, but it's possible for more than one of them to trigger. You have:
if ycor = 0 [ ...commands #1... ]
if ycor > 0 [ ...commands #2... ]
if ycor < 0 [ ...commands #3... ]
but the turtle's ycor might be changed by commands #1 or #2. So it's possible that both #1 and #2 might run, or both #2 and #3, and perhaps other combinations as well. I assume you intended that each turtle should only move once per tick, so I recommend you rewrite this as:
ifelse ycor = 0
[ ...commands #1... ]
[ ifelse ycor > 0
[ ...commands #2... ]
[ ...commands #3... ] ]
Something else that should be fixed in this code:
reset-ticks should go at the end of setup, not near the start. It tells NetLogo setup is finished.
tick should go at the end of go, not near the start. It tells NetLogo a tick has finished.
I don't know if either of these problems I've pointed out are actually causing the unintended behavior you're seeing. Perhaps the bug isn't obvious just from reading over the code. In that case, you have two possible courses of action ahead of you:
1) Back up. Throw away this broken code and go back to the last version of your model that contained only code that have you have verified to work correctly. Then try again, but this time, don't add so much new code all at once. Attempt to make a very small improvement to the code, and get that working, before moving on to the next small improvement. And so on. If at any point you get stuck, come here, show your code, and ask a specific question about it. That question should be much easier to answer than your current question. Questions of the form “Here is a big mass of code that doesn't work, help!" are very difficult to answer.
2) Press on by investigating your questions yourself. You write, “not all turtles move, why?” Perhaps someone can answer this just by reading your code; I can't (unless my first guess above is correct). In order to figure it out, I would have to run the code myself and do experiments with it. I'd do things like try running it with just a single turtle and see if that case fails; add print statements to the code, showing each the turtle's coordinates and motions, so I could try and figure out which turtle is going wrong, and exactly under what conditions; and so forth. It's like detective work, or like doing chemistry experiments in the lab.
I've made a model that aranges factions (turtles in different colours) in a circle.
At the moment they arrange randomly, was wondering if someone could help me arrange them so, for example, red occupies the first 90 degrees, blue the next 90 degrees, etc (on setup).
Here's my code...
ask patch 0 0
[ ask patches in-radius ( max-pxcor * .9) with [ random-float 100 < density ]
[ sprout 1
[ set breed cons
set shape "circle"
set faction random factions
set heading random 360
set size 1
]
]
]
.. guessing I will have to do 360 / fractions, but not sure how to phrase it, if someone could help me out that'd be great. Thanks!
The NetLogo primitive that's the closest to what you want to do is in-cone, which reports the set of turtles that are in the "cone of vision" of another turtle. But your "pie slices" should just be relative to patch 0 0, not to another turtle! No problem: just make a temporary turtle at patch 0 0, use it to get turtles in-cone with the appropriate angle, and kill your temporary turtle.
The following procedure can be used "as is" with your code (just call it from your setup procedure after creating your turtles exactly as you were doing before):
to assign-factions
let angle 360 / factions
foreach n-values factions [?] [
ask patch 0 0 [
sprout 1 [
set heading ? * angle
ask turtles in-cone max-pxcor angle [ set faction ? + 1 ]
die
]
]
]
end
The code is pretty straightforward, except for maybe the more obscure n-values. You could replace it with a while loop if you prefer, but it's really just counting from 0 to factions.
Here is what you'd get with 5 factions: