' 0.42 '' Nanoships AI module '' coderJeff_AI.bi - May 2006 - version 1.1 '' '' Requires NanoShips 0.41 or higher '' - Get NanoShips here: http://ecowles.dyndns.org/Nano '' '' Contact info for coderJeff: '' coderJeff@execulink.com '' http://frontpage.execulink.com/coder/ '' '' This file: '' http://www.execulink.com/~coder/nanoships/coderJeff_AI.bi '' type coderJeff_V2 x as double y as double end type type coderJeff_L2 n as coderJeff_V2 d as double end type type coderJeff_brain state as integer '' current state, 1 = init'd toggle as integer '' 1/0 flip each cycle IsEnemyNear as integer IsLaserThreat as integer sp as coderJeff_V2 '' Ship position sh as coderJeff_V2 '' Ship Heading sv as coderJeff_V2 '' Ship Velocity sd as coderJeff_V2 '' Ship Unit Velocity rst as coderJeff_V2 '' Relative ship target (missle lock) mv as coderJeff_V2 '' Missle Velocity mp as coderJeff_V2 '' Estimated Missle Position aep as coderJeff_V2 '' Actual Enemy position ep as coderJeff_V2 '' Enemy position ev as coderJeff_V2 '' Enemy Velocity ed as coderJeff_V2 '' Enemy Unit Velocity rep as coderJeff_V2 '' Relative Enemy position red as coderJeff_V2 '' Relative Enemy direction rev as coderJeff_V2 '' Relative Enemy Velocity IsTargetActive as integer ret as coderJeff_V2 '' Relative Enemy Target Position (estimate) IsLaserActive as integer lp as coderJeff_V2 '' Laser Position lv as coderJeff_V2 '' Laser Velocity ld as coderJeff_V2 '' Laser Unit Velocity lf as coderJeff_L2 '' Laser Forward line equation ls as coderJeff_L2 '' Laser Side line equation rlp as coderJeff_V2 '' Relative Laser position rlv as coderJeff_V2 '' Relative Laser Velocity rld as coderJeff_V2 '' Relative Laser Direction end type private sub coderJeff_VSet(byref v as coderJeff_V2, byval x as double, byval y as double) v.x = x v.y = y end sub private function coderJeff_VDot(byref a as coderJeff_V2, byref b as coderJeff_V2) as double return ( a.x * b.x + a.y * b.y ) end function private function coderJeff_VPerpDot(byref a as coderJeff_V2, byref b as coderJeff_V2) as double return ( a.x * b.y - a.y * b.x ) end function private function coderJeff_VMag(byref v as coderJeff_V2) as double return sqr( v.x * v.x + v.y * v.y) end function private sub coderJeff_VMul(byref v as coderJeff_V2, byval k as double, byref b as coderJeff_V2) v.x = k * b.x v.y = k * b.y end sub private sub coderJeff_VSub(byref v as coderJeff_V2, a as coderJeff_V2, byref b as coderJeff_V2) v.x = a.x - b.x v.y = a.y - b.y end sub private function coderJeff_VDist(byref a as coderJeff_V2, byref b as coderJeff_V2) as double return sqr( (a.x - b.x)^2 + (a.y - b.y)^2 ) end function FUNCTION coderJeff_AI ( BYVAL ShipData AS ShipData, _ Flag() AS DOUBLE) AS MessageAI DIM AS MessageAI ReturnAI '' flags '' 0 - mode '' 1 - my last x '' 2 - my last y '' 3 - enemy last x '' 4 - enemy last y '' 5 - last laser x '' 6 - last laser y '' 7 - 100 cycle timer '' 8 - enemy last vx '' 9 - enemy last vy dim as coderJeff_brain t dim as coderJeff_V2 v dim as double d, d1, d2, s1, s2 ReturnAI.Action = IDLE ReturnAI.Message = " " if flag(0) = 0 then flag(0) = 1 flag(7) = 99 ReturnAI.Message = "Starting main reactor ..." ReturnAI.Action = THRUST RETURN ReturnAI end if flag(7) -= 1 if flag(7) < 0 then flag(7) = 99 end if with t .state = flag(0) .toggle = (flag(7) mod 2) <> 0 .IsEnemyNear = 0 .IsLaserThreat = 0 coderJeff_VSet .sp, ShipData.PosX, ShipData.PosY coderJeff_VSet .sh, cos( ShipData.Angle * Radians ), sin( ShipData.Angle * Radians ) coderJeff_VSet .sv, (ShipData.PosX - flag(1)), (ShipData.PosY - flag(2)) coderJeff_VMul .sd, 1/coderJeff_VMag(.sv), .sv coderJeff_VMul .mv, 1.0, .sh coderJeff_VSet .aep, ShipData.EnemyX, ShipData.EnemyY coderJeff_VSet .ep, ShipData.EnemyX, ShipData.EnemyY if abs(.sp.x - .ep.x) > SCRW / 2 then .ep.x += SCRW * sgn(.sp.x - .ep.x) end if if abs(.sp.y - .ep.y) > SCRH / 2 then .ep.y += SCRH * sgn(.sp.y - .ep.y) end if coderJeff_VSet .ev, ((ShipData.EnemyX - flag(3))), ((ShipData.EnemyY - flag(4))) 'coderJeff_VSet .ev, ((ShipData.EnemyX - flag(3))+flag(8))/2, ((ShipData.EnemyY - flag(4))+flag(9))/2 coderJeff_VMul .ed, 1/coderJeff_VMag(.ev), .ev coderJeff_VSub( .rep, .ep, .sp ) coderJeff_VSub( .rev, .ev, .sv ) coderJeff_VMul .red, 1/coderJeff_VMag(.rep), .rep .IsTargetActive = 0 if (ShipData.LaserX <> -1) and (flag(5) <> - 1) then .IsLaserActive = 1 coderJeff_VSet .lp, ShipData.LaserX, ShipData.LaserY coderJeff_VSet .lv, (ShipData.LaserX - flag(5)), (ShipData.LaserY - flag(6)) coderJeff_VMul .ld, 1/coderJeff_VMag(.lv), .lv .lf.n = .ld .lf.d = -coderJeff_VDot(.lp, .lf.n) .ls.n.x = -.ld.y .ls.n.y = .ld.x .ls.d = -coderJeff_VDot(.lp, .ls.n) coderJeff_VSub( .rlp, .lp, .sp ) coderJeff_VSub( .rlv, .lv, .sv ) coderJeff_VMul .rld, -1/coderJeff_VMag(.rlp), .rlp else .IsLaserActive = 0 end if end with '' check for enemy lasers with t ReturnAI.Message = "Scanning .." if( ReturnAI.Action = IDLE ) then if .IsLaserActive then ReturnAI.Message = "Monitoring Threat .." d1 = -coderJeff_VPerpDot( .lv, .rlp ) d2 = coderJeff_VPerpDot( .lv, .sd ) if d2 <> 0 then s1 = -d1 / d2 .rst.x = s1 * .sv.x '- .rlp.x .rst.y = s1 * .sv.y '- .rlp.y d1 = -coderJeff_VPerpDot( .sd, .rlp ) d2 = coderJeff_VPerpDot( .sd, .lv ) if d2 <> 0 then s2 = -d1 / d2 if s1 >= 0 and s2 >= 0 and s1 <= 100 then .IsTargetActive = 1 if (abs(s2 - s1) <= 2) then ReturnAI.Message = "Missle lock detected!" .IslaserThreat = 3 end if end if end if end if if .IslaserThreat = 0 then d = coderJeff_VDot( .lf.n, .sp ) + .lf.d + 10 if d > 0 then ReturnAI.Message = "Monitoring Threat ..." d = coderJeff_VDot( .ls.n, .sp ) + .ls.d if (abs(d) < 60) then s2 = coderJeff_VMag( .rlp ) / coderJeff_VMag( .lv ) if s2 < 250 then ReturnAI.Message = "Incoming!" .IslaserThreat = 1 end if end if end if end if if .IslaserThreat <> 0 then d = coderJeff_VDot( .rlv, .rlp ) if d < 0 then s2 = coderJeff_VMag( .rlp ) / coderJeff_VMag( .lv ) if s2 < 200 then ReturnAI.Message = "Proximity Alert!" .IslaserThreat = 2 end if end if end if end if if .IsLaserThreat = 1 or .IsLaserThreat = 3 then d = coderJeff_VDot( .lf.n, .sh ) d2 = coderJeff_VPerpDot( .lf.n, .sh ) 'if (t.toggle) then if d < -0.7 then if d2 < 0 then ReturnAI.Action = TURNCW else ReturnAI.Action = TURNCCW end if elseif d > 0.7 then if d2 < 0 then ReturnAI.Action = TURNCCW else ReturnAI.Action = TURNCW end if end if 'end if if( ReturnAI.Action = IDLE ) then if d < -0.8 then ReturnAI.Action = BACKTHRUST elseif d > 0.8 then ReturnAI.Action = THRUST else if d < 0 then ReturnAI.Action = BACKTHRUST else ReturnAI.Action = THRUST end if end if end if elseif .IsLaserThreat = 2 then d = coderJeff_VDot( .rlv, .sh ) if abs(d) < 0.01 then d = coderJeff_VDot( .lf.n, .sp ) + .lf.d if d < 0 then d = coderJeff_VDot( .ls.n, .sp ) + .ls.d if d < 0 then ReturnAI.Action = TURNCCW else ReturnAI.Action = TURNCW end if else d = coderJeff_VDot( .ls.n, .sp ) + .ls.d if d < 0 then ReturnAI.Action = TURNCW else ReturnAI.Action = TURNCCW end if end if else if d < 0 then ReturnAI.Action = BACKTHRUST else ReturnAI.Action = THRUST end if end if end if end if end with '' search for and fire on target with t ReturnAI.Message = "Range Finding ..." if( ReturnAI.Action = IDLE ) then '' Slow moving enemy if coderJeff_VMag( .ev ) <= 0.2 then s2 = coderJeff_VMag( .rep ) / coderJeff_VMag( .mv ) .ret.x = s2 * .ev.x + .rep.x .ret.y = s2 * .ev.y + .rep.y .mp.x = s2 * .mv.x .mp.y = s2 * .mv.y .IsTargetActive = 1 if (coderJeff_VDist( .ret, .mp ) < 8) and (shipdata.power > 10) then ReturnAI.Message = "Fire!" ReturnAI.Action = SHOOT end if end if end if if( ReturnAI.Action = IDLE ) then '' close proximity d = coderJeff_VMag( .rep ) if d < 100 then s2 = coderJeff_VMag( .rep ) / coderJeff_VMag( .mv ) .ret.x = s2 * .ev.x + .rep.x .ret.y = s2 * .ev.y + .rep.y .mp.x = s2 * .mv.x .mp.y = s2 * .mv.y .IsTargetActive = 1 if coderJeff_VDist( .ret, .mp ) < 8 then ReturnAI.Message = "Fire!" ReturnAI.Action = SHOOT end if end if end if if( ReturnAI.Action = IDLE ) then '' Standard Targetting d1 = coderJeff_VPerpDot( .mv, .rep ) d2 = coderJeff_VPerpDot( .mv, .ev ) if d2 <> 0 then s1 = -d1 / d2 .ret.x = s1 * .ev.x + .rep.x .ret.y = s1 * .ev.y + .rep.y d1 = -coderJeff_VPerpDot( .ed, .rep ) d2 = coderJeff_VPerpDot( .ed, .mv ) if d2 <> 0 then s2 = -d1 / d2 if s1 >= 0 and s2 >= 0 and s1 <= LASER_RANGE then .IsTargetActive = 1 if (abs(s2 - s1) <= 2) and (ShipData.power > 30) then ReturnAI.Message = "Fire!" ReturnAI.Action = SHOOT end if end if end if end if end if '' Guess a target if( ReturnAI.Action = IDLE ) then s2 = coderJeff_VMag( .rep ) / coderJeff_VMag( .mv ) .ret.x = s2 * .ev.x + .rep.x .ret.y = s2 * .ev.y + .rep.y .IsTargetActive = 1 end if end with with t if( ReturnAI.Action = IDLE ) then ReturnAI.Message = "Scanning ..." d = coderJeff_VDist( .sp, .ep ) if d < 125 then ReturnAI.Message = "Enemy is near" d = coderJeff_VDot( .rep, .rev ) if d < 0 then ReturnAI.Message = "Enemy is approaching" d = coderJeff_VDot( .red, .rev ) if d < -1.5 then ReturnAI.Action = THRUST elseif d > 1.5 then ReturnAI.Action = BACKTHRUST end if end if end if end if end with '' turn to face target/enemy with t if( ReturnAI.Action = IDLE ) then ReturnAI.Message = "Tactical Maneuvers ..." if .IsTargetActive then d = coderJeff_VPerpDot( .sh, .ret ) d1 = coderJeff_VMag( .ret ) d2 = coderJeff_VDot( .rev, .sh ) else d = coderJeff_VPerpDot( .sh, .rep ) d1 = coderJeff_VMag( .rep ) d2 = coderJeff_VDot( .rev, .sh ) end if if d < -0.1 then ReturnAI.Action = TURNCCW elseif d > 0.1 then ReturnAI.Action = TURNCW else d = coderJeff_VPerpDot( .sh, .rep ) d1 = coderJeff_VMag( .rep ) d2 = coderJeff_VDot( .rev, .sh ) if (d1 < 100) or (d1 > 250) then if d < 0 then ReturnAI.Action = BACKTHRUST elseif d > 0 then ReturnAI.Action = THRUST end if end if end if end if end with '' Save Values flag(0) = t.state flag(8) = t.ev.x flag(9) = t.ev.y with shipdata flag(1) = .PosX flag(2) = .PosY flag(3) = .EnemyX flag(4) = .EnemyY flag(5) = .LaserX flag(6) = .LaserY end with if ReturnAI.Action = IDLE = SHOOT then ReturnAI.Action = IDLE end if RETURN ReturnAI END FUNCTION private sub coderJeff_LocalPointToWorld(byref v as coderJeff_V2, byref p as coderJeff_V2, h as coderJeff_V2, byval x as double, byval y as double) v.x = h.x * x - h.y * y + p.x v.y = h.y * x + h.x * y + p.y end sub FUNCTION coderJeff_DrawLaser ( BYVAL LaserData AS DrawLaserData ) AS INTEGER #define coderJeff_Pset(_x, _y, _c) coderJeff_LocalPointToWorld v, p, h, (_x), (_y): Pset (v.x, v.y), _c #define coderJeff_Line(_x, _y, _c) coderJeff_LocalPointToWorld v, p, h, (_x), (_y): Line -(v.x, v.y), _c '' PosX, PosY, Angle, Colour dim as coderJeff_V2 h, v, p With LaserData coderJeff_Vset p, .PosX + 3 * cos(.Angle*RADIANS), .PosY + 3 * sin(.Angle*RADIANS) coderJeff_Vset h, sin(.Life * 0.1 + .Angle*RADIANS), -cos(.Life* 0.1 + .Angle*RADIANS) End With coderJeff_Pset( -3, 0, 14 ) coderJeff_Line( 3, 0, 14 ) coderJeff_Line( 0, -3, 14 ) coderJeff_Line( 0, 3, 14 ) coderJeff_Line( -2, -2, 12 ) coderJeff_Line( 2, 2, 12 ) coderJeff_Line( -2, 2, 12 ) coderJeff_Line( 2, -2, 12 ) #undef coderJeff_Pset #undef coderJeff_Line END FUNCTION FUNCTION coderJeff_DrawShip ( BYVAL ShipData AS DrawShipData ) AS INTEGER #define coderJeff_Pset(_x, _y, _c) coderJeff_LocalPointToWorld v, p, h, (_x), (_y): Pset (v.x, v.y), _c #define coderJeff_Line(_x, _y, _c) coderJeff_LocalPointToWorld v, p, h, (_x), (_y): Line -(v.x, v.y), _c static as integer iThrust=0, iLThrust=0, iRThrust=0, iShoot=0, iBThrustL=0, iBThrustR=0 static as integer cntr=0 dim as coderJeff_V2 h, v, p dim as double scx cntr -= 1 if cntr < 0 then cntr = 1000 end if select case ShipData.Action case THRUST iThrust = 32 case BACKTHRUST iBThrustL = 10 iBThrustR = 10 case TURNCCW iLThrust = 2 case TURNCW iRThrust = 2 case SHOOT iShoot = 10 end select if iLThrust <> 0 and iRThrust <> 0 then iLThrust = 0 iRThrust = 0 end if with ShipData coderJeff_Vset p, .PosX + 3 * cos(.Angle*RADIANS), .PosY + 3 * sin(.Angle*RADIANS) coderJeff_Vset h, sin(.Angle * RADIANS), -cos(.Angle * RADIANS) ''Body coderJeff_Pset( 0.0, 8.0, .Colour ) coderJeff_Line( 3.0, 5.0, .Colour ) coderJeff_Line( 1.5, 3.5, .Colour ) coderJeff_Line( 2.0, -7.0, .Colour ) coderJeff_Line( 0.0, -8.0, .Colour ) coderJeff_Line( -2.0, -7.0, .Colour ) coderJeff_Line( -1.5, 3.5, .Colour ) coderJeff_Line( -3.0, 5.0, .Colour ) coderJeff_Line( 0.0, 8.0, .Colour ) ''Wing coderJeff_Pset( 1.5, 0.0, .Colour) coderJeff_Line( 7.0, 1.0, .Colour) coderJeff_Line( 8.0, -1.0, .Colour) coderJeff_Line( 2.0, -7.0, .Colour) ''Wing coderJeff_Pset( -1.5, 0.0, .Colour) coderJeff_Line( -7.0, 1.0, .Colour) coderJeff_Line( -8.0, -1.0, .Colour) coderJeff_Line( -2.0, -7.0, .Colour) if iThrust then scx = 0.1 * iThrust coderJeff_Pset( 0.0, -8.0 - 0.0 * scx, 12 ) coderJeff_Line( 1.0, -8.0 - 2.0 * scx, 12) coderJeff_Line( 0.0, -8.0 - 7.0 * scx, 12) coderJeff_Line( -1.0, -8.0 - 2.0 * scx, 12) coderJeff_Line( 0.0, -8.0 - 0.0 * scx, 12) coderJeff_Pset( 0.0, -8.0 - 1.0 * scx, 14) coderJeff_Line( 0.0, -8.0 - 6.0 * scx, 14) iThrust -= 1 end if if iBThrustR then scx = 0.2 * iBThrustR coderJeff_Pset( 7.0, 1.0 + 0.0 * scx, 12) coderJeff_Line( 8.0, 1.0 + 1.0 * scx, 12) coderJeff_Line( 7.0, 1.0 + 4.0 * scx, 12) coderJeff_Line( 6.0, 1.0 + 1.0 * scx, 12) coderJeff_Line( 7.0, 1.0 + 0.0 * scx, 12) coderJeff_Pset( 7.0, 1.0 + 1.0 * scx, 14) coderJeff_Line( 7.0, 1.0 + 3.0 * scx, 14) iBThrustR -= 1 end if if iBThrustL then scx = 0.2 * iBThrustL coderJeff_Pset( -7.0, 1.0 + 0.0 * scx, 12) coderJeff_Line( -8.0, 1.0 + 1.0 * scx, 12) coderJeff_Line( -7.0, 1.0 + 4.0 * scx, 12) coderJeff_Line( -6.0, 1.0 + 1.0 * scx, 12) coderJeff_Line( -7.0, 1.0 + 0.0 * scx, 12) coderJeff_Pset( -7.0, 1.0 + 1.0 * scx, 14) coderJeff_Line( -7.0, 1.0 + 3.0 * scx, 14) iBThrustL -= 1 end if if iRThrust then coderJeff_Pset( 3.0, 5.0, 12) coderJeff_Line( 4.0, 6.0, 12) coderJeff_Line( 6.0, 5.0, 12) coderJeff_Line( 4.0, 4.0, 12) coderJeff_Line( 3.0, 5.0, 12) coderJeff_Pset( 4.0, 5.0, 14) coderJeff_Line( 5.0, 5.0, 14) iRThrust -= 1 end if if iLThrust then coderJeff_Pset( -3.0, 5.0, 12) coderJeff_Line( -4.0, 6.0, 12) coderJeff_Line( -6.0, 5.0, 12) coderJeff_Line( -4.0, 4.0, 12) coderJeff_Line( -3.0, 5.0, 12) coderJeff_Pset( -4.0, 5.0, 14) coderJeff_Line( -5.0, 5.0, 14) iLThrust -= 1 end if end with #undef coderJeff_Pset #undef coderJeff_Line END FUNCTION AI( AI_ID ).Callsign = "coderJeff" AI( AI_ID ).Colour = 10 AI( AI_ID ).AI = @coderJeff_AI AI(AI_ID).DrawShip = @coderJeff_DrawShip AI(AI_ID).DrawLaser = @coderJeff_DrawLaser AI(AI_ID).WeaponName = "Fireball Accelerator" AI(AI_ID).ShipDetails = _ "A Massive cannon, powerful main rocket motor, four auxillary maneuvering thrusters and an " & _ "on-board stimulus-reposonse tactical processor makes this a serious tactical threat."