aUCBLogo Demos and Tests / molecules
			
				
			
			
be molecules
   max_   =   100
   min_   =   1
   maxb   =   6
   dopt   =   25
   dbind   =   trunc 2*dopt
   ffein   =   100
   Temperature=300
   cfein   =   80000/Temperature
   dopf   =   dopt*ffein
   maxf   =   ffein*dbind
   tE      =   1.1
   anfE   =   0.4
   expo   =   5
   ep      =   1
   fac   =   0.5
   gravV=-0.01*fac
   mov   =   10*fac
   vfac=100
   cmin   =   20
   deltaTFac   =   1.5
   sqrDeltaTFac   =   deltaTFac*deltaTFac
   rx=4
   ry=3
   sizeX=2
   sizeY=2
   ox=FloatArray max_
   oy=FloatArray max_
   c=IntArray max_
   x=FloatArray max_
   y=FloatArray max_
   vx=FloatArray max_
   vy=FloatArray max_
   ax=FloatArray max_
   ay=FloatArray max_
   banz=IntArray max_
   b=Array max_
   for [i 1 max_]
   [   b.i=[]
   ]
   
   f=(FloatArray maxf+1 0)
   onePoint=true
   gravity   =false
   tooSlow   = false
   tooFast   = false
   topteil = 0
   disposalY=   0
   col=[]
   lineColor=RGB 1 0 1
   setScreenColor 0
   norefresh
   setUpdateGraph false
   disableRoundLineEnds
   setPenSize [0 0]
   hideTurtle
   PenUp
   be init
      be initforcetable
;         setItems 0 f (rSeqFA 1 0 int maxf/2)^2/2
;         setItems int maxf/2 f (rSeqFA 0 1 int maxf/2)^2/100* -1
;      stop
         for [i 4 maxf]
         [   f.i=fac*( -((i/dopf)^(-expo))+(i/dopf)^(-expo-ep))
         ]
         for [i 0 3]
         [   f.i=0
         ]
      end
   
      be square side x_ y_ angle v vangle
          angle= angle
         vangle=vangle
         vx_=v*Cos vangle
         vy_=v*Sin vangle
         vxx= dopt*Cos angle 
         vxy= dopt*Sin angle
         vyx= dopt*Sin angle
         vyy=-dopt*Cos angle
         kx=side/2+(mod trunc side/2 2)/2
         ky=side/2*(Sqrt 3)/2
         x_= x_-(vxx*kx+vyx*ky)
         y_= y_-(vxy*kx+vyy*ky)
         local [i]
         i=1
         for [yi 1 side]
         [   for [xi 1 side]
            [   kx=xi+(mod yi 2)/2
               ky=yi*(Sqrt 3)/2
               x.i= x_+vxx*kx+vyx*ky
               y.i= y_+vxy*kx+vyy*ky
               vx.i=vx_
               vy.i=vy_
               banz.i=0
               ifElse i <= max_
               [   i=i+1
               ][   print [Too many parts!]
               ]
            ]
         ]
         topteil=i
      end
   
      square 10 0 0 30 0 90
      topteil=topteil-1
   
      initforcetable
   
      setXY 0 -270  setH 90
      Label [[RETURN]=splines  [+]=heat  [-]=cool
        [G]=gravity  [other Key]=cS  Mouse: L=pull R=del]
      col=loadpalette "TEILE.PAL
   end
   be movethem
   
      be faster
         local [k]
         for [k 1 topteil]
         [   vx.k=vx.k*deltaTFac
            vy.k=vy.k*deltaTFac
         ]
         for [k 0 maxf]
         [   f.k=f.k*sqrDeltaTFac
         ]
         gravV:= gravV*sqrDeltaTFac
      end
   
      be slower
         local [k]
         for [k 1 topteil]
         [   vx.k=vx.k/deltaTFac
            vy.k=vy.k/deltaTFac
         ]
         for [k 0 maxf]
         [   f.k=f.k/sqrDeltaTFac
         ]
         gravV:= gravV/sqrDeltaTFac
      end
      be preparevars
         local [i]
         if tooSlow [faster]
         if tooFast [slower]
   
         tooSlow=true
         tooFast=false
   
         for [i 1 topteil]
         [   ax.i=0
            ay.i=0
            c.i=0
         ]
      end
   
      be energyloss
         local [hx hy]
         setPC RGB 1 1 1
         Line List List x.i y.i  List x.j y.j RGB 0 0 1
         hx=(vx.i+vx.j)/2
         hy=(vy.i+vy.j)/2
   
         if i >= min_
         [   vx.i=hx
            vy.i=hy
         ]
         banz.i=banz.i+1
         b.i=fput j b.i
         vx.j=hx
         vy.j=hy
         banz.j=banz.j+1
         b.j=fput i b.j
   
         setPC 0
         Line List List x.i y.i  List x.j y.j RGB 0 0 1
      end
   
      be ionize
         if member? j b.i
         [   b.i=remove j b.i
            banz.i=banz.i-1
            b.j=remove i b.j
            banz.j=banz.j-1
         ]
      end
   
      be draw i
         setXY x.i y.i
         setFC col.(c.i+2)
         fillCircle dopt/2
         PenDown
         Line List 
            List x.i y.i 
            List x.i+vx.i*vfac y.i+vy.i*vfac lineColor
         PenUp
      end
   
      be del x y
         setXY x y
         setFC 0
      ;   fillCircle dopt/2
      end
   
      be unboundf i j
         output not member? j b.i
      end
   
      local [i j bi di
         d dx dy
         fx fy f0 force _c nomml]
      unboundv=true
      tag "nomml
         preparevars
         for [i 1 topteil-1]
         [   for [j topteil i+1]
            [   dx= x.i-x.j
               if (abs dx) > dbind [continueLoop]
               dy= y.i-y.j
               if (abs dy) > dbind [continueLoop]
               d= Sqrt (Sqr dx)+(Sqr dy)
               if d > dbind
               [
                  ionize
               ]
               if d < dbind
               [   unboundv=unboundf i j
                  if unboundv 
                  and2 (banz.i < maxb) 
                  and2 (banz.j < maxb)
                  [   ;if not yet bound & free
                     if (abs d-dopt) < 0.01
                     [   ;and d around dopt
                        energyloss   ;then "emitt a Photon"
                     ]
                  ]   
               ]
               if unboundv and2 (d > dopt)
               [
                  continueLoop
               ]
               d=d*ffein
               di=Int d
               if di >= maxf-1 [di=maxf-1]
               f0=f.di
               force=f0 ;+(d-Int d)*(f.(di+1)-f0)
ignore[
               _c=abs force*cfein
               if _c > 255 
               [
                  tooFast=true
                  tooSlow=false
                  goto "nomml
               ]
               c.i=c.i+trunc _c
               if c.i > 250 [c.i=250]
]      
               fx=dx*force
               fy=dy*force
               ax.i=ax.i+fx
               ay.i=ay.i+fy
               ax.j=ax.j-fx
               ay.j=ay.j-fy
ignore[
               c.j=c.j+trunc _c
               if c.j > 250 [c.j=250]
               
               if tooSlow
               [   if c.i > cmin
                  [   tooSlow=false
                  ]
               ]
]
            ]
         ]
      for [i min_ topteil]
      [   c.i=Int (sqrt (sqr ax.i)+(sqr ay.i))*cfein
         if c.i > 250 
         [
            tooFast=true
            tooSlow=false
            goto "nomml
         ]
         if c.i > cmin
         [   tooSlow=false
         ]
      ]
      clearScreen
      for [i 1 min_-1 1]
      [   draw i
      ]   
      for [i min_ topteil]
      [   vx.i=vx.i+ax.i
         vy.i=vy.i+ay.i
   
         if gravity
         [   vy.i=vy.i+gravV
         ]
         x.i=x.i+vx.i
         y.i=y.i+vy.i
   
         if x.i < -400+rx or2 x.i > 400-rx
         [   vx.i=-vx.i
            x.i=x.i+vx.i
         ]
         if y.i < -300+ry or2 y.i > 300-ry
         [   vy.i=-vy.i
            y.i=y.i+vy.i
         ]
         ifElse onePoint
         [   draw i
         ][   setPixelXY x.i y.i c.i+1
         ]
      ]
   end
   be cooling
      local [i]
      for [i 1 topteil]
      [   vx.i=vx.i/tE
         vy.i=vy.i/tE
      ]
   end
   
   be heating
      local [i]
      for [i 1 topteil]
      [   vx.i=vx.i*tE
         vy.i=vy.i*tE
      ]
   end
   
   be findnearest hx hy
      local [i j dmin d]
      dmin=IntMax
      for [i 1 topteil]
      [   d=trunc Sqrt (Sqr hx-x.i)+(Sqr hy-y.i)
         if d < dmin
         [   dmin=d
            j=i
         ]
      ]
      output j
   end
   
   be showmark x y
      setPC 12
      setXY x y
      circle dopt/4
      setPixelXY x y 0
      updateGraph
      setPC 0
      setXY x y
      circle dopt/4
   end
   
   be mousepulling
      mx=MouseX
      my=MouseY
      if not clicked
      [   clicki=findnearest mx my
         clicked=true
      ]
      i=clicki
   ;   showmark(ox,oy);
      d=((Sqr mx-x)+Sqr my-y)^0.3
      vx.i=0 ;(vx+mov*(mx-x)/d)/te
      vy.i=0 ;(vy+mov*(my-y)/d)/te
      x.i=x.i+mov*(mx-x.i)/d
      y.i=y.i+mov*(my-y.i)/d
   end
   
   be mousespecials
      local [i mx my]
      mx=MouseX
      my=MouseY
      i=findnearest mx my
      showmark ox.i oy.i
      vx.i=0
      vy.i=0
      x.i=rx
      y.i=ry+dopt*disposalY
      disposalY= Mod (disposalY+1) 6
      while [MouseButtons!=0]
      [   dispatchMessages
      ]
   end
   init
   setPixelXY rSeqFA -400 400 maxf+1  f*1000 15
;stop
   forever
   [   movethem
;updateVars
      updateGraph
      dispatchMessages
      if Key?
      [   ch=lowerCase readChar
         if ch==Char 27   [break]
         if ch==Char 13 [onePoint=not onePoint]
         if ch=="- [cooling]
         if ch=="+ [heating]
         if ch=="g [gravity=not gravity]
         if ch=="  [clearScreen]
      ]
      ifElse MouseButtons==1 
      [   mousepulling
      ][   ifElse MouseButtons==2 
         [   mousespecials
         ][   clicked=false
         ]
      ]
   ]
   pr [End]
end