NetLogo version NetLogo 3.0
Running with NetLogoLite.jar version 302.
NetLogo Version: NetLogo 3.0
;; SUMMARY ;;;; A NetLogo model. ;; COPYRIGHT & LICENSE ;;;; Copyright © 2004,2005 James P. Steiner ;;;; Some Rights Reserved. ;;;; Creative Commons Attribution-NonCommercial-ShareAlike License v. 2.0. ;;;; Visit http://creativecommons.org/licenses/by-nc-sa/2.0/ for more information. ;; breeds [ ducks] ducks-own [ new-heading flockmates my-speed ] to startup setup end to setup ca create-custom-ducks population [ make-duck ] end to scatter ;; ducks setxy (random-int-or-float screen-size-x) - screen-edge-x (random-int-or-float screen-size-y) - screen-edge-y set heading random-int-or-float 360.0 set new-heading heading end to go ;; the model runs faster if we don't update the screen ;; until after all turtles have moved ; no-display check-pop ask ducks [ flock ] ask ducks [ move ] ; display end to check-pop locals [ curr-pop ] set curr-pop ( count ducks ) if curr-pop != population [ ifelse population > curr-pop [ ;; make new ducks create-custom-ducks (population - curr-pop) [ make-duck ] ] [ ;; kill extra ducks repeat (curr-pop - population) [ ask random-one-of ducks [ die ] ] ] ] end to make-duck set color yellow - 2 + random-int-or-float 7 ;; random shades look nice scatter set my-speed speed ; + speed * (( random 1.0) - .5) end to flock ;; turtle procedure locals [ closest-duck cohere-heading conform-heading avoid-heading spleen-heading close-duck-distance panic ] set new-heading heading set cohere-heading heading set conform-heading heading set avoid-heading heading set spleen-heading heading + wheel set flockmates visible-ducks if any? flockmates [ set closest-duck duck-closest-to-me ;; avoid set close-duck-distance (distance closest-duck) if close-duck-distance < comfort-zone [ ifelse close-duck-distance > 0 [ set avoid-heading ( normal-360 ( 180 + towards closest-duck ) ) set avoid-heading weighted-mean heading avoid-heading ( ( comfort-zone ) - close-duck-distance ) / ( comfort-zone * .5 ) ] [ set avoid-heading random 360 ] ] ;; cohere if mean-flockmates-distance > comfort-zone [ set cohere-heading towards-flockmates-center ] ;; conform set conform-heading mean-flockmates-heading set new-heading weighted-mean-multi spleen-heading independence avoid-heading caution cohere-heading cohesion conform-heading conformity ] end to move set heading new-heading jump speed; my-speed end ;;; HELPER PROCEDURES to-report visible-ducks locals [ nearby-ducks] set nearby-ducks ducks in-radius vision-range with [self != myself] ifelse any? nearby-ducks [ report nearby-ducks with [ ( vision-angle - field-of-view) < abs( subtract-headings ( heading-of myself ) ( normal-360 ( away-from myself ) ) ) and ( vision-angle + field-of-view) > abs( subtract-headings ( heading-of myself ) ( normal-360 ( away-from myself ) ) ) ] ] [ report nearby-ducks ] end to-report duck-closest-to-me ;; turtle procedure report min-one-of flockmates [distance myself ] end to-report mean-flockmates-heading ;; turtle procedure ;; We can't just average the heading variables here. ;; For example, the average of 1 and 359 should be 0, ;; not 180. So we have to use trigonometry. let mean-sin mean values-from flockmates [sin heading] let mean-cos mean values-from flockmates [cos heading] ifelse mean-sin != 0 or mean-cos != 0 [ report atan mean-sin mean-cos ] [ report 0 ] end to-report weighted-mean-multi [ ah aw bh bw ch cw dh dw ] ifelse (aw + bw + cw + dw) = 0 [ report ah ] [ report atan ( ( (sin ah ) * aw + (sin bh ) * bw + (sin ch ) * cw + (sin dh ) * dw ;+ (sin eh ) * ew ) / (aw + bw + cw + dw ) ) ( ( (cos ah ) * aw + (cos bh ) * bw + (cos ch ) * cw + (cos dh ) * dw ;+ (cos eh ) * ew ) / (aw + bw + cw + dw ) ) ] end to-report weighted-mean [ a b c ] report normal-360 atan ( ( sin a + sin b ) * ( c ) ) ( ( cos a + cos b ) * (1 - c) ) end to-report towards-flockmates-center ;; turtle procedure ;; "towards myself" gives us the heading from the other turtle ;; to me, but we want the heading from me to the other turtle, ;; so we add 180 report normal-360 ( atan mean values-from flockmates [sin (normal-360 (smart-towards-myself + 180 ))] mean values-from flockmates [cos (normal-360 (smart-towards-myself + 180 ))] ) end to-report mean-flockmates-distance report mean values-from flockmates [ distance myself ] end to-report smart-towards-myself ifelse xcor != xcor-of myself or ycor != ycor-of myself [ report towards myself ] [ report random-float 360 ] end ;;; PATTERN ;to pattern ;; option 1: veer to create preferred angle re nearest neighbor ; set vee-angle subtract-headings (towards closest-duck) heading ; set heading heading + sin( 90 + vee-angle - flock-angle ) ;end ;; ACCELLERATE ;to accelerate ; if speed < 1 [ set speed speed + .1 ] ; if speed > 1 [ set speed speed - .1 ] ;end to-report plus-or-minus-one report 2 * ( 0.5 - random-int-or-float 2 ) end To-report normal-360 [ input-angle ] ; normalizes the input angle to be between 0 and 359.9999 ( 0.0 <= angle < 360.0 ) locals [ angle ] set angle input-angle while [ angle < 0.0 ] [ set angle angle + 360.0 ] while [ angle >= 360.0 ] [ set angle angle - 360.0 ] report angle end to-report away-from [ agent ] ifelse xcor-of agent != xcor or ycor-of agent != ycor [ report 180 + towards agent ] [ report 0 ] end ;; To find the difference between two headings, we can't just ;; subtract the numbers, because 0 and 360 are the same heading. ;; For example, the difference between a heading of 5 degrees ;; and a heading of 355 degrees is 10 degrees, not 350 degrees. ;;;;to-report subtract-headings [h1 h2] ;;;; ifelse abs (h1 - h2) <= 180 ;;;; [ report h1 - h2 ] ;;;; [ ifelse h1 > h2 ;;;; [ report h1 - h2 - 360 ] ;;;; [ report h1 - h2 + 360 ] ] ;;;;end
View or download the complete model file (to download: right-click, save-link-as):
-- Download flocking --