;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Program: Fish Schooling Model ;; Authors: Jude Battista and Kendra Knudtzon ;; Date: December 15, 1999 ;; Purpose: To model fish schooling among a breed, fear of different breeds, and ;; a predator/prey paradigm with sharks that eat all fish in its path ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; breeds [redfish yellowfish greenfish sharks bubbles] patches-own [red-here green-here yellow-here shark-here red-near green-near yellow-near shark-near total-near] ;; variables used in the program turtles-own [rClosest rClosest-dist rProximity rNeighborhood rFear rFear-dist rShark rShark-dist gClosest gClosest-dist gProximity gNeighborhood gFear gFear-dist gShark gShark-dist yClosest yClosest-dist yProximity yNeighborhood yFear yFear-dist yShark yShark-dist oClosest oClosest-dist sClosest sClosest-dist] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; setup method ;; Create all fish and randomly place them on screen , specified by user (sliders) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to setup clearall create-redfish numberOfRed create-greenfish numberOfGreen create-yellowfish numberOfYellow create-sharks numberOfSharks ask-redfish [ setcolor red setheading (random 360) ifelse heading > 180 [setshape red-fish-left] [setshape red-fish] setxy (random screen-size) (random screen-size) setrNeighborhood Sociable_red ] ask-greenfish [setcolor green setheading (random 360) ifelse heading > 180 [setshape green-fish-left] [setshape green-fish] setxy (random screen-size) (random screen-size) setgNeighborhood Sociable_green ] ask-yellowfish [setcolor yellow setheading (random 360) ifelse heading > 180 [setshape yellow-puffer-left] [setshape yellow-puffer] setxy (random screen-size) (random screen-size) setyNeighborhood Sociable_yellow ] ask-sharks [setcolor grey setheading (random 360) ifelse heading > 180 [setshape shark-left] [setshape shark] setxy (random screen-size) (random screen-size) ] ;; color the patches (background) blue and make some bubbles in the water setpc blue create-bubbles 100 ask-bubbles [setshape bubble setxy (random screen-size) (random screen-size) seth 0] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; start the interactions in the pond ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to goFish update-water if breed = redfish [move-redfish] if breed = greenfish [move-greenfish] if breed = yellowfish [move-yellowfish] if breed = sharks [move-sharks] if breed = bubbles [move-bubbles] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; update water variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to update-water setred-here 0 setgreen-here 0 setyellow-here 0 setshark-here 0 if color = red [setred-here 1] if color = green [setgreen-here 1] if color = yellow [setyellow-here 1] if color = grey [setshark-here 1] nsum red-here red-near ;; 8-neighbor sum nsum green-here green-near nsum yellow-here yellow-near nsum shark-here shark-near settotal-near red-near + green-near + yellow-near + shark-near end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Move the fish, according to several rules: ;; Fear sharks, Fear Others, Desire to be near to fish of your kind (schooling) ;; (Priority of these factors is based on user slider input) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to move-redfish wait 0.01 ifelse (heading > 180) [setshape red-fish-left] [setshape red-fish] ;;find closest redfish and its distance setrClosest who-min-of-redfish [distance xcor-of myself ycor-of myself] setrClosest-dist distance xcor-of rClosest ycor-of rClosest ;; find the nearest shark setrShark who-min-of-sharks [distance xcor-of myself ycor-of myself] setrShark-dist distance xcor-of rShark ycor-of rShark ;;find closest green or yellow fish setrFear who-min-of-turtles-with [breed = greenfish or breed = yellowfish] [distance xcor-of myself ycor-of myself] setrFear-dist distance xcor-of rFear ycor-of rFear ;; highly sociable fish want to be closer to neighbors setrProximity ( 6 - Sociable_red ) if rShark-dist < 1 [die] ;; fish dies if it is too near a shark getRheading fd 0.05 * fishSpeedRed rt 1.0 * (-1 + random 3) ;; allow for alteration in the fish's course end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Set the desired heading based on interactions with other fish in the pond ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to getRheading ;; if shark is in fear radius, run away ifelse rShark-dist <= FearOtherRed [seth-fish 180 + towards xcor-of rShark ycor-of rShark 2 * fearOtherRed] ;; else if a fish is within our proximity, run away [ifelse rClosest-dist <= rProximity [seth-fish 180 + towards xcor-of rClosest ycor-of rClosest 5] ;; if we aren't avoiding collision, then we need to know which way to head [ifelse rFear <= FearOtherRed [ifelse rClosest <= rNeighborhood ;;determine how much to fear others and how much to try schooling ;; seth-fish (towards xcor ycor) (degrees) [seth-fish (towards fearOtherRed * cos (180 + towards xcor-of rFear ycor-of rFear) + Sociable_red * cos heading-of rClosest fearOtherRed * sin (180 + towards xcor-of rFear ycor-of rFear) + Sociable_red * sin heading-of rClosest ) (Sociable_red + fearOtherRed) / 2 ] [seth-fish (towards fearOtherRed * cos (180 + towards xcor-of rFear ycor-of rFear) + xcor-of rClosest fearOtherRed * sin (180 + towards xcor-of rFear ycor-of rFear) + ycor-of rClosest ) (Sociable_red + fearOtherRed) / 2 ] ] ;; if there isn't other fish to fear, school based on closeness of breed [ifelse rClosest <= rNeighborhood [seth-fish heading-of rClosest Sociable_red] [seth-fish towards xcor-of rClosest ycor-of rClosest Sociable_red] ] ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Sharks move to avoid collision, and to chase after other fish to eat ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to move-sharks wait 0.01 rt 1.0 * (-1 + random 3) ;;find the closest shark setsClosest who-min-of-sharks [distance xcor-of myself ycor-of myself] setsClosest-dist distance xcor-of sClosest ycor-of sClosest ;; find the closest fish to eat setoClosest who-min-of-turtles-with [breed = yellowfish or breed = redfish or breed = greenfish] [distance xcor-of myself ycor-of myself] setoClosest-dist distance xcor-of oClosest ycor-of oClosest ;; if another shark is close, avoid colliding with it ifelse sClosest-dist < 2 [seth-fish 180 + towards xcor-of sClosest ycor-of sClosest 10] ;; otherwise, go towards the closest fish [if oClosest-dist <= Hunger [seth towards xcor-of oClosest ycor-of oClosest]] ifelse heading > 180 [setshape shark-left] [setshape shark] fd ( (random Hunger) * Speed / 100) end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Moves the desired heading of the fish from its current heading by degrees, unless ;; the fish are already close, in which case the fish match heading ;; ;; This is copied from the StarLogo flocking example included with the Mac ;; download version of StarLogo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to seth-fish :other-heading :degrees ;;copied from flocking example ifelse ((:other-heading >= heading) and ((:other-heading - heading) <= :degrees)) or ((:other-heading <= heading) and ((heading - :other-heading) <= :degrees)) [seth :other-heading] [ifelse ((:other-heading - heading) mod 360) < 180 [rt :degrees] [lt :degrees]] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Bubbles move randomly up ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to move-bubbles wait 0.01 fd ( (random 10) / 200) end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; function so that we can have empty buttons for interface labels ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to doNothing end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; moving green and yellow fish is the same as moving red fish ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to move-yellowfish wait 0.01 ifelse (heading > 180) [setshape yellow-puffer-left] [setshape yellow-puffer] ;;find closest yellowfish and its distance setyClosest who-min-of-yellowfish [distance xcor-of myself ycor-of myself] setyClosest-dist distance xcor-of yClosest ycor-of yClosest ;; find the nearest shark setyShark who-min-of-sharks [distance xcor-of myself ycor-of myself] setyShark-dist distance xcor-of yShark ycor-of yShark ;;find closest green or red fish setyFear who-min-of-turtles-with [breed = greenfish or breed = redfish] [distance xcor-of myself ycor-of myself] setyFear-dist distance xcor-of yFear ycor-of yFear setrProximity ( 6 - Sociable_yellow ) if yShark-dist < 1 [die] getYheading fd 0.05 * fishSpeedYellow rt 1.0 * (-1 + random 3) ;; allows for alteration in the fish's course end to move-greenfish wait 0.01 ifelse (heading > 180) [setshape green-fish-left] [setshape green-fish] ;;find closest redfish and its distance setgClosest who-min-of-greenfish [distance xcor-of myself ycor-of myself] setgClosest-dist distance xcor-of gClosest ycor-of gClosest ;; find the nearest shark setgShark who-min-of-sharks [distance xcor-of myself ycor-of myself] setgShark-dist distance xcor-of gShark ycor-of gShark ;;find closest red or yellow fish setgFear who-min-of-turtles-with [breed = redfish or breed = yellowfish] [distance xcor-of myself ycor-of myself] setgFear-dist distance xcor-of gFear ycor-of gFear setrProximity ( 6 - Sociable_green ) if gShark-dist < 1 [die] getGheading fd 0.05 * fishSpeedGreen rt 1.0 * (-1 + random 3) ;; allows for alteration in the fish's course end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Setting headings for green and yellow fish is the same as for red ones ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to getYheading ifelse yShark-dist <= FearOtherYellow ;;shark is in fear radius, run away [seth-fish 180 + towards xcor-of yShark ycor-of yShark 2 * fearOtherYellow] [ifelse yClosest-dist <= yProximity ;; if a fish is within our proximity, run away [seth-fish 180 + towards xcor-of yClosest ycor-of yClosest 5] [ifelse yFear <= FearOtherYellow [ifelse yClosest <= yNeighborhood [seth-fish towards fearOtherYellow * cos (180 + towards xcor-of yFear ycor-of yFear) + Sociable_yellow * cos heading-of yClosest ;;x-cor fearOtherYellow * sin (180 + towards xcor-of yFear ycor-of yFear) + Sociable_yellow * sin heading-of yClosest ;;y-cor (Sociable_yellow + fearOtherYellow) / 2 ] [seth-fish towards fearOtherYellow * cos (180 + towards xcor-of yFear ycor-of yFear) + xcor-of yClosest ;;x-cor fearOtherYellow * sin (180 + towards xcor-of yFear ycor-of yFear) + ycor-of yClosest ;;y-cor (Sociable_yellow + fearOtherYellow) / 2 ] ] [ifelse yClosest <= yNeighborhood [seth-fish heading-of yClosest Sociable_yellow] [seth-fish towards xcor-of yClosest ycor-of yClosest Sociable_yellow] ] ] ] end to getGheading ifelse gShark-dist <= FearOtherGreen ;;shark is in fear radius, run away [seth-fish 180 + towards xcor-of gShark ycor-of gShark 2 * fearOtherGreen] [ifelse gClosest-dist <= gProximity ;; if a fish is within our proximity, run away [seth-fish 180 + towards xcor-of gClosest ycor-of gClosest 5] [ifelse gFear <= FearOtherGreen [ifelse gClosest <= gNeighborhood [seth-fish towards fearOtherGreen * cos (180 + towards xcor-of gFear ycor-of gFear) + Sociable_green * cos heading-of gClosest ;;x-cor fearOtherGreen * sin (180 + towards xcor-of gFear ycor-of gFear) + Sociable_green * sin heading-of gClosest ;;y-cor (Sociable_green + fearOtherGreen) / 2 ] [seth-fish towards fearOtherGreen * cos (180 + towards xcor-of gFear ycor-of gFear) + xcor-of gClosest ;;x-cor fearOtherGreen * sin (180 + towards xcor-of gFear ycor-of gFear) + ycor-of gClosest ;;y-cor (Sociable_green + fearOtherGreen) / 2 ] ] [ifelse gClosest <= gNeighborhood [seth-fish heading-of gClosest Sociable_green] [seth-fish towards xcor-of gClosest ycor-of gClosest Sociable_green] ] ] ] end