;*************************** OBSERVER PROCEDURES ****************************** globals [aa bb Total-Free List-Ready? Occupied-List-Ready?] breeds [living working visiting1 visiting2] patches-own [Probability-Timer] to track-vacant loop[ set Total-Free (count-patches-with [pc = white and count-turtles-here = 0 ] ) output Total-Free] end to track-vacant-all ; here we generate a list called "aa" which tracks the vacant spots on the east sides of roads wait-until [List-Ready? = true] if List-Ready? = true [ set List-Ready? false set aa make-list 0 0 ask-patches [if pc = white and count-turtles-here = 0 [ let [:bb (list xcor ycor)] set aa insert 1 aa :bb ]] set List-Ready? true] ask-patches-with [pc = white] [ if (count-turtles-here = 0) [ setProbability-Timer 0] ] end to track-occupied-all ; here we generate a list called "bb" which tracks the ocupied spots for probabilitsic search wait-until [Occupied-List-Ready? = true] if Occupied-List-Ready? = true [ setOccupied-List-Ready? false set bb make-list 0 0 ask-patches [if pc = white and count-turtles-here > 0 [ let [:bb (list xcor ycor)] set bb insert 1 bb :bb ]] setOccupied-List-Ready? true] end to setup set-random-seed 100 set List-Ready? true setOccupied-List-Ready? true set aa make-list 0 0 set bb make-list 0 0 ct crt number-of-cars ask-turtles [setPark-Counter 0 setshape cross setc red setspeed 1 setSpeedLimit 1 if (who <= (number-of-cars / 5)) [setbreed living] if (who > (number-of-cars / 5) and who <= (number-of-cars / 2)) [setbreed working] if (who > (number-of-cars / 2) and who <= (number-of-cars / 1.25)) [setbreed visiting1] if (who > (number-of-cars / 1.25)) [setbreed visiting2] if breed = living [setParkTime 48] if breed = working [setParkTime 32] if breed = visiting1 [setParkTime 2] if breed = visiting2 [setParkTime 8] loop [ifelse ((pc-at 0 0) = black and count-turtles-here = 1 ) [stop] [ ifelse (random 2) = 0 [seth 0] [ifelse (random 2) = 0 [seth 90][ifelse (random 2) = 0 [seth 180] [seth 270]]] fd (int random 25) ifelse (random 2) = 0 [seth 0] [ifelse (random 2) = 0 [seth 90][ifelse (random 2) = 0 [seth 180] [seth 270]]] fd (int random 25) ]]] starttrackingall startcountaverage startoccupied-all end to count-steps-to-find-parking output (average-of-turtles-with [color = yellow] [steps-to-find-parking]) end to stop-it stoptrackingall stopcountaverage stopDrive&Park stopoccupied-all end to count-average ; this is for statistical analysis: paste these number into excel and calculate the mean, median and standard deviation show (round average-of-turtles-with [color = yellow] [steps-to-find-parking]) wait 1 end ;*************************** TURTLE PROCEDURES ****************************** turtles-own [speed SpeedLimit ParkTime Parked? steps-to-find-parking Direction CoordX CoordY MyDist MyDist-Occupied Total-Min-Dist Total-Min-Occupied-Chances Aacopy Bbcopy Search-Counter Park-Counter Vacant-Chances Occupied-Chances] to check-patches-after-park if (pc-ahead = 7) or (pc-ahead = 9) [ rt 90 check-patches-after-park ] end to try-all-vacant-choices let [:nullcheck2 (length Aacopy)] ifelse :nullcheck2 > 0 [ set Search-Counter 1 setMyDist 2000 repeat :nullcheck2 [ ;check only for free spots, don't waste RAM let [:item-number (item Search-Counter Aacopy)] ; extract the first (eventually each) element from the aa list let [:item-numberX (item 1 :item-number)] ; extract the X value of aa item let [:item-numberY (item 2 :item-number)] ; extract the Y value of the aa item let [:a (round(:item-numberX - xcor))] let [:b (round(:item-numberY - ycor))] ifelse (heading = 0 and :item-numberY < ycor) or (heading = 90 and :item-numberX < xcor) or (heading = 180 and :item-numberY > ycor) or (heading = 270 and :item-numberX > xcor)[ let [:distnew ((abs :a) + (abs :b) + 45)]] ; if the destination spot is in the opposite direction, the add 1/2 (average) block loop (22 + 8) to the dist [let [:distnew ((abs :a) + (abs :b))]] if (:distnew <= MyDist ) [let[:kchosen Search-Counter] setMyDist :distnew] ; CoordX and CoordY are turtle-own variables, which remember which parking spot the turtles zoomed onto, and will keep that until a turtles goes to that spot. if (Search-Counter <= (:nullcheck2)) [set Search-Counter (Search-Counter + 1)] ] set :item-number (item :kchosen Aacopy) ; extract the memorized smallest distance element from the :aacopy list set :item-numberX (item 1 :item-number) ; extract the X value set :item-numberY (item 2 :item-number) ; extract the Y value set :a (round (:item-numberX - xcor)) set :b (round (:item-numberY - ycor)) ifelse (heading = 0 and :item-numberY < ycor) or (heading = 90 and :item-numberX < xcor) or (heading = 180 and :item-numberY > ycor) or (heading = 270 and :item-numberX > xcor)[ setMyDist ( (abs :a) + (abs :b) + 45)] ; if the destination spot is in the opposite direction, the add 1/2 (average) block loop (22 + 8) to the dist [setMyDist ((abs :a) + (abs :b))] set :a (CoordX) set :b (CoordY) setTotal-Min-Dist ( min-of-turtles-with [CoordX = :a and CoordY = :b] [MyDist]) ;show Total-Min-Dist; ask from all turtles who has the same target, what the min dist is and save it for later ifelse (MyDist <= Total-Min-Dist)[ set CoordX (:item-numberX) set CoordY (:item-numberY) setDirection (towards-nowrap CoordX CoordY) setVacant-Chances (1 / MyDist)]; this is for comparison with the occupied spot search- availability probability / distance. [set Aacopy (remove-element :item-number Aacopy) try-all-vacant-choices]] [setCoordX 0 setCoordY 0 setMyDist 1000] end to try-all-occupied-choices let [:nullcheck3 (length Bbcopy)] ifelse (:nullcheck3 > 0) [ setMyDist-Occupied 2000 ; initialize a distance that is bigger than any on screen dist, so that a new dist will always be smaller set Search-Counter 1 ; loop through every elemnt in the "number" list starts with 1 repeat :nullcheck3 [ ;check only for free spots, don't waste RAM let [:item-number (item Search-Counter Bbcopy)] ; extract the first (eventually each) element from the aa list let [:item-numberX (item 1 :item-number)] ; extract the X value of aa item let [:item-numberY (item 2 :item-number)] ; extract the Y value of the aa item let [:a (round(:item-numberX - xcor))] let [:b (round(:item-numberY - ycor))] ifelse (heading = 0 and :item-numberY < ycor) or (heading = 90 and :item-numberX < xcor) or (heading = 180 and :item-numberY > ycor) or (heading = 270 and :item-numberX > xcor)[ let [:distnew ((abs :a) + (abs :b) + 45)]] ; if the destination spot is in the opposite direction, the add 1/2 (average) block loop (22 + 8) to the dist [let [:distnew ((abs :a) + (abs :b))]] if (:distnew <= MyDist-Occupied ) [let [:kchosen Search-Counter] setMyDist-Occupied :distnew] ; CoordX and CoordY are turtle-own variables, which remember which parking spot the turtles zoomed onto, and will keep that until a turtles goes to that spot. if (Search-Counter <= (:nullcheck3)) [set Search-Counter (Search-Counter + 1)] ] set :item-number (item :kchosen Bbcopy) ; extract the memorized smallest distance element from the :aacopy list set :item-numberX (item 1 :item-number) ; extract the X value set :item-numberY (item 2 :item-number) ; extract the Y value set :a (round (:item-numberX - xcor)) set :b (round (:item-numberY - ycor)) ifelse (heading = 0 and :item-numberY < ycor) or (heading = 90 and :item-numberX < xcor) or (heading = 180 and :item-numberY > ycor) or (heading = 270 and :item-numberX > xcor)[ setMyDist-Occupied ( (abs :a) + (abs :b) + 45)] ; if the destination spot is in the opposite direction, the add 1/2 (average) block loop (22 + 8) to the dist [setMyDist-Occupied ((abs :a) + (abs :b))] ;set :a (CoordX) set :b (CoordY) ;setTotal-Min-Dist ( min-of-turtles-with [CoordX = :a and CoordY = :b] [MyDist-Occupied]) ;show Total-Min-Dist; ask from all turtles who has the same target, what the min dist is and save it for later show (pc-at :a :b) if ((Probability-Timer-at :a :b) > 0) and ((Probability-Timer-at :a :b) < 2) [setOccupied-Chances (0.3 / (abs (int MyDist-Occupied - 1)))] if ((Probability-Timer-at :a :b) > 2) and ((Probability-Timer-at :a :b) < 8) [setOccupied-Chances (0.3 / (abs (int MyDist-Occupied - 6)))] ; 3 is half of six, which is ha max waiting time. if ((Probability-Timer-at :a :b) > 8) and ((Probability-Timer-at :a :b) < 32) [setOccupied-Chances (0.6 / (abs (int MyDist-Occupied - 24)))] ; 12 is half of 24, which is ha max waiting time. if ((Probability-Timer-at :a :b) > 32) and ((Probability-Timer-at :a :b) < 48) [setOccupied-Chances (1 / (abs (int MyDist-Occupied - 16)))] ; 8 is half of 16, which is ha max waiting time. set :a (CoordX) set :b (CoordY) setTotal-Min-Occupied-Chances ( min-of-turtles-with [CoordX = :a and CoordY = :b] [Occupied-Chances]) ifelse (Occupied-Chances <= Total-Min-Occupied-Chances)[ setCoordX (:item-numberX) setCoordY (:item-numberY) setDirection (towards-nowrap CoordX CoordY)] ;show "gotooccupied!"] [setBbcopy (remove-element :item-number Aacopy) try-all-vacant-choices]][setCoordX 0 setCoordY 0 setMyDist-Occupied 1000] end to choose-nearest-spot ; here extract the itam in the aa list, then extract ech item's x and y and check the patche's distance from the turtle (for all patches) ; use a turtles-own variable named MyDist which indicates the distance to the nearest free spot and a variable named ":kchosen" indicating the number of the element in the aa list wait-until [(Occupied-List-Ready? = true) and (List-Ready? = true)] if (Occupied-List-Ready? = true and List-Ready? = true) [ let [:nullcheck (length aa)] ifelse (:nullcheck > 0) [ setMyDist 2000 ; initialize a distance that is bigger than any on screen dist, so that a new dist will always be smaller setAacopy (copy-list aa) ; make a copy of the "aa", so if the real aa changes in length, their's remain the same until end of counting setBbcopy (copy-list bb); do the same for occupied spots try-all-vacant-choices if (CoordX = 0 and CoordY = 0) [try-all-occupied-choices]] [try-all-occupied-choices]] end to park ; has to be done so that agent will look for parking until found if (Parked? = false)[ setc yellow ;ask-patch-at CoordX CoordY [setpc green] ;ask-patch-at CoordX CoordY [setpc white] loop[ choose-nearest-spot ; here set the car to break or accelerate according to other cars ifelse (count-turtles-towards heading 1) > 0 ;if there is a turtle 1 space ahead, decelerate [setspeed speed-of one-of-turtles-towards heading 1 decelerate] [ifelse lookahead = 2 ;if lookahead=2, check 2 spaces ahead also [ifelse (count-turtles-at heading 1) > 0 [setspeed speed-of one-of-turtles-towards heading 2 decelerate] [accelerate]] ;else accelerate [accelerate]] if speed < 0.01 [setspeed 0.01] ;also adjust speed based on SpeedLimit and radar if speed > SpeedLimit [setspeed SpeedLimit] ; here is how the actual parking move happens ; first, parking at your own side of the road and then parking at the opposite side of the road, parking on horisontal streets is also allowed. ; augment the counter, which counts the program iterations during which a car parks (instead of real time) ifelse ((pc-at 0 0) = 0 and (pc-at 1 0) = 9 and (count-turtles-at 1 0) = 0) or ((pc-at 0 0) = 0 and (pc-at (-1) 0) = 9 and (count-turtles-at (-1) 0) = 0) or ((pc-at 0 0) = 0 and (pc-at -2 0) = 9 and (count-turtles-at -2 0) = 0) or ((pc-at 0 0) = 0 and (pc-at 2 0) = 9 and (count-turtles-at 2 0) = 0) or ((pc-at 0 0) = 0 and (pc-at 0 1) = 9 and (count-turtles-at 0 1) = 0) or ((pc-at 0 0) = 0 and (pc-at 0 (-1)) = 9 and (count-turtles-at 0 (-1)) = 0) or ((pc-at 0 0) = 0 and (pc-at 0 -2) = 9 and (count-turtles-at 0 -2) = 0) or ((pc-at 0 0) = 0 and (pc-at 0 2) = 9 and (count-turtles-at 0 2) = 0) or ((pc-at 0 0) = 9) [ ; here we augment the parking counter and check if the counter is full, in which case a car leaves if ((pc-at 0 0) = 9 and (pc-at (-1) 0) = 0) [ setPark-Counter Park-Counter + 1 ask-patch-at 0 0 [setProbability-Timer (Probability-Timer + 1)] if Park-Counter > ParkTime [setPark-Counter 0 seth 270 fd 1 seth 0 setParked? true stop]] if ((pc-at 0 0) = 9 and (pc-at 1 0) = 0) [ setPark-Counter Park-Counter + 1 ask-patch-at 0 0 [setProbability-Timer (Probability-Timer + 1)] if Park-Counter > ParkTime [setPark-Counter 0 seth 90 fd 1 seth 180 setParked? true stop]] if ((pc-at 0 0) = 9 and (pc-at 0 (-1)) = 0) [setPark-Counter Park-Counter + 1 ask-patch-at 0 0 [setProbability-Timer (Probability-Timer + 1)] if Park-Counter > ParkTime [setPark-Counter 0 seth 180 fd 1 seth 270 setParked? true stop]] if ((pc-at 0 0) = 9 and (pc-at 0 1) = 0) [setPark-Counter Park-Counter + 1 ask-patch-at 0 0 [setProbability-Timer (Probability-Timer + 1)] if Park-Counter > ParkTime [setPark-Counter 0 seth 0 fd 1 seth 90 setParked? true stop]] if ((pc-at 0 0) = 0 and (pc-at 1 0) = 9 and (count-turtles-at 1 0) = 0) [seth 90 fd 1 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at (-1) 0) = 9 and (count-turtles-at (-1) 0) = 0) [seth 270 fd 1 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at -2 0) = 9 and (count-turtles-at -2 0) = 0)[seth 270 fd 2 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at 2 0) = 9 and (count-turtles-at 2 0) = 0) [seth 90 fd 2 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at 0 1) = 9 and (count-turtles-at 0 1) = 0) [seth 0 fd 1 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at 0 (-1)) = 9 and (count-turtles-at 0 (-1)) = 0) [seth 180 fd 1 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at 0 -2) = 9 and (count-turtles-at 0 -2) = 0)[seth 180 fd 2 set steps-to-find-parking 0 setc red setMyDist 0] if ((pc-at 0 0) = 0 and (pc-at 0 2) = 9 and (count-turtles-at 0 2) = 0) [seth 0 fd 2 set steps-to-find-parking 0 setc red setMyDist 0]] [if (pc-at 0 0) not= white [ ifelse (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3 set steps-to-find-parking (steps-to-find-parking + 3)] [ifelse (random 2) = 0 [rt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 2)][fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)]]] [check-patches-after-park fd speed set steps-to-find-parking (steps-to-find-parking + speed)] if (CoordX = 0 and CoordY = 0)[choose-nearest-spot]]] ; here are the rules to guide a car towards a chosen spot, assuming it can also park on the opposite side of the road. ;in reality you should try the second best option here and then third best and so on! ifelse (CoordX not= 0 and CoordY not= 0 and MyDist not= 1000) [ ;only if you are closest in the competition for a given spot, drive there, else roam randomly and try again next step ; for heading = 0, supposing that you can also park on the opposite side of the road if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and ((heading = 0) and (xcor < CoordX and ycor < CoordY))[ ifelse (CoordX < (xcor + 3))[fd 2 set steps-to-find-parking (steps-to-find-parking + 2)] [rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)]] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and ((heading = 0) and (xcor < CoordX and ycor > CoordY))[ rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and ((heading = 0) and (xcor > CoordX and ycor > CoordY))[ fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and ((heading = 0) and (xcor > CoordX and ycor < CoordY))[ ifelse (CoordX > (xcor - 3)) [fd 2 set steps-to-find-parking (steps-to-find-parking + 2)][fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)]] ; for heading = 90, supposing that you can also park on the opposite side of the road if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 90 and (xcor < CoordX and ycor < CoordY))[ ifelse (CoordX < (xcor + 3)) [fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)][fd 2 set steps-to-find-parking (steps-to-find-parking + 2)]] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 90 and (xcor < CoordX and ycor > CoordY))[ ifelse (CoordX < (xcor + 3)) [rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)] [fd 2 set steps-to-find-parking (steps-to-find-parking + 2)]] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 90 and (xcor > CoordX and ycor > CoordY))[ rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 90 and (xcor > CoordX and ycor < CoordY))[ fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)] ; for heading = 180, supposing that you can also park on the opposite side of the road if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 180 and (xcor < CoordX and ycor < CoordY))[ fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 180 and (xcor < CoordX and ycor > CoordY))[ ifelse (CoordX < (xcor + 3)) [fd 2 set steps-to-find-parking (steps-to-find-parking + 2)] [fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)]] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 180 and (xcor > CoordX and ycor > CoordY))[ ifelse (CoordX > (xcor - 3)) [fd 2 set steps-to-find-parking (steps-to-find-parking + 2)] [rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)]] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 180 and (xcor > CoordX and ycor < CoordY))[ rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)] ; for heading = 270, supposing that you can also park on the opposite side of the road if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 270 and (xcor < CoordX and ycor < CoordY))[ rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 270 and (xcor < CoordX and ycor > CoordY))[ fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 270 and (xcor > CoordX and ycor > CoordY))[ ifelse (CoordX > (xcor - 3)) [fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)] [fd 2 set steps-to-find-parking (steps-to-find-parking + 2)]] if ((pc-at 0 0) = 2 and (pc-ahead)= 2) and (heading = 270 and (xcor > CoordX and ycor < CoordY))[ ifelse (CoordX > (xcor - 3)) [rt 90 fd 1 set steps-to-find-parking (steps-to-find-parking + 1)] [fd 2 set steps-to-find-parking (steps-to-find-parking + 2)]] ][if (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3 set steps-to-find-parking (steps-to-find-parking + 3)] [ifelse (random 2) = 0 [rt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 2)][fd 1 lt 90 fd 2 set steps-to-find-parking (steps-to-find-parking + 3)]]]] ]] end to drive ; each egnt will park and then drive for a certain time if (pc-at 1 0) = 7 or (pc-at 1 0) = 9 [ seth 0 setParked? false park repeat (parking-interval * 10) [ ; these are turtles driving up if (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3] [ifelse (random 2) = 0 [rt 90 fd 2][fd 1 lt 90 fd 2]]] check-patches-after-park ifelse (count-turtles-at 0 1) > 0 ;if there is a turtle 1 space ahead, decelerate [setspeed speed-of one-of-turtles-at 0 1 decelerate] [ifelse lookahead = 2 ;if lookahead=2, check 2 spaces ahead also [ifelse (count-turtles-at 0 1) > 0 [setspeed speed-of one-of-turtles-at 0 2 decelerate] [accelerate]] ;else accelerate [accelerate]] if speed < 0.01 [setspeed 0.01] ;also adjust speed based on SpeedLimit and radar if speed > SpeedLimit [setspeed SpeedLimit] fd speed ] ] if (pc-at (-1) 0) = 7 or (pc-at (-1) 0) = 9 [ seth 180 setParked? false park repeat (parking-interval * 10) [ ; these are turtles driving up if (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3] [ifelse (random 2) = 0 [rt 90 fd 2][fd 1 lt 90 fd 2]]] check-patches-after-park ifelse (count-turtles-at 0 (-1)) > 0 ;if there is a turtle 1 space ahead, decelerate [setspeed speed-of one-of-turtles-at 0 (-1) decelerate] [ifelse lookahead = 2 ;if lookahead=2, check 2 spaces ahead also [ifelse (count-turtles-at 0 (-1)) > 0 [setspeed speed-of one-of-turtles-at 0 (-2) decelerate] [accelerate]] ;else accelerate [accelerate]] if speed < 0.01 [setspeed 0.01] ;also adjust speed based on SpeedLimit and radar if speed > SpeedLimit [setspeed SpeedLimit] fd speed ] ] if (pc-at 0 1) = 7 or (pc-at 0 1) = 9 [ seth 270 setParked? false park repeat (parking-interval * 10) [ ; these are turtles driving up if (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3] [ifelse (random 2) = 0 [rt 90 fd 2][fd 1 lt 90 fd 2]]] check-patches-after-park ifelse (count-turtles-at (-1) 0) > 0 ;if there is a turtle 1 space ahead, decelerate [setspeed speed-of one-of-turtles-at (-1) 0 decelerate] [ifelse lookahead = 2 ;if lookahead=2, check 2 spaces ahead also [ifelse (count-turtles-at (-1) 0) > 0 [setspeed speed-of one-of-turtles-at (-2) 0 decelerate] [accelerate]] ;else accelerate [accelerate]] if speed < 0.01 [setspeed 0.01] ;also adjust speed based on SpeedLimit and radar if speed > SpeedLimit [setspeed SpeedLimit] fd speed ] ] if (pc-at 0 (-1)) = 7 or (pc-at 0 (-1)) = 9 [ seth 90 setParked? false park repeat (parking-interval * 10) [ ; these are turtles driving up if (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3] [ifelse (random 2) = 0 [rt 90 fd 2][fd 1 lt 90 fd 2]]] check-patches-after-park ifelse (count-turtles-at 1 0) > 0 ;if there is a turtle 1 space ahead, decelerate [setspeed speed-of one-of-turtles-at 1 0 decelerate] [ifelse lookahead = 2 ;if lookahead=2, check 2 spaces ahead also [ifelse (count-turtles-at 2 0) > 0 [setspeed speed-of one-of-turtles-at 2 0 decelerate] [accelerate]] ;else accelerate [accelerate]] if speed < 0.01 [setspeed 0.01] ;also adjust speed based on SpeedLimit and radar if speed > SpeedLimit [setspeed SpeedLimit] fd speed ] ] if (pc-ahead = 2 and (pc-at 0 0) = 2) [ifelse (random 2) = 0 [leap 3] [ifelse (random 2) = 0 [rt 90 fd 2][fd 1 lt 90 fd 2]]] check-patches-after-park if (pc-at 0 0 )= 2 [fd 1] end to accelerate setspeed (speed + (speedup / 1000)) end to decelerate setspeed speed - (slowdown / 1000) end