turtles-own [lost inside my-xcor my-ycor historyx historyy bad-move] ; variable to store if a particular turtle is lost globals [rand-list rand-list-nozero inside-move found] ; Called when user clicks on the setup button to setup ca set rand-list [-1 -0.5 0 0.5 1] ; initializes the list of random numbers (used for creating error) set rand-list-nozero [-0.5 -0.25 0.25 0.5] set inside-move [1 0 0 0 0 0 0 0 0 0] ; set-default-shape turtles "circle" create-n-turtles num-turtles ;*************************************************************************************** ; Uncomment the following lines to see the shape they are conforming to ;*************************************************************************************** ask patches [ ; this series of if statements set up the vertical rectangles ;if ((pxcor <= -12) and (pxcor >= -15)) and ((pycor <= 15) and (pycor >= -15)) ;[ set pcolor gray ] ;if ((pxcor >= 12) and (pxcor <= 15)) and ((pycor <= 15) and (pycor >= -15)) ;[ set pcolor gray ] ;if ((pxcor <= -3) and (pxcor >= -6)) and ((pycor <= 15) and (pycor >= -15)) ;[ set pcolor gray ] ;if ((pxcor >= 3) and (pxcor <= 6)) and ((pycor <= 15) and (pycor >= -15)) ;[ set pcolor gray ] ; this series of if statements set up the horizontal rectangles ;if ((pycor <= -12) and (pycor >= -15)) and ((pxcor <= 15) and (pxcor >= -15)) ;[ set pcolor gray ] ;if ((pycor >= 12) and (pycor <= 15)) and ((pxcor <= 15) and (pxcor >= -15)) ;[ set pcolor gray ] ;if ((pycor <= -3) and (pycor >= -6)) and ((pxcor <= 15) and (pxcor >= -15)) ;[ set pcolor gray ] ;if ((pycor >= 3) and (pycor <= 6)) and ((pxcor <= 15) and (pxcor >= -15)) ;[ set pcolor gray ] ] end ; Actually sets up the initial locations of the turtles to create-n-turtles [n] locals [t1 t2 t3 the-neighbors] create-custom-turtles n [ setxy ((random screen-size-x) - screen-edge-x) ((random screen-size-y) - screen-edge-y) set found (list 0) set heading random 360 set lost true set inside false set color red set bad-move false set shape "square" set my-xcor (xcor + random-one-of rand-list-nozero) set my-ycor (ycor + random-one-of rand-list-nozero) set historyx (list my-xcor) set historyy (list my-ycor) ;************************************************************************************ ; When turtle is first created, try to look for neighbors and triangulate position ;************************************************************************************ set the-neighbors find-neighbors ; get an agentset of 3 nearby turtles if(count the-neighbors = 3) ; if we actually have 3 nearby neighbors... [ let id-neighbors values-from the-neighbors [who] ; get the id's of the turtle neighbors set t1 (distance-nowrap (turtle (first id-neighbors)) + random-one-of rand-list) ; get the distance (approx) to each neighbor set t1 (distance-nowrap (turtle (item 1 id-neighbors)) + random-one-of rand-list) set t1 (distance-nowrap (turtle (last id-neighbors)) + random-one-of rand-list) ;********************************************************************************* ; Do the following for all 3 neighbors: ; - Find the distance between the neighbors ; - Find the angle between 2 of the neighbors and the current agent ; - Find the x offset using sin(angle) to one neighbor ; - Find the y offset using sin(angle) to other neighbor set lost false ] ] end ; Updates the locations of the turtles to update if(count turtles < num-turtles) [ create-n-turtles num-turtles - count turtles ] while [count turtles > num-turtles] [ ask random-one-of turtles [die] ] ask turtles [without-interruption [move]] end ; Moves the turtles (does all the actual work for turtle movement) to move locals [g cx cy the-neighbors newx newy] ; now, to move one step in the gradient you just have to set the-neighbors find-neighbors set g get-gradient the-neighbors set my-xcor (xcor + first g + random-one-of rand-list-nozero) set my-ycor (ycor + last g + random-one-of rand-list-nozero) set historyx fput my-xcor historyx ; add latest x location to front of the list if (length historyx > 8) [ set historyx remove (last historyx) historyx ] ; remove oldest x location from the list set historyy fput my-ycor historyy ; add latest y location to front of the list if (length historyy > 8) [ set historyy remove (last historyy) historyy ] ; remove oldest y location from the list set newx (xcor + first g) set newy (ycor + last g) set bad-move true ; bad-move is when an agent inside the shape tries to move outside the shape ; this series of if statements set up when the agent is in a vertical rectangle if ((my-xcor <= -12) and (my-xcor >= -15)) and ((my-ycor <= 15) and (my-ycor >= -15)) [ set inside true set bad-move false ] if ((my-xcor >= 12) and (my-xcor <= 15)) and ((my-ycor <= 15) and (my-ycor >= -15)) [ set inside true set bad-move false ] if ((my-xcor <= -3) and (my-xcor >= -6)) and ((my-ycor <= 15) and (my-ycor >= -15)) [ set inside true set bad-move false ] if ((my-xcor >= 3) and (my-xcor <= 6)) and ((my-ycor <= 15) and (my-ycor >= -15)) [ set inside true set bad-move false ] ; this series of if statements set up when the agent is in a horizontal rectangle if ((my-ycor <= -12) and (my-ycor >= -15)) and ((my-xcor <= 15) and (my-xcor >= -15)) [ set inside true set bad-move false ] if ((my-ycor >= 12) and (my-ycor <= 15)) and ((my-xcor <= 15) and (my-xcor >= -15)) [ set inside true set bad-move false ] if ((my-ycor <= -3) and (my-ycor >= -6)) and ((my-xcor <= 15) and (my-xcor >= -15)) [ set inside true set bad-move false ] if ((my-ycor >= 3) and (my-ycor <= 6)) and ((my-xcor <= 15) and (my-xcor >= -15)) [ set inside true set bad-move false ] ifelse (inside = true) [ ifelse (bad-move = false) [ set color blue setxy newx newy ] [ let rand-move random-one-of inside-move if(rand-move = 1) [ let offset random-one-of [-.1 -0.5 0.5 .1] setxy (xcor + offset) (ycor + offset) ] ] ] [ setxy newx newy ] ; setxy (xcor + first g) (ycor + last g) display end ; Returns a list of 3 neighbors to-report find-neighbors locals [near tnear rand sensor neighbor t-here th-id isin] ; declare some local variables set sensor 1 ; sets sensor radius initially to 1 set rand 0; ; set rand random-one-of rand-list ; get a random offset from the list set tnear turtles in-radius-nowrap (sensor + rand) ; find all turtles within a certain radius while[(count tnear) < 5] ; while the turtle can't find 3 neighbors [ set sensor (sensor + 1) ; increment sensor radius by 1 ; set rand random-one-of rand-list ; get a random offset from the list if(sensor >= 25) [report tnear] ; if the sensor tries to go too far, just exit b/c it's not going to find more agents set tnear turtles in-radius-nowrap (sensor + rand) ; find all turtles within a certain radius ] ;set t-here turtles-here ;set th-id values-from t-here [who] ;set isin false if ((count tnear) >= 5) ; if turtle has 5 or more neighbors, prune to 3 neighbors (not including self) [ set neighbor (random-n-of 3 tnear) set near values-from neighbor [who] ; foreach th-id [ if(member? ?1 near) [ set isin true ] ] ; while[isin = true] while[member? who near] [ set neighbor (random-n-of 3 tnear) set near values-from neighbor [who] ;foreach th-id[ if(member? ? near) [ set isin true ] ] ] ] ; show near ; set lost false ; show neighbor report neighbor end ;*********************************************************************************************** ; If an agent is lost, uses data from nearby neighbors to triangulate it's own position to find-turtle locals [near tnear rand] ; declare some local variables set rand random-one-of rand-list ; get a random offset from the list set tnear turtles in-radius-nowrap (6 + rand) ; find all turtles within a certain radius set near values-from tnear [who] ; get id's of these turtles set near remove who near ; remove self from the list if (length near) < 3 ; if turtle doesn't find 3 neighbors, exit procedure and continue [ stop ] while [(length near) > 3] ; if turtle has more than 3 neighbors, prune to 3 neighbors [ set near remove (random-one-of near) near ] ; set lost false ; show near end ;************************************************************************************************** ; Displaces a large number of the turtles a random distance away from the original shape to shake locals [x1 x2 y1 y2] set x1 random screen-edge-x set x2 (x1 - abs((random 5) + 10)) set y1 random screen-edge-y set y2 (y1 - abs((random 5) + 10)) ask turtles [ if (xcor <= x1) and (xcor >= x2) and (ycor <= y1) and (ycor >= y2) [ set lost true set inside false set color green setxy (xcor + (random 5) - 10) (ycor + (random 5) - 10) ] ] end ;turtle function ; if other-node is a distance of more than d away from my perceived coordinates ; (where I think I am: my-xcor my-ycor) ; then report the unit vector which points towards other-node ; if other-node is a distance of less than d ; then report the unit vector which points away from other-node ; else report (0 0) to-report get-unit-vector-towards [other-node] without-interruption [ no-display ;turn display off to hide the jump back and forth. let d distance-nowrap other-node ;the real distance to other-node let tx xcor ;save my coordinates let ty ycor setxy my-xcor my-ycor ;temporarily place myself where I think I am. set heading towards-nowrap other-node ifelse (distance other-node > d) [ report (list dx dy) ][ ifelse (distance other-node < d)[ set heading heading + 180 report (list dx dy) ][ report (list 0 0) ] ] ; the following 2 lines are useless because they will never get executed setxy tx ty ;put me back where I really am display ] end ;turtle function ;reports a unit vector that is the gradient (step 2 in the algorithm) for this ; turtle given the-neighbors. ;the-neighbors is the list of neighbors to-report get-gradient [the-neighbors] let vector reduce [(list ((first ?1) + (first ?2)) ((last ?1) + (last ?2)))] values-from the-neighbors [get-unit-vector-towards myself] let magnitude sqrt ((first vector) * (first vector) + (item 1 vector) * (item 1 vector)) if (magnitude = 0) [ report (list 0 0) ] report (list (first vector / magnitude) (item 1 vector / magnitude)) end @#$#@#$#@ GRAPHICS-WINDOW 303 10 733 461 17 17 12.0 1 10 1 1 1 0 1 1 1 CC-WINDOW 5 475 742 570 Command Center 0 SLIDER 8 60 180 93 num-turtles num-turtles 0 2000 1006 1 1 NIL BUTTON 8 11 71 44 NIL setup NIL 1 T OBSERVER T NIL BUTTON 78 11 148 44 NIL update NIL 1 T OBSERVER T NIL BUTTON 155 11 225 44 NIL update T 1 T OBSERVER T NIL BUTTON 8 106 73 139 NIL shake NIL 1 T OBSERVER T NIL @#$#@#$#@ Title: Shapebugs Author: Matt Baker Description: This is an implementation of the Shapebugs algorithm from