Swarm Behavior + Attractor : Agent methods: 1. Align : Move in the same direction as your neighbours. 2. Cohesion : Remain close to your neighbours. 3. Seperation : Avoid collisions with your neighbours. Attractor methods: (Controlling the shape) From starting points move to target points to create bridge. Using swarm simulation in Grasshopper is in this post: Swarm Python GH Component   ```import rhinoscriptsyntax as rs
import Rhino as rc
import time
import math
import scriptcontext as rc
import Rhino.Geometry as rg
from scriptcontext import escape_test
from random import *

rectX = 600
rectY = 600

class Runner:
def __init__(self, p, v):
self.p = p
self.v = v
self.a = rs.VectorCreate( (0,0,0),(0,0,0) )
self.ptList = []

def ptRun(self):
v = rs.VectorLength(self.v)
if v > 15:
self.v = rs.VectorScale(rs.VectorUnitize(self.v), 15)
self.a = rs.VectorCreate( (0,0,0),(0,0,0) )

self.ptList.append(self.p)

def flock(self):
self.separate(4.0)
self.cohesion(0.001)
self.align(0.1)

self.attractor(0.7)

def align(self, mag):

steer = rs.VectorCreate( (0,0,0) , (0,0,0) )
count = 0

for i in pts:
distance = rs.Distance(i.p, self.p)
if distance > 0 and distance < 40:
count += 1

if count>0:
steer = rs.VectorScale(steer, 1.0/count)

steer = rs.VectorScale(steer, mag)

def cohesion(self, mag):

sum = rs.VectorCreate( (0,0,0) , (0,0,0) )
count = 0

for i in pts:
distance = rs.Distance(i.p, self.p)
if distance > 0 and distance < 60:
count += 1

if count>0:
sum = rs.VectorScale(sum, 1.0/count)

steer = rs.VectorSubtract(sum, self.p)
steer = rs.VectorScale(steer, mag)

def separate(self, mag):

steer = rs.VectorCreate( (0,0,0) , (0,0,0) )
count = 0

for i in pts:
distance = rs.Distance(i.p, self.p)
if distance > 0 and distance < 30:
diff = rs.VectorSubtract(self.p, i.p)
diff = rs.VectorUnitize(diff)
diff = rs.VectorScale(diff, 1.0/distance)

count += 1

if count>0:
steer = rs.VectorScale(steer, 1.0/count)

steer = rs.VectorScale(steer, mag)

def attractor(self, mag):

attrPt = rs.VectorCreate((-800,-700,0) , (0,0,0))
steer = rs.VectorCreate( (0,0,0) , (0,0,0) )
diff = rs.VectorSubtract( attrPt, self.p )
diff = rs.VectorUnitize(diff)

steer = rs.VectorScale(steer, mag)

def drawLines(self):
for i in pts:
distance = rs.Distance(i.p, self.p)
if distance < 40 and distance > 0:
pt1 = rg.Point3d(i.p, i.p, i.p)
pt2 = rg.Point3d(self.p, self.p, self.p)

def drawPt(self):
return pt

def setup():
global pts
pts = []
global lns
lns = []
numAG = 36

for i in range(numAG):
run1 = Runner(p, v)
pts.append(run1)

def run():
pos = []
vec = []

for i in pts:
pos.append(i.drawPt())
vec.append(i.v)
for i in pts:
i.flock()
i.ptRun()
if t > 10 and t%6==1:
i.drawLines()

def drawTime():
FPS = 30
last_time = time.time()
global t
t = 0
curves = []
# whatever the loop is...
while True:
# draw animation
t += 1
# pause so that the animation runs at 30 fps
new_time = time.time()
# see how many milliseconds we have to sleep for
# then divide by 1000.0 since time.sleep() uses seconds
sleep_time = ((1000.0 / FPS) - (new_time - last_time)) / 1000.0
if sleep_time > 0:
time.sleep(sleep_time)
last_time = new_time

run()

print t

if t > 108:
for k in pts:

rs.EnableRedraw(False)
for crv in curves:

for ln in lns: