Talk:Physics

From WikiManual
Jump to: navigation, search

Physics

Attribute VB_Name = "Physics"
'
'                 P H Y S I C S
'

Option Explicit

' experimental object: used to store a grid of environmental
' features
Public envir As New EnvGrid
Public envgridpres As Boolean
Public nlink As Single         ' links physics constants
Public plink As Single
Public klink As Single
Public mlink As Single

Const cof_E As Single = 0.8

Public Sub Newaccel

' assigns every robot a new acceleration
' this is the first step in recalculating positions
Public Sub Newaccel()
  Dim nd As node
  Dim t As Integer
  Set nd = rlist.firstnode
  While Not nd Is rlist.last
    t = nd.robn
    With rob(t)
    .ax = 0 + Random(-SimOpts.PhysBrown, SimOpts.PhysBrown)
    .ay = SimOpts.PhysGrav + Random(-SimOpts.PhysBrown, SimOpts.PhysBrown)
    Set nd = rlist.nextnode(nd)
    End With
  Wend
  KeepOff
End Sub

Public Function angle

' calculates angle between (x1,y1) and (x2,y2)
Public Function angle(x1 As Long, y1 As Long, x2 As Long, y2 As Long) As Single
  Dim an As Single
  Dim dx As Long
  Dim dy As Long
  dx = x2 - x1
  dy = y1 - y2
  If dx = 0 Then
    an = 0
    If dy < 0 Then an = pi / 4 * 3
  Else
    an = Atn(dy / dx)
    If dx < 0 Then
      an = an + pi
    End If
  End If
  angle = an
End Function

Public Function angnorm

' normalizes angle in 0,2pi
Public Function angnorm(ByVal an As Single) As Single
  While an < 0
    an = an + 2 * pi
  Wend
  While an > 2 * pi
    an = an - 2 * pi
  Wend
  angnorm = an
End Function

Public Function AngDiff

' calculates difference between two angles
Public Function AngDiff(a1 As Single, a2 As Single) As Single
  Dim r As Single
  r = a1 - a2
  If r > pi Then
    r = -(2 * pi - r)
  End If
  If r < -pi Then
    r = r + 2 * pi
  End If
  AngDiff = r
End Function

Private Sub NewAccelEnv

' same as above, but using the experimental environment grid
Private Sub NewAccelEnv()
  Dim nd As node
  Dim t As Integer
  Set nd = rlist.firstnode
  Dim phv As Variant
  While Not nd Is rlist.last
    t = nd.robn
    With rob(t)
    phv = envir.GetMat(.envx, .envy)
    .ax = 0 + Random(-phv(1), phv(1))
    .ay = phv(2) + Random(-phv(1), phv(1))
    Set nd = rlist.nextnode(nd)
    End With
  Wend
  KeepOff
End Sub

Public Sub linklen

Public Sub linklen()
  Dim k As Integer
  Dim d As Single
  Dim m As Single       'Acceleration modifier
  Dim dx As Long
  Dim dy As Long
  Dim dxl As Single
  Dim dyl As Single
  Dim j As Integer
  Dim kconst As Single
  Dim TLength As Single     'target length for tie. = existing length + shrink variable
  Dim Xdif As Single
  Dim Ydif As Single
  Dim AvgVX As Single
  Dim AvgVY As Single
  Dim Stiff As Integer
  Dim nd As node
  Dim t As Integer
  Dim kl As Boolean
  Dim dif As Single
  
  m = 1.5
  Set nd = rlist.firstnode
  While Not nd Is rlist.last
    j = 1
    t = nd.robn
    If Not rob(t).Corpse Then       'new condition added to speed up code by not parsing corpses
      If rob(t).Numties > 0 Then    'new condition added to speed up code by not parsing robots without ties.
        While rob(t).Ties(j).pnt > 0    'Tie points to something
          k = rob(t).Ties(j).pnt        'k is the number of the robot it points to
          TLength = rob(t).Ties(j).ln + rob(t).Ties(j).shrink
          rob(t).Ties(j).shrink = 0
          If k > 0 And k <> t Then      'doesn't point to himself?
            dx = (rob(t).x - rob(k).x)  'X distance
            dy = (rob(t).Y - rob(k).Y)  'Y distance
            d = Sqr(dx ^ 2 + dy ^ 2)    'inter robot distance
            If d = 0 Then d = 0.01      'UUH??? prevents division by zero perhaps?
            dif = Abs(d - TLength) * 0.1  'sets strength of ties
            
            kconst = dif * klink
            
            'If d <> TLength Then
            '  If d > TLength Then
            '    If d > TLength + RobSize Then
            '      kconst = dif * klink
            '    Else
            '      kconst = dif * klink      ' 0.01 in other words
            '    End If
            '  Else
            '    If d < TLength / 2 Then
            '      kconst = dif * plink      ' 0.1 that is
            '    Else
            '      kconst = dif * klink
            '    End If
            '  End If
            'End If
            
            dxl = (dx - (TLength * dx) / d)     'gives fractional accelerations
            dyl = (dy - (TLength * dy) / d)
            rob(t).ax = rob(t).ax - kconst * dxl / rob(t).mass
            rob(t).ay = rob(t).ay - kconst * dyl / rob(t).mass
            rob(k).ax = rob(k).ax + kconst * dxl / rob(k).mass
            rob(k).ay = rob(k).ay + kconst * dyl / rob(k).mass
            
            Xdif = (rob(t).vx - rob(t).ax) - (rob(k).vx + rob(k).ax)
            Ydif = (rob(t).vy - rob(t).ay) - (rob(k).vy + rob(k).ay)
            'If rob(t).Multibot And rob(t).mem(stifftie) <> 0 Then
              If rob(t).mem(stifftie) > 40 Then rob(t).mem(stifftie) = 40
              Stiff = 40 - rob(t).mem(stifftie)
              If Abs(Xdif) > Stiff Or Abs(Ydif) > Stiff Then
              'if this works then we will be normalizing tied robot's
              'velocities to one another.
                AvgVX = (rob(t).vx + rob(k).vx) / 2
                AvgVY = (rob(t).vy + rob(k).vy) / 2
                rob(t).vx = (rob(t).vx + AvgVX) / 2
                rob(k).vx = (rob(k).vx + AvgVX) / 2
                rob(t).vy = (rob(t).vy + AvgVY) / 2
                rob(k).vy = (rob(k).vy + AvgVY) / 2
              End If
            'End If
            If Abs(rob(t).Ties(j).last) > 1 Then
              rob(t).Ties(j).last = rob(t).Ties(j).last - Sgn(rob(t).Ties(j).last)
              If rob(t).Ties(j).last > 47 And rob(t).Ties(j).last < 68 Then 'should copy the memory locations 971 to 990 from parent to child. One per cycle.
                If rob(t).mem(1038 - rob(t).Ties(j).last) = 0 And rob(rob(t).Ties(j).pnt).mem(1038 - rob(t).Ties(j).last) <> 0 Then
                  rob(t).mem(1038 - rob(t).Ties(j).last) = rob(rob(t).Ties(j).pnt).mem(1038 - rob(t).Ties(j).last)
                End If
              End If
            End If
            
            Select Case rob(t).Ties(j).last
              Case 1
                deltie t, k
              Case -2
                regang t, j
                regang k, srctie(t, k)
            End Select
            'If kl Then deltie t, k
            If d > 1000 Then
              deltie t, k ' destroys ties that get too long
              
            End If
          End If
          j = j + 1
        Wend
      End If
    End If
    Set nd = nd.pn
  Wend
  'If rob(t).ax > 10 Then rob(t).absvel = 100000 'debug crash inducing line
End Sub

Private Sub Linklen3

' calculates attraction/repulsion forces due to the ties
Private Sub LinkLen3()
  Dim k As Integer
  Dim d As Single
  Dim dx As Long
  Dim dy As Long
  Dim dxl As Single
  Dim dyl As Single
  Dim j As Integer
  Dim kconst As Single
  Dim nd As node
  Dim t As Integer
  Dim kl As Boolean
  Set nd = rlist.firstnode
  While Not nd Is rlist.last
    j = 1
    t = nd.robn
    If Not rob(t).Corpse Then       'new condition added to speed up code by not parsing corpses
      If rob(t).Numties > 0 Then    'new condition added to speed up code by not parsing robots without ties.
        While rob(t).Ties(j).pnt > 0    'Tie points to something
          k = rob(t).Ties(j).pnt        'k is the number of the robot it points to
          nlink = rob(t).Ties(j).ln + rob(t).Ties(j).shrink
          rob(t).Ties(j).shrink = 0
          If k > 0 And k <> t Then      'doesn't point to himself?
            dx = (rob(t).x - rob(k).x)
            dy = (rob(t).Y - rob(k).Y)
            d = Sqr(dx ^ 2 + dy ^ 2)    'inter robot distance
            If d = 0 Then d = 0.01      'UUH??? prevents division by zero perhaps?
            kl = False                  'and again with the UUH??
            If d > nlink Then
              If d > mlink Then
                kconst = 5 * klink
                If d > nlink * 4 Then kl = True
              Else
                kconst = klink
              End If
            Else
              If d < RobSize * 2 Then
                kconst = plink
              Else
                kconst = klink
              End If
            End If
            dxl = (dx - (nlink * dx) / d)
            dyl = (dy - (nlink * dy) / d)
            rob(t).ax = rob(t).ax - kconst * dxl
            rob(t).ay = rob(t).ay - kconst * dyl
            rob(k).ax = rob(k).ax + kconst * dxl
            rob(k).ay = rob(k).ay + kconst * dyl
            If Abs(rob(t).Ties(j).last) > 1 Then
              rob(t).Ties(j).last = rob(t).Ties(j).last - Sgn(rob(t).Ties(j).last)
            End If
            Select Case rob(t).Ties(j).last
              Case 1
                deltie t, k
              Case -2
                regang t, j
                regang k, srctie(t, k)
            End Select
            'If kl Then deltie t, k
            If d > 1000 Then deltie t, k ' destroys ties that get too long
          End If
          j = j + 1
        Wend
      End If
    End If
    Set nd = nd.pn
  Wend
  'If rob(t).ax > 10 Then rob(t).absvel = 100000 'debug crash inducing line
End Sub

Public Sub Momenti

' calculates torque generated by all ties on robots
Public Sub Momenti()
  Dim check As Single
  Dim anl As Single
  Dim dlo As Single
  Dim dx As Long
  Dim dy As Long
  Dim dist As Long
  Dim n As Integer
  Dim nd As node
  Dim t As Integer
  Dim j As Integer
  Dim mt As Single, mm As Single, m As Single
  Dim nax As Long, nay As Long
  Set nd = rlist.firstnode
  While Not (nd Is rlist.last)
    t = nd.robn
    rob(t).mt = 0
    Set nd = nd.pn
  Wend
  Set nd = rlist.firstnode
  While Not (nd Is rlist.last)
    j = 1
    mt = 0
    t = nd.robn
    With rob(t)
      If Not .Corpse Then         'condition added to prevent parsing corpses.
        If .Numties > 0 Then        'condition added to prevent parsing robots without ties.
          If .Ties(1).pnt > 0 Then
            While .Ties(j).pnt > 0
              If .Ties(j).angreg Then 'if angle is fixed.
                n = .Ties(j).pnt
                anl = angle(.x, .Y, rob(n).x, rob(n).Y) 'angle of tie in euclidian space
                dlo = AngDiff(anl, .aim) 'difference of angle of tie and direction of robot
                mm = AngDiff(dlo, .Ties(j).ang + .Ties(j).bend) 'difference of actual angle and requested angle
                .Ties(j).bend = 0 'reset bend command .tieang
                m = mm * 0.3
                dx = rob(n).x - .x
                dy = .Y - rob(n).Y
                dist = Sqr(dx ^ 2 + dy ^ 2)
                nax = -Sin(anl) * m * dist / 10
                nay = -Cos(anl) * m * dist / 10
                'experimental limits to acceleration
                If Abs(nax) > 100 Then nax = 100 * Sgn(nax)
                If Abs(nay) > 100 Then nay = 100 * Sgn(nax)
                rob(n).ax = rob(n).ax - nax
                rob(n).ay = rob(n).ay - nay
                .ax = .ax + nax
                .ay = .ay + nay
                mt = mt + mm    'in other words mt = mm for 1 tie
                If t = 10 Then
                  mt = mt
                End If
              End If
              j = j + 1
            Wend
            'If rob(t).absvel > 10 Then rob(30000).absvel = 1000000  'crash inducing line for debugging
            .ma = angnorm(mt / (j - 1))
            .aim = angnorm(.aim + .ma)
            .aimx = Cos(.aim)
            .aimy = Sin(.aim)
            '.mem(setaim) = .aim * 200
          End If
        End If
      End If
    End With
    Set nd = nd.pn
  Wend
End Sub

Public Sub LinkForce

' calculates acceleration due to the medium action on the links
' (used for swimming)
Public Sub LinkForce()
  Dim vxle As Long
  Dim vyle As Long
  Dim nd As node
  Dim t As Integer, p As Integer
  Dim j As Byte
  Dim anle As Single, anve As Single, ancm As Single
  Dim vea As Long, lle As Long
  Dim cnorm As Single
  Dim fx As Long, fy As Long
  Set nd = rlist.firstnode
  While Not (nd Is rlist.last)
    t = nd.robn
    With rob(t)
      If .Corpse = False And .Numties > 0 Then  'new conditions to prevent parsing corpses and robots without ties.
        j = 1
        While .Ties(j).pnt > 0
          p = .Ties(j).pnt
          vxle = (.vx + rob(p).vx) / 2  'average x velocity
          vyle = (.vy + rob(p).vy) / 2  'average y velocity
          anle = angle(.x, .Y, rob(p).x, rob(p).Y)  'Angle between robots
          anve = angle(0, 0, vxle, vyle)            'Angle of vector velocity
          ancm = anve - anle                        'Combined angle
          vea = Sqr(vxle ^ 2 + vyle ^ 2)            'velocity along vector
          lle = Sqr((.x - rob(p).x) ^ 2 + (.Y - rob(p).Y) ^ 2)  'distance between robots
          cnorm = Sin(ancm) * vea * lle * SimOpts.PhysSwim  'Swim force?
          fx = cnorm * Sin(anle) / 800
          fy = cnorm * Cos(anle) / 800
          .ax = .ax + fx
          .ay = .ay + fy
          rob(p).ax = rob(p).ax + fx
          rob(p).ay = rob(p).ay + fy
          j = j + 1
        Wend
      End If
    End With
    Set nd = nd.pn
  Wend
End Sub

Public Sub updpos

' updates positions, transforming calculated accelerations
' in velocities, and velocities in new positions
Public Sub updpos(ByVal n As node)
  Dim t As Integer
  Dim vt As Single, k As Single
  Dim Reduce As Single
  t = n.robn
  With rob(t)
  'If t <> moving And Not rob(t).Fixed Then
   If t <> moving Then 'plugs loophole and velocity error
    Maxspeed = 30 / (.mass / 2) 'Set maximum speed. Absolute max = 60
    
    ' friction only applied to existing velocity
    k = SimOpts.PhysFriction / 10
    If .Veg And Not .Multibot Then
      k = 0.1 + SimOpts.PhysFriction / 5 'more friction for veggies. shielded if part of a multibot
    End If
    'If .Corpse Then k = 0
    vt = 0.001 + Sqr(.vx ^ 2 + .vy ^ 2)
    'If vt < SimOpts.PhysFriction Then
    '  .vx = .vx / 10 ' I think there should still be movement possible even in high friction.
    '  .vy = .vy / 10 ' This allows a robot to move still but only at half the speed applied by acceleration.
    'Else
      .vx = .vx - (.vx / vt) * k
      .vy = .vy - (.vy / vt) * k
    'End If
    .vx = .vx + .ax
    .vy = .vy + .ay
    If SimOpts.Bouyancy Then
      .vy = .vy - .Bouyancy
    End If
    ' speed normalization
    vt = Sqr(.vx ^ 2 + .vy ^ 2)
    If vt > Maxspeed Then     'top speed limit routine 2 changed faster speeds for lower mass robots
       Reduce = vt / Maxspeed
      .vx = .vx / Reduce
      .vy = .vy / Reduce
    End If
    
    'reset acceleration to zero at end of cycle
    .ax = 0
    .ay = 0
  End If
    colls n
    bordercolls t
    
    If Not .Fixed Then
      .x = .x + .vx
      .Y = .Y + .vy
    End If
    
    'this is where we will sort of sort the robot into the array
    'perhaps use its old position to guess at its new position
    'if it's crossed a screen boundary, we have to reset its
    'position counter to something so we know we have to really go through the
    'array, starting at either end
    Dim temp As Integer
    
    On Error Resume Next
    'below is bubble-sortish
    If .order < UBound(rob()) And .order >= 0 Then
    If Roborder(.order + 1) <> -1 Then
      If (.x > rob(Roborder(.order + 1)).x) Then
       'move it on up.... to the east side!
       'we finally got a piece of the piieeeee
       While .x > rob(Roborder(.order + 1)).x
        temp = Roborder(.order + 1)
        Roborder(.order + 1) = t
        Roborder(.order) = temp
       
        .order = .order + 1
        rob(temp).order = .order - 1
        If Roborder(.order + 1) = -1 Then GoTo endloop1
       Wend
      End If
    End If
    End If
endloop1:
    
    If .order > 0 And .order <= UBound(rob()) Then
    If Roborder(.order - 1) <> -1 Then
    If .x < rob(Roborder(.order - 1)).x Then
        'move it down the list
        While .x < rob(Roborder(.order - 1)).x
       
          temp = Roborder(.order - 1)
          Roborder(.order - 1) = t
          Roborder(.order) = temp
       
          .order = .order - 1
          rob(temp).order = .order + 1
          If .order = 0 Then GoTo endloop2
        Wend
      End If
    End If
    End If
endloop2:
    
    .mem(velscalar) = Sqr(.vy ^ 2 + .vx ^ 2)
    .mem(vel) = Cos(.aim) * .vx + Sin(.aim) * .vy * -1
    .mem(veldn) = .mem(vel) * -1
    .mem(veldx) = Sin(.aim) * .vx + Cos(.aim) * .vy
    .mem(velsx) = .mem(veldx) * -1
  End With
End Sub

Private Sub bordercolls

' collisions with borders, or moves robs from one end of
' the field to the other one, if toroidal is selected
Private Sub bordercolls(t As Integer)
  If rob(t).x <= 0 Then
    If SimOpts.Dxsxconnected = True Then
      ReSpawn t, SimOpts.FieldWidth - RobSize, rob(t).Y
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).x = 0
      rob(t).vx = rob(t).vx / 2
    End If
  End If
  If rob(t).x >= SimOpts.FieldWidth - RobSize Then
    
    If SimOpts.Dxsxconnected Then
      ReSpawn t, 0, rob(t).Y
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).x = SimOpts.FieldWidth - RobSize
      rob(t).vx = rob(t).vx / 2
    End If
  End If
  If rob(t).Y <= 0 Then
    If SimOpts.Updnconnected Then
      ReSpawn t, rob(t).x, SimOpts.FieldHeight - RobSize
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).Y = 0
      rob(t).vy = rob(t).vy / 2
    End If
  End If
  If rob(t).Y >= SimOpts.FieldHeight - RobSize Then
    If SimOpts.Updnconnected Then
      ReSpawn t, rob(t).x, 0
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).Y = SimOpts.FieldHeight - RobSize
      rob(t).vy = rob(t).vy / 2
    End If
  End If
  t = t
End Sub

Private Sub bordercolls2

' collisions with borders, or moves robs from one end of
' the field to the other one, if toroidal is selected
Private Sub bordercolls2(t As Integer) 'new code that doesn't seem to work right.
  Dim x As Long
  Dim Y As Long
  
  x = rob(t).x + rob(t).vx
  Y = rob(t).Y + rob(t).vy
    
  If x < 0 Then
    If SimOpts.Dxsxconnected Then
      ReSpawn t, SimOpts.FieldWidth - RobSize, rob(t).Y
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).x = 0 '(RobSize + rob(t).Radius) / 2
      rob(t).vx = 0 'rob(t).vx / -2
    End If
  End If
  If rob(t).x > SimOpts.FieldWidth - (RobSize + rob(t).Radius) Then
    If SimOpts.Dxsxconnected Then
      ReSpawn t, 0, rob(t).Y
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).x = SimOpts.FieldWidth - (RobSize + rob(t).Radius)
      rob(t).vx = 0 'rob(t).vx / -2
    End If
  End If
  If rob(t).Y < 0 Then
    If SimOpts.Updnconnected Then
      ReSpawn t, rob(t).x, SimOpts.FieldHeight - RobSize
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).Y = 0 '(RobSize + rob(t).Radius) / 2
      rob(t).vy = 0
    End If
  End If
  If rob(t).Y > SimOpts.FieldHeight - RobSize Then
    If SimOpts.Updnconnected Then
      ReSpawn t, rob(t).x, 0
    Else
      rob(t).mem(214) = 1 'flags collision with edge of screen in mem location 510
      rob(t).Y = SimOpts.FieldHeight - (RobSize + rob(t).Radius)
      rob(t).vy = 0
    End If
  End If
  t = t
End Sub

Private Sub colls

' calculates collisions between the robot pointed by node n
' (of the robots' sorted linked list) and other robots
' and generates accelerations
Private Sub colls(n As node)
  Dim nd As node
  Dim t As Integer
  Dim a As Integer
  Dim dist As Long
  Dim tvx As Long, tvy As Long
  Dim slowdown As Single
  Dim angl As Single
  Dim aPer As Single
  Dim tPer As Single
  Dim aM As Single
  Dim tM As Single
  Dim totM As Single
  Dim colldist As Long
  Dim colldistsquared As Long
  Dim deltax As Long
  Dim deltay As Long
  Dim deltaxsquare As Long
  Dim deltaysquare As Long
  Dim maxdist As Integer
  Dim otherrobot As Integer
  Dim xpos As Long
    
  slowdown = 0.8
  
  On Error Resume Next
  
  t = n.robn
  xpos = n.xpos
  maxdist = RobSize * 2 + Half
  Set nd = rlist.firstprox(n, maxdist)
  otherrobot = rob(nd.robn).order
  
  If Roborder(otherrobot) = -1 Then Exit Sub
  
  While rob(Roborder(otherrobot)).x < xpos + maxdist
    a = Roborder(otherrobot)
    If t <> a Then
      colldist = RobSize + rob(t).Radius + rob(a).Radius
      colldistsquared = colldist * colldist 'so we don't need the sqr
      
      deltax = rob(t).x - rob(a).x
      If Abs(deltax) > colldist Then GoTo bypass1
      deltay = rob(t).Y - rob(a).Y
      If Abs(deltay) > colldist Then GoTo bypass1
      
      deltaxsquare = deltax * deltax
      deltaysquare = deltay * deltay
      If deltaxsquare + deltaysquare > colldistsquared Then GoTo bypass1
      
        repel a, t
        touch t, rob(a).x + Half, rob(a).Y + Half
        touch a, rob(t).x + Half, rob(t).Y + Half
        GoTo bypass
      'End If
bypass1:
    
    'PLEASE don't delete this
    'this was Numsgil's attempt at physics
    'there might still be some useful bits here and there
    
    'deltax = deltax + rob(t).vx - rob(a).vx
    'If deltax > colldist Then GoTo bypass
    '
    'deltay = deltay + rob(t).vy - rob(a).vy
    'If deltay > colldist Then GoTo bypass
    '
    'deltaxsquare = deltax * deltax
    'deltaysquare = deltay * deltay
    '
    'If deltaxsquare + deltaysquare <= colldistsquared Then
    '
    '  dist = Sqr(deltaxsquare + deltaysquare)
    '  If dist = 0 Then GoTo bypass
    '
    '  Dim deltaxsingle As Single
    '  Dim deltaysingle As Single
    '
    '  deltaxsingle = deltax
    '  deltaysingle = deltay
    '
    '  deltaxsingle = deltaxsingle / dist
    '  deltaysingle = deltaysingle / dist
    '
    '  Dim tabx As Single
    '  Dim taby As Single
    '
    '  tabx = -deltaysingle
    '  taby = deltaxsingle
    '
    '  Dim vait As Single
    '  vait = rob(a).vx * tabx + rob(a).vy * taby

    '  Dim vain As Single
    '  vain = rob(a).vx * deltaxsingle + rob(a).vy * deltaysingle

    '  Dim vbit As Single
    '  vbit = rob(t).vx * tabx + rob(t).vy * taby

    '  Dim vbin As Single
    '  vbin = rob(t).vx * deltaxsingle + rob(t).vy * deltaysingle

    '  Dim ma As Single
    '  ma = rob(a).mass
    '  If rob(a).Fixed Then ma = 1000000

    '  Dim mb As Single
    '  mb = rob(t).mass
    '  If rob(t).Fixed Then mb = 1000000

    '  Dim vafn As Single
    '  vafn = (mb * vbin * (cof_E + 1) + vain * (ma - cof_E * mb)) / (ma + mb)

    '  Dim vbfn As Single
    '  vbfn = (ma * vain * (cof_E + 1) - vbin * (ma - cof_E * mb)) / (ma + mb)

    '  Dim vaft As Single
    '  vaft = vait

    '  Dim vbft As Single
    '  vbft = vbit

    '  Dim xfa As Single
    '  xfa = vafn * deltaxsingle + vaft * tabx

    '  Dim yfa As Single
    '  yfa = vafn * deltaysingle + vaft * taby

    '  Dim xfb As Single
    '  xfb = vbfn * deltaxsingle + vbft * tabx

    '  Dim yfb As Single
    '  yfb = vbfn * deltaysingle + vbft * taby

    '  If Sqr(xfa ^ 2 + yfa ^ 2) > 60 Then
    '    'normalize * maxspeed
    '  End If

    '  If Sqr(xfb ^ 2 + yfb ^ 2) > 60 Then
    '    'normalize * maxspeed
    '  End If

    '  rob(a).vx = xfa
    '  rob(a).vy = yfa

    '  rob(t).vx = xfb
    '  rob(t).vy = yfb
   'End If
bypass:
    End If
    'Set nd = rlist.nextorder(nd)
    otherrobot = otherrobot + 1
    If Roborder(otherrobot) = -1 Then
      Exit Sub
    End If
  Wend
End Sub

Private Sub repel

' gives to too near robots an accelaration towards
' opposite directions, inversely prop. to their distance
Private Sub repel(k As Integer, t As Integer)
 Dim d As Single
 Dim dx As Integer
 Dim dy As Integer
 Dim dxlk As Single
 Dim dylk As Single
 Dim dxlt As Single
 Dim dylt As Single
 Dim kconst As Single
 Dim llink As Single
 Dim accel As Long  'new acceleration to apply
 Dim difKE As Long
 
 Dim maxcel As Single
 Dim angl1 As Single
 Dim angl2 As Single
 Dim colldist As Integer
 Dim totx As Single 'total x velocity
 Dim toty As Single 'total y velocity
 Dim totv As Single 'total absolute velocity
 Dim totaccel As Single
 Dim decell As Single
 Dim kmovx As Single
 Dim kmovy As Single
 Dim tmovx As Single
 Dim tmovy As Single
 Dim kKE As Single
 Dim tKE As Single
 Dim kxm As Single   'robot k x momentum
 Dim kym As Single   'robot k y momentum
 Dim txm As Single   'robot t x momentum
 Dim tym As Single   'robot t y momentum
 Dim xmean As Single  'Mean of both x momentums
 Dim ymean As Single  'Mean of both y momentums
 
 Dim totKE As Single
 Dim kPer As Single    'percentage of acceleration to give to robot k based on mass
 Dim tPer As Single    'same for robot t
 Dim moveaway As Single  'The amount to directly move a robot away from a collision
 
 'If xmoveaway(k, t) Then GoTo bypass2
 'If ymoveaway(k, t) Then GoTo bypass2
 
 dx = (rob(t).x - rob(k).x)
 dy = (rob(t).Y - rob(k).Y)
 colldist = RobSize + (rob(k).body / factor + rob(t).body / factor) 'amount of overlap based on size of robot
 d = Sqr(dx ^ 2 + dy ^ 2) + 0.01   'inter-robot distance
 
 decell = 1
 maxcel = 40
 'GoTo bypass2
 kKE = rob(k).mass * rob(k).vx + rob(k).mass * rob(k).vy
 tKE = rob(t).mass * rob(t).vx + rob(t).mass * rob(t).vy
 kxm = rob(k).mass * rob(k).vx     'rob(k) x momentum signed
 kym = rob(k).mass * rob(k).vy     'rob(k) y momentum signed
 txm = rob(t).mass * rob(t).vx     'rob(t) x momentum signed
 tym = rob(t).mass * rob(t).vy     'rob(t) y momentum signed
 xmean = (Abs(kxm) + Abs(txm)) / 2 'absolute mean of x momentums. Both counted as positive
 ymean = (Abs(kym) + Abs(tym)) / 2 'absolute mean of y momentums. Both counted as positive
 If rob(k).mass = 0 Then rob(k).mass = 0.01
 rob(k).vx = rob(k).vx + (xmean / rob(k).mass) * kxColdir(k, t) * decell
 rob(t).vx = rob(t).vx + (xmean / rob(t).mass) * txColdir(k, t) * decell
 rob(k).vy = rob(k).vy + (ymean / rob(k).mass) * kyColdir(k, t) * decell
 rob(t).vy = rob(t).vy + (ymean / rob(t).mass) * tyColdir(k, t) * decell
 
 Maxspeed = 30 / (rob(t).mass / 2)
 totv = Sqr(rob(t).vx ^ 2 + rob(t).vy ^ 2)
 If totv > Maxspeed Then     'top speed limit routine 2 changed faster speeds for lower mass robots
   maxcel = totv / Maxspeed
   rob(t).vx = rob(t).vx / maxcel
   rob(t).vy = rob(t).vy / maxcel
 End If
 Maxspeed = 30 / (rob(k).mass / 2)
 totv = Sqr(rob(k).vx ^ 2 + rob(k).vy ^ 2)
 If totv > Maxspeed Then     'top speed limit routine 2 changed faster speeds for lower mass robots
   maxcel = totv / Maxspeed
   rob(k).vx = rob(k).vx / maxcel
   rob(k).vy = rob(k).vy / maxcel
 End If
 
bypass2:
 'totKE = tKE + kKE   'calculates total momentum of both robots
 'difKE = kKE - tKE   'difference in momentum
 
 'tPer = rob(k).mass / (rob(k).mass + rob(t).mass)  'percentage of total momentum in bot k
 'kPer = rob(t).mass / (rob(k).mass + rob(t).mass)  'percentage of total momentum in bot t
   
 'If rob(k).vx = 0 Then rob(k).vx = 0.00001
 'If rob(t).vx = 0 Then rob(t).vx = 0.00001
 'mvanglt = Atn(rob(k).vy / rob(k).vx)
 'mvangla = Atn(rob(t).vy / rob(t).vx)
 'angledifference = angnorm(AngDiff(mvanglt, angl))
 'exitangle = angnorm(angl - angledifference)
 'newvx = (rob(k).vx + rob(t).vx) * (rob(t).mass / (rob(k).mass + rob(t).mass))
 'newvy = (rob(k).vy + rob(t).vy) * (rob(t).mass / (rob(k).mass + rob(t).mass))
 'newvx = newvx * 0.95
 'newvy = newvy * 0.95
 'llink = 1000
 
 'totx = Abs(rob(k).vx) + Abs(rob(t).vx)
 'totx = rob(k).vx + rob(t).vx
 'toty = Abs(rob(k).vy) + Abs(rob(t).vy)
 'toty = rob(k).vy + rob(t).vy
 'totv = totx + toty
   
 angl1 = angle(rob(k).x, rob(k).Y, rob(t).x, rob(t).Y) 'angle from rob k to rob t
 angl2 = angle(rob(t).x, rob(t).Y, rob(k).x, rob(k).Y) 'angle from rob t to rob k
 'colldist = colldist * 1.2
 
 'dxlk = absx(angl1, totKE, 0, 0, 0) * tPer
 'dylk = absy(angl1, totKE, 0, 0, 0) * tPer
 'dxlt = absx(angl2, totKE, 0, 0, 0) * kPer
 'dylt = absy(angl2, totKE, 0, 0, 0) * kPer
 'totaccel = Abs(dxl) + Abs(dyl)
 
 'kconst = 0.01
 'dxl = (dx - (llink * dx) / d)
 'dyl = (dy - (llink * dy) / d)
 moveaway = (colldist - d) / 2 'move away based on half of overlap
 If d < colldist Then
   kmovx = absx(angl1, moveaway, 0, 0, 0)
   kmovy = absy(angl1, moveaway, 0, 0, 0)
   tmovx = absx(angl2, moveaway, 0, 0, 0)
   tmovy = absy(angl2, moveaway, 0, 0, 0)
   If Not rob(t).Fixed Then
     rob(t).x = rob(t).x - tmovx
     rob(t).Y = rob(t).Y - tmovy
   End If
   If Not rob(k).Fixed Then
     rob(k).x = rob(k).x - kmovx
     rob(k).Y = rob(k).Y - kmovy
   End If
 Else
   kmovx = 0
   kmovy = 0
   tmovx = 0
   tmovy = 0
 End If
bypass3:
End Sub

Private Function kxColdir

Private Function kxColdir(k As Integer, t As Integer)
  If rob(k).x < rob(t).x Then
    kxColdir = -1
  Else
    kxColdir = 1
  End If
End Function

Private Function kyColdir

Private Function kyColdir(k As Integer, t As Integer)
If rob(k).Y < rob(t).Y Then
    kyColdir = -1
  Else
    kyColdir = 1
  End If
End Function

Private Function txColdir

Private Function txColdir(k As Integer, t As Integer)
If rob(t).x < rob(k).x Then
    txColdir = -1
  Else
    txColdir = 1
  End If
End Function

Private Function tyColdir

Private Function tyColdir(k As Integer, t As Integer)
If rob(t).Y < rob(k).Y Then
    tyColdir = -1
  Else
    tyColdir = 1
  End If
End Function

Private Function xmoveaway

Private Function xmoveaway(k As Integer, t As Integer) As Boolean
  If Sgn(rob(k).vx) = Sgn(rob(t).vx) Then 'both moving the same way
    If rob(k).x < rob(t).x Then           'rob(k) is to the left
      If Sgn(rob(k).vx) = 1 Then          'rob(k) moving to the right
        If rob(k).vx < rob(t).vx Then     'rob(k) moving slower than rob(t)
          xmoveaway = True                'moving away
        Else
          xmoveaway = False               'not moving away
        End If
      Else                                'rob(k) moving to the left
        If rob(k).vx > rob(t).vx Then     'rob(k) moving faster than rob(t)
          xmoveaway = True                'moving away
        Else
          xmoveaway = False               'not moving away
        End If
      End If
    Else                                  'rob(k) is NOT to the left (right or level)
      If Sgn(rob(k).vx) = 1 Then          'rob(k) moving to the right
        If rob(k).vx > rob(t).vx Then     'rob(k) moving faster than rob(t)
          xmoveaway = True                'moving away
        Else
          xmoveaway = False               'not moving away
        End If
      Else                                'rob(k) moving to the left
        If rob(k).vx < rob(t).vx Then     'rob(k) moving faster than rob(t)
          xmoveaway = True                'moving away
        Else
          xmoveaway = False               'not moving away
        End If
      End If
    End If
  Else                                    'robots moving opposite directions
    If rob(k).x < rob(t).x Then           'rob(k) is to the left
      If Sgn(rob(k).vx) = 1 Then          'rob(k) moving to the right
        xmoveaway = False
      Else                                'rob(k) moving to the left
        xmoveaway = True
      End If
    Else                                  'rob(k) is to the right or level
      If Sgn(rob(k).vx) = 1 Then          'rob(k) moving to the right
        xmoveaway = True                  'must be moving away
      Else                                'rob(k) moving to the left
        xmoveaway = False                 'must be moving towards
      End If
    End If
  End If
End Function

Private Function ymoveaway

Private Function ymoveaway(k As Integer, t As Integer) As Boolean
If Sgn(rob(k).vy) = Sgn(rob(t).vy) Then   'both moving the same way
    If rob(k).Y < rob(t).Y Then           'rob(k) is to the top
      If Sgn(rob(k).vy) = 1 Then          'rob(k) moving to the bottom
        If rob(k).vy < rob(t).vy Then     'rob(k) moving slower than rob(t)
          ymoveaway = True                'moving away
        Else
          ymoveaway = False               'not moving away
        End If
      Else                                'rob(k) moving to the left
        If rob(k).vy > rob(t).vy Then     'rob(k) moving faster than rob(t)
          ymoveaway = True                'moving away
        Else
          ymoveaway = False               'not moving away
        End If
      End If
    Else                                  'rob(k) is NOT to the left (right or level)
      If Sgn(rob(k).vy) = 1 Then          'rob(k) moving to the bottom
        If rob(k).vy > rob(t).vy Then     'rob(k) moving faster than rob(t)
          ymoveaway = True                'moving away
        Else
          ymoveaway = False               'not moving away
        End If
      Else                                'rob(k) moving to the top
        If rob(k).vy < rob(t).vy Then     'rob(k) moving faster than rob(t)
          ymoveaway = True                'moving away
        Else
          ymoveaway = False               'not moving away
        End If
      End If
    End If
  Else                                    'robots moving opposite directions
    If rob(k).Y < rob(t).Y Then           'rob(k) is to the top
      If Sgn(rob(k).vy) = 1 Then          'rob(k) moving to the bottom
        ymoveaway = False
      Else                                'rob(k) moving to the top
        ymoveaway = True
      End If
    Else                                  'rob(k) is to the right or level
      If Sgn(rob(k).vy) = 1 Then          'rob(k) moving to the bottom
        ymoveaway = True                  'must be moving away
      Else                                'rob(k) moving to the top
        ymoveaway = False                 'must be moving towards
      End If
    End If
  End If
End Function