hedgewars/uAIAmmoTests.pas
changeset 8959 ad680848a5c9
parent 8952 a6ee1e7310fb
child 8971 fcb29a13b1b1
equal deleted inserted replaced
8958:3818b38d72c0 8959:ad680848a5c9
    18 
    18 
    19 {$INCLUDE "options.inc"}
    19 {$INCLUDE "options.inc"}
    20 
    20 
    21 unit uAIAmmoTests;
    21 unit uAIAmmoTests;
    22 interface
    22 interface
    23 uses SDLh, uConsts, uFloat, uTypes;
    23 uses SDLh, uConsts, uFloat, uTypes, uAIMisc;
    24 const
    24 const
    25     amtest_Rare     = $00000001; // check only several positions
    25     amtest_Rare     = $00000001; // check only several positions
    26     amtest_NoTarget = $00000002; // each pos, but no targetting
    26     amtest_NoTarget = $00000002; // each pos, but no targetting
    27 
    27 
    28 var windSpeed: real;
    28 var windSpeed: real;
    32         Angle, Power: LongInt;
    32         Angle, Power: LongInt;
    33         ExplX, ExplY, ExplR: LongInt;
    33         ExplX, ExplY, ExplR: LongInt;
    34         AttackPutX, AttackPutY: LongInt;
    34         AttackPutX, AttackPutY: LongInt;
    35         end;
    35         end;
    36 
    36 
    37 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    37 function TestBazooka(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    38 function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    38 function TestSnowball(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    39 function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    39 function TestGrenade(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    40 function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    40 function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    41 function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    41 function TestClusterBomb(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    42 function TestWatermelon(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    42 function TestWatermelon(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    43 function TestDrillRocket(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    43 function TestDrillRocket(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    44 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    44 function TestMortar(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    45 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    45 function TestShotgun(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    46 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    46 function TestDesertEagle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    47 function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    47 function TestSniperRifle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    48 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    48 function TestBaseballBat(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    49 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    49 function TestFirePunch(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    50 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    50 function TestWhip(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    51 function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    51 function TestKamikaze(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    52 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    52 function TestAirAttack(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    53 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    53 function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    54 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    54 function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    55 function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    55 function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    56 
    56 
    57 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
    57 type TAmmoTestProc = function (Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
    58     TAmmoTest = record
    58     TAmmoTest = record
    59             proc: TAmmoTestProc;
    59             proc: TAmmoTestProc;
    60             flags: Longword;
    60             flags: Longword;
    61             end;
    61             end;
    62 
    62 
   121             (proc: nil;              flags: 0), // amIceGun
   121             (proc: nil;              flags: 0), // amIceGun
   122             (proc: nil;              flags: 0)  // amKnife
   122             (proc: nil;              flags: 0)  // amKnife
   123             );
   123             );
   124 
   124 
   125 implementation
   125 implementation
   126 uses uAIMisc, uVariables, uUtils, uGearsHandlers;
   126 uses uVariables, uUtils, uGearsHandlers;
   127 
   127 
   128 function Metric(x1, y1, x2, y2: LongInt): LongInt; inline;
   128 function Metric(x1, y1, x2, y2: LongInt): LongInt; inline;
   129 begin
   129 begin
   130 Metric:= abs(x1 - x2) + abs(y1 - y2)
   130 Metric:= abs(x1 - x2) + abs(y1 - y2)
   131 end;
   131 end;
   132 
   132 
   133 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   133 function TestBazooka(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   134 var Vx, Vy, r, mX, mY: real;
   134 var Vx, Vy, r, mX, mY: real;
   135     rTime: LongInt;
   135     rTime: LongInt;
   136     EX, EY: LongInt;
   136     EX, EY: LongInt;
   137     valueResult: LongInt;
   137     valueResult: LongInt;
   138     x, y, dX, dY: real;
   138     x, y, dX, dY: real;
   145 rTime:= 350;
   145 rTime:= 350;
   146 ap.ExplR:= 0;
   146 ap.ExplR:= 0;
   147 valueResult:= BadTurn;
   147 valueResult:= BadTurn;
   148 repeat
   148 repeat
   149     rTime:= rTime + 300 + Level * 50 + random(300);
   149     rTime:= rTime + 300 + Level * 50 + random(300);
   150     Vx:= - windSpeed * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
   150     Vx:= - windSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime;
   151     Vy:= cGravityf * rTime * 0.5 - (Targ.Y + 1 - mY) / rTime;
   151     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - mY) / rTime;
   152     r:= sqr(Vx) + sqr(Vy);
   152     r:= sqr(Vx) + sqr(Vy);
   153     if not (r > 1) then
   153     if not (r > 1) then
   154         begin
   154         begin
   155         x:= mX;
   155         x:= mX;
   156         y:= mY;
   156         y:= mY;
   169         EX:= trunc(x);
   169         EX:= trunc(x);
   170         EY:= trunc(y);
   170         EY:= trunc(y);
   171         if Level = 1 then
   171         if Level = 1 then
   172             value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   172             value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   173         else value:= RateExplosion(Me, EX, EY, 101);
   173         else value:= RateExplosion(Me, EX, EY, 101);
   174         if value = 0 then
   174         if (value = 0) and (Targ.Kind = gtHedgehog) then
   175             value:= 1024 - Metric(Targ.X, Targ.Y, EX, EY) div 64;
   175             value:= 1024 - Metric(Targ.Point.X, Targ.Point.Y, EX, EY) div 64;
   176         if valueResult <= value then
   176         if valueResult <= value then
   177             begin
   177             begin
   178             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   178             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   179             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
   179             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
   180             ap.ExplR:= 100;
   180             ap.ExplR:= 100;
   187 until rTime > 5050 - Level * 800;
   187 until rTime > 5050 - Level * 800;
   188 TestBazooka:= valueResult
   188 TestBazooka:= valueResult
   189 end;
   189 end;
   190 
   190 
   191 
   191 
   192 function TestDrillRocket(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   192 function TestDrillRocket(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   193 var Vx, Vy, r, mX, mY: real;
   193 var Vx, Vy, r, mX, mY: real;
   194     rTime: LongInt;
   194     rTime: LongInt;
   195     EX, EY: LongInt;
   195     EX, EY: LongInt;
   196     valueResult: LongInt;
   196     valueResult: LongInt;
   197     x, y, dX, dY: real;
   197     x, y, dX, dY: real;
   208     rTime:= 350;
   208     rTime:= 350;
   209     ap.ExplR:= 0;
   209     ap.ExplR:= 0;
   210     valueResult:= BadTurn;
   210     valueResult:= BadTurn;
   211     repeat
   211     repeat
   212         rTime:= rTime + 300 + Level * 50 + random(300);
   212         rTime:= rTime + 300 + Level * 50 + random(300);
   213         Vx:= - windSpeed * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
   213         Vx:= - windSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime;
   214         Vy:= cGravityf * rTime * 0.5 - (Targ.Y - 35 - mY) / rTime;
   214         Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - 35 - mY) / rTime;
   215         r:= sqr(Vx) + sqr(Vy);
   215         r:= sqr(Vx) + sqr(Vy);
   216         if not (r > 1) then
   216         if not (r > 1) then
   217             begin
   217             begin
   218             x:= mX;
   218             x:= mX;
   219             y:= mY;
   219             y:= mY;
   227                 dY:= dY + cGravityf;
   227                 dY:= dY + cGravityf;
   228                 dec(t)
   228                 dec(t)
   229             until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   229             until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   230                    ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine);
   230                    ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine);
   231 
   231 
   232             if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then
   232             if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then
   233                 begin
   233                 begin
   234                 timer := 500;
   234                 timer := 500;
   235                 t2 := 0.5 / sqrt(sqr(dX) + sqr(dY));
   235                 t2 := 0.5 / sqrt(sqr(dX) + sqr(dY));
   236                 dX := dX * t2;
   236                 dX := dX * t2;
   237                 dY := dY * t2;
   237                 dY := dY * t2;
   238                 repeat
   238                 repeat
   239                     x:= x + dX;
   239                     x:= x + dX;
   240                     y:= y + dY;
   240                     y:= y + dY;
   241                     dec(timer);
   241                     dec(timer);
   242                 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 22)
   242                 until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 22)
   243                     or (x < 0)
   243                     or (x < 0)
   244                     or (y < 0)
   244                     or (y < 0)
   245                     or (trunc(x) > LAND_WIDTH)
   245                     or (trunc(x) > LAND_WIDTH)
   246                     or (trunc(y) > LAND_HEIGHT)
   246                     or (trunc(y) > LAND_HEIGHT)
   247                     or not TestCollExcludingObjects(trunc(x), trunc(y), 5)
   247                     or not TestCollExcludingObjects(trunc(x), trunc(y), 5)
   248                     or (timer = 0)
   248                     or (timer = 0)
   249                 end;
   249                 end;
   250             EX:= trunc(x);
   250             EX:= trunc(x);
   251             EY:= trunc(y);
   251             EY:= trunc(y);
   252             // Try to prevent AI from thinking firing into water will cause a drowning
   252             // Try to prevent AI from thinking firing into water will cause a drowning
   253             if (EY < cWaterLine-5) and (Timer > 0) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then exit(BadTurn);
   253             if (EY < cWaterLine-5) and (Timer > 0) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then exit(BadTurn);
   254             if Level = 1 then
   254             if Level = 1 then
   255                 value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   255                 value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   256             else value:= RateExplosion(Me, EX, EY, 101);
   256             else value:= RateExplosion(Me, EX, EY, 101);
   257             if valueResult <= value then
   257             if valueResult <= value then
   258                 begin
   258                 begin
   267     until rTime > 5050 - Level * 800;
   267     until rTime > 5050 - Level * 800;
   268     TestDrillRocket:= valueResult
   268     TestDrillRocket:= valueResult
   269 end;
   269 end;
   270 
   270 
   271 
   271 
   272 function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   272 function TestSnowball(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   273 var Vx, Vy, r: real;
   273 var Vx, Vy, r: real;
   274     rTime: LongInt;
   274     rTime: LongInt;
   275     EX, EY: LongInt;
   275     EX, EY: LongInt;
   276     valueResult: LongInt;
   276     valueResult: LongInt;
   277     x, y, dX, dY, meX, meY: real;
   277     x, y, dX, dY, meX, meY: real;
   285 rTime:= 350;
   285 rTime:= 350;
   286 ap.ExplR:= 0;
   286 ap.ExplR:= 0;
   287 valueResult:= BadTurn;
   287 valueResult:= BadTurn;
   288 repeat
   288 repeat
   289     rTime:= rTime + 300 + Level * 50 + random(1000);
   289     rTime:= rTime + 300 + Level * 50 + random(1000);
   290     Vx:= - windSpeed * rTime * 0.5 + ((Targ.X + AIrndSign(2)) - meX) / rTime;
   290     Vx:= - windSpeed * rTime * 0.5 + ((Targ.Point.X + AIrndSign(2)) - meX) / rTime;
   291     Vy:= cGravityf * rTime * 0.5 - (Targ.Y - meY) / rTime;
   291     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - meY) / rTime;
   292     r:= sqr(Vx) + sqr(Vy);
   292     r:= sqr(Vx) + sqr(Vy);
   293     if not (r > 1) then
   293     if not (r > 1) then
   294         begin
   294         begin
   295         x:= meX;
   295         x:= meX;
   296         y:= meY;
   296         y:= meY;
   309         EY:= trunc(y);
   309         EY:= trunc(y);
   310 
   310 
   311         value:= RateShove(Me, trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
   311         value:= RateShove(Me, trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
   312         // LOL copypasta: this is score for digging with... snowball
   312         // LOL copypasta: this is score for digging with... snowball
   313         //if value = 0 then
   313         //if value = 0 then
   314         //    value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
   314         //    value:= - Metric(Targ.Point.X, Targ.Point.Y, EX, EY) div 64;
   315 
   315 
   316         if valueResult <= value then
   316         if valueResult <= value then
   317             begin
   317             begin
   318             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   318             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   319             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
   319             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
   325      end
   325      end
   326 until (rTime > 5050 - Level * 800);
   326 until (rTime > 5050 - Level * 800);
   327 TestSnowball:= valueResult
   327 TestSnowball:= valueResult
   328 end;
   328 end;
   329 
   329 
   330 function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   330 function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   331 var Vx, Vy, r: real;
   331 var Vx, Vy, r: real;
   332     Score, EX, EY, valueResult: LongInt;
   332     Score, EX, EY, valueResult: LongInt;
   333     TestTime: Longword;
   333     TestTime: Longword;
   334     x, y, dY, meX, meY: real;
   334     x, y, dY, meX, meY: real;
   335     t: LongInt;
   335     t: LongInt;
   339 valueResult:= BadTurn;
   339 valueResult:= BadTurn;
   340 TestTime:= 0;
   340 TestTime:= 0;
   341 ap.ExplR:= 0;
   341 ap.ExplR:= 0;
   342 repeat
   342 repeat
   343     inc(TestTime, 300);
   343     inc(TestTime, 300);
   344     Vx:= (Targ.X - meX) / TestTime;
   344     Vx:= (Targ.Point.X - meX) / TestTime;
   345     Vy:= cGravityf * (TestTime div 2) - Targ.Y - meY / TestTime;
   345     Vy:= cGravityf * (TestTime div 2) - Targ.Point.Y - meY / TestTime;
   346     r:= sqr(Vx) + sqr(Vy);
   346     r:= sqr(Vx) + sqr(Vy);
   347     if not (r > 1) then
   347     if not (r > 1) then
   348         begin
   348         begin
   349         x:= meX;
   349         x:= meX;
   350         y:= meY;
   350         y:= meY;
   376         end
   376         end
   377 until (TestTime > 5050 - Level * 800);
   377 until (TestTime > 5050 - Level * 800);
   378 TestMolotov:= valueResult
   378 TestMolotov:= valueResult
   379 end;
   379 end;
   380 
   380 
   381 function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   381 function TestGrenade(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   382 const tDelta = 24;
   382 const tDelta = 24;
   383 var Vx, Vy, r: real;
   383 var Vx, Vy, r: real;
   384     Score, EX, EY, valueResult: LongInt;
   384     Score, EX, EY, valueResult: LongInt;
   385     TestTime: Longword;
   385     TestTime: Longword;
   386     x, y, meX, meY, dY: real;
   386     x, y, meX, meY, dY: real;
   391 ap.ExplR:= 0;
   391 ap.ExplR:= 0;
   392 meX:= hwFloat2Float(Me^.X);
   392 meX:= hwFloat2Float(Me^.X);
   393 meY:= hwFloat2Float(Me^.Y);
   393 meY:= hwFloat2Float(Me^.Y);
   394 repeat
   394 repeat
   395     inc(TestTime, 1000);
   395     inc(TestTime, 1000);
   396     Vx:= (Targ.X - meX) / (TestTime + tDelta);
   396     Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
   397     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Y - meY) / (TestTime + tDelta);
   397     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Point.Y - meY) / (TestTime + tDelta);
   398     r:= sqr(Vx) + sqr(Vy);
   398     r:= sqr(Vx) + sqr(Vy);
   399     if not (r > 1) then
   399     if not (r > 1) then
   400         begin
   400         begin
   401         x:= meX;
   401         x:= meX;
   402         y:= meY;
   402         y:= meY;
   432 //until (Score > 204800) or (TestTime > 4000);
   432 //until (Score > 204800) or (TestTime > 4000);
   433 until TestTime > 4500 - Level * 512;
   433 until TestTime > 4500 - Level * 512;
   434 TestGrenade:= valueResult
   434 TestGrenade:= valueResult
   435 end;
   435 end;
   436 
   436 
   437 function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   437 function TestClusterBomb(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   438 const tDelta = 24;
   438 const tDelta = 24;
   439 var Vx, Vy, r: real;
   439 var Vx, Vy, r: real;
   440     Score, EX, EY, valueResult: LongInt;
   440     Score, EX, EY, valueResult: LongInt;
   441     TestTime: Longword;
   441     TestTime: Longword;
   442     x, y, dY, meX, meY: real;
   442     x, y, dY, meX, meY: real;
   448 meX:= hwFloat2Float(Me^.X);
   448 meX:= hwFloat2Float(Me^.X);
   449 meY:= hwFloat2Float(Me^.Y);
   449 meY:= hwFloat2Float(Me^.Y);
   450 repeat
   450 repeat
   451     inc(TestTime, 900);
   451     inc(TestTime, 900);
   452     // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
   452     // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
   453     if meX<Targ.X then
   453     if meX<Targ.Point.X then
   454         Vx:= ((Targ.X+10) - meX) / (TestTime + tDelta)
   454         Vx:= ((Targ.Point.X+10) - meX) / (TestTime + tDelta)
   455     else
   455     else
   456         Vx:= ((Targ.X-10) - meX) / (TestTime + tDelta);
   456         Vx:= ((Targ.Point.X-10) - meX) / (TestTime + tDelta);
   457     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Y-50) - meY) / (TestTime + tDelta);
   457     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
   458     r:= sqr(Vx)+sqr(Vy);
   458     r:= sqr(Vx)+sqr(Vy);
   459     if not (r > 1) then
   459     if not (r > 1) then
   460         begin
   460         begin
   461         x:= meX;
   461         x:= meX;
   462         y:= meY;
   462         y:= meY;
   489      end
   489      end
   490 until (TestTime = 4100);
   490 until (TestTime = 4100);
   491 TestClusterBomb:= valueResult
   491 TestClusterBomb:= valueResult
   492 end;
   492 end;
   493 
   493 
   494 function TestWatermelon(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   494 function TestWatermelon(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   495 const tDelta = 24;
   495 const tDelta = 24;
   496 var Vx, Vy, r: real;
   496 var Vx, Vy, r: real;
   497     Score, EX, EY, valueResult: LongInt;
   497     Score, EX, EY, valueResult: LongInt;
   498     TestTime: Longword;
   498     TestTime: Longword;
   499     x, y, dY, meX, meY: real;
   499     x, y, dY, meX, meY: real;
   504 ap.ExplR:= 0;
   504 ap.ExplR:= 0;
   505 meX:= hwFloat2Float(Me^.X);
   505 meX:= hwFloat2Float(Me^.X);
   506 meY:= hwFloat2Float(Me^.Y);
   506 meY:= hwFloat2Float(Me^.Y);
   507 repeat
   507 repeat
   508     inc(TestTime, 900);
   508     inc(TestTime, 900);
   509     Vx:= (Targ.X - meX) / (TestTime + tDelta);
   509     Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
   510     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Y-50) - meY) / (TestTime + tDelta);
   510     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
   511     r:= sqr(Vx)+sqr(Vy);
   511     r:= sqr(Vx)+sqr(Vy);
   512     if not (r > 1) then
   512     if not (r > 1) then
   513         begin
   513         begin
   514         x:= meX;
   514         x:= meX;
   515         y:= meY;
   515         y:= meY;
   565             end
   565             end
   566             else
   566             else
   567                 Solve:= 0
   567                 Solve:= 0
   568     end;
   568     end;
   569 
   569 
   570 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   570 function TestMortar(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   571 //const tDelta = 24;
   571 //const tDelta = 24;
   572 var Vx, Vy: real;
   572 var Vx, Vy: real;
   573     Score, EX, EY: LongInt;
   573     Score, EX, EY: LongInt;
   574     TestTime: Longword;
   574     TestTime: Longword;
   575     x, y, dY, meX, meY: real;
   575     x, y, dY, meX, meY: real;
   581     meY:= hwFloat2Float(Me^.Y);
   581     meY:= hwFloat2Float(Me^.Y);
   582 
   582 
   583     if (Level > 2) then
   583     if (Level > 2) then
   584         exit(BadTurn);
   584         exit(BadTurn);
   585 
   585 
   586     TestTime:= Solve(Targ.X, Targ.Y, trunc(meX), trunc(meY));
   586     TestTime:= Solve(Targ.Point.X, Targ.Point.Y, trunc(meX), trunc(meY));
   587 
   587 
   588     if TestTime = 0 then
   588     if TestTime = 0 then
   589         exit(BadTurn);
   589         exit(BadTurn);
   590 
   590 
   591     Vx:= (Targ.X - meX) / TestTime;
   591     Vx:= (Targ.Point.X - meX) / TestTime;
   592     Vy:= cGravityf * (TestTime div 2) - (Targ.Y - meY) / TestTime;
   592     Vy:= cGravityf * (TestTime div 2) - (Targ.Point.Y - meY) / TestTime;
   593 
   593 
   594     x:= meX;
   594     x:= meX;
   595     y:= meY;
   595     y:= meY;
   596     dY:= -Vy;
   596     dY:= -Vy;
   597 
   597 
   607     if (EY < cWaterLine) and (dY >= 0) then
   607     if (EY < cWaterLine) and (dY >= 0) then
   608         begin
   608         begin
   609         Score:= RateExplosion(Me, EX, EY, 91);
   609         Score:= RateExplosion(Me, EX, EY, 91);
   610         if (Score = 0) then
   610         if (Score = 0) then
   611             if (dY > 0.15) then
   611             if (dY > 0.15) then
   612                 Score:= - abs(Targ.Y - EY) div 32
   612                 Score:= - abs(Targ.Point.Y - EY) div 32
   613             else
   613             else
   614                 Score:= BadTurn
   614                 Score:= BadTurn
   615         else if (Score < 0) then
   615         else if (Score < 0) then
   616             Score:= BadTurn
   616             Score:= BadTurn
   617         end
   617         end
   627         ap.ExplY:= EY;
   627         ap.ExplY:= EY;
   628         TestMortar:= Score
   628         TestMortar:= Score
   629         end;
   629         end;
   630 end;
   630 end;
   631 
   631 
   632 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   632 function TestShotgun(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   633 const
   633 const
   634     MIN_RANGE =  80;
   634     MIN_RANGE =  80;
   635     MAX_RANGE = 400;
   635     MAX_RANGE = 400;
   636 var Vx, Vy, x, y: real;
   636 var Vx, Vy, x, y: real;
   637     rx, ry, valueResult: LongInt;
   637     rx, ry, valueResult: LongInt;
   641 ap.ExplR:= 0;
   641 ap.ExplR:= 0;
   642 ap.Time:= 0;
   642 ap.Time:= 0;
   643 ap.Power:= 1;
   643 ap.Power:= 1;
   644 x:= hwFloat2Float(Me^.X);
   644 x:= hwFloat2Float(Me^.X);
   645 y:= hwFloat2Float(Me^.Y);
   645 y:= hwFloat2Float(Me^.Y);
   646 range:= Metric(trunc(x), trunc(y), Targ.X, Targ.Y);
   646 range:= Metric(trunc(x), trunc(y), Targ.Point.X, Targ.Point.Y);
   647 if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
   647 if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
   648     exit(BadTurn);
   648     exit(BadTurn);
   649 
   649 
   650 Vx:= (Targ.X - x) * 1 / 1024;
   650 Vx:= (Targ.Point.X - x) * 1 / 1024;
   651 Vy:= (Targ.Y - y) * 1 / 1024;
   651 Vy:= (Targ.Point.Y - y) * 1 / 1024;
   652 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   652 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   653 repeat
   653 repeat
   654     x:= x + vX;
   654     x:= x + vX;
   655     y:= y + vY;
   655     y:= y + vY;
   656     rx:= trunc(x);
   656     rx:= trunc(x);
   660     begin
   660     begin
   661         x:= x + vX * 8;
   661         x:= x + vX * 8;
   662         y:= y + vY * 8;
   662         y:= y + vY * 8;
   663         valueResult:= RateShotgun(Me, vX, vY, rx, ry);
   663         valueResult:= RateShotgun(Me, vX, vY, rx, ry);
   664 
   664 
   665         if valueResult = 0 then
   665         if (valueResult = 0) and (Targ.Kind = gtHedgehog) then
   666             valueResult:= 1024 - Metric(Targ.X, Targ.Y, rx, ry) div 64
   666             valueResult:= 1024 - Metric(Targ.Point.X, Targ.Point.Y, rx, ry) div 64
   667         else
   667         else
   668             dec(valueResult, Level * 4000);
   668             dec(valueResult, Level * 4000);
   669         // 27/20 is reuse bonus
   669         // 27/20 is reuse bonus
   670         exit(valueResult * 27 div 20)
   670         exit(valueResult * 27 div 20)
   671     end
   671     end
   672 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
   672 until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4)
   673     or (x < 0)
   673     or (x < 0)
   674     or (y < 0)
   674     or (y < 0)
   675     or (trunc(x) > LAND_WIDTH)
   675     or (trunc(x) > LAND_WIDTH)
   676     or (trunc(y) > LAND_HEIGHT);
   676     or (trunc(y) > LAND_HEIGHT);
   677 
   677 
   678 TestShotgun:= BadTurn
   678 TestShotgun:= BadTurn
   679 end;
   679 end;
   680 
   680 
   681 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   681 function TestDesertEagle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   682 var Vx, Vy, x, y, t, dmgMod: real;
   682 var Vx, Vy, x, y, t, dmgMod: real;
   683     d: Longword;
   683     d: Longword;
   684     fallDmg, valueResult: LongInt;
   684     fallDmg, valueResult: LongInt;
   685 begin
   685 begin
   686 if Level > 4 then exit(BadTurn);
   686 if Level > 4 then exit(BadTurn);
   691 ap.Power:= 1;
   691 ap.Power:= 1;
   692 
   692 
   693 x:= hwFloat2Float(Me^.X);
   693 x:= hwFloat2Float(Me^.X);
   694 y:= hwFloat2Float(Me^.Y);
   694 y:= hwFloat2Float(Me^.Y);
   695 
   695 
   696 if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 20 then
   696 if Abs(trunc(x) - Targ.Point.X) + Abs(trunc(y) - Targ.Point.Y) < 20 then
   697     exit(BadTurn);
   697     exit(BadTurn);
   698 
   698 
   699 t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
   699 t:= 2 / sqrt(sqr(Targ.Point.X - x)+sqr(Targ.Point.Y-y));
   700 Vx:= (Targ.X - x) * t;
   700 Vx:= (Targ.Point.X - x) * t;
   701 Vy:= (Targ.Y - y) * t;
   701 Vy:= (Targ.Point.Y - y) * t;
   702 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   702 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   703 d:= 0;
   703 d:= 0;
   704 
   704 
   705 repeat
   705 repeat
   706     x:= x + vX;
   706     x:= x + vX;
   707     y:= y + vY;
   707     y:= y + vY;
   708     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   708     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   709     and (Land[trunc(y), trunc(x)] <> 0) then
   709     and (Land[trunc(y), trunc(x)] <> 0) then
   710         inc(d);
   710         inc(d);
   711 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5)
   711 until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5)
   712     or (x < 0)
   712     or (x < 0)
   713     or (y < 0)
   713     or (y < 0)
   714     or (trunc(x) > LAND_WIDTH)
   714     or (trunc(x) > LAND_WIDTH)
   715     or (trunc(y) > LAND_HEIGHT)
   715     or (trunc(y) > LAND_HEIGHT)
   716     or (d > 48);
   716     or (d > 48);
   717 
   717 
   718 if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5 then
   718 if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5 then
   719      valueResult:= RateShove(Me, Targ.X, Targ.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall)
   719      valueResult:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall)
   720 else valueResult:= BadTurn;
   720 else valueResult:= BadTurn;
   721 TestDesertEagle:= valueResult
   721 TestDesertEagle:= valueResult
   722 end;
   722 end;
   723 
   723 
   724 
   724 
   725 function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   725 function TestSniperRifle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   726 var Vx, Vy, x, y, t, dmg, dmgMod: real;
   726 var Vx, Vy, x, y, t, dmg, dmgMod: real;
   727     d: Longword;
   727     d: Longword;
   728     fallDmg: LongInt;
   728     fallDmg: LongInt;
   729 begin
   729 begin
   730 if Level > 3 then exit(BadTurn);
   730 if Level > 3 then exit(BadTurn);
   733 ap.ExplR:= 0;
   733 ap.ExplR:= 0;
   734 ap.Time:= 0;
   734 ap.Time:= 0;
   735 ap.Power:= 1;
   735 ap.Power:= 1;
   736 x:= hwFloat2Float(Me^.X);
   736 x:= hwFloat2Float(Me^.X);
   737 y:= hwFloat2Float(Me^.Y);
   737 y:= hwFloat2Float(Me^.Y);
   738 if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then
   738 if Abs(trunc(x) - Targ.Point.X) + Abs(trunc(y) - Targ.Point.Y) < 40 then
   739     exit(BadTurn);
   739     exit(BadTurn);
   740 
   740 
   741 dmg:= sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
   741 dmg:= sqrt(sqr(Targ.Point.X - x)+sqr(Targ.Point.Y-y));
   742 t:= 1.5 / dmg;
   742 t:= 1.5 / dmg;
   743 dmg:= dmg * 0.025; // div 40
   743 dmg:= dmg * 0.025; // div 40
   744 Vx:= (Targ.X - x) * t;
   744 Vx:= (Targ.Point.X - x) * t;
   745 Vy:= (Targ.Y - y) * t;
   745 Vy:= (Targ.Point.Y - y) * t;
   746 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   746 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   747 d:= 0;
   747 d:= 0;
   748 
   748 
   749 repeat
   749 repeat
   750     x:= x + vX;
   750     x:= x + vX;
   751     y:= y + vY;
   751     y:= y + vY;
   752     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   752     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   753     and (Land[trunc(y), trunc(x)] <> 0) then
   753     and (Land[trunc(y), trunc(x)] <> 0) then
   754         inc(d);
   754         inc(d);
   755 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
   755 until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4)
   756     or (x < 0)
   756     or (x < 0)
   757     or (y < 0)
   757     or (y < 0)
   758     or (trunc(x) > LAND_WIDTH)
   758     or (trunc(x) > LAND_WIDTH)
   759     or (trunc(y) > LAND_HEIGHT)
   759     or (trunc(y) > LAND_HEIGHT)
   760     or (d > 22);
   760     or (d > 22);
   761 
   761 
   762 if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then
   762 if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4 then
   763      TestSniperRifle:= RateShove(Me, Targ.X, Targ.Y, 1, trunc(dmg), 20, vX*0.166, vY*0.166, afTrackFall)
   763      TestSniperRifle:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, trunc(dmg), 20, vX*0.166, vY*0.166, afTrackFall)
   764 else TestSniperRifle:= BadTurn;
   764 else TestSniperRifle:= BadTurn;
   765 end;
   765 end;
   766 
   766 
   767 
   767 
   768 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   768 function TestBaseballBat(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   769 var valueResult, a, v1, v2: LongInt;
   769 var valueResult, a, v1, v2: LongInt;
   770     x, y, trackFall: LongInt;
   770     x, y, trackFall: LongInt;
   771     dx, dy: real;
   771     dx, dy: real;
   772 begin
   772 begin
   773     Targ:= Targ; // avoid compiler hint
   773     Targ:= Targ; // avoid compiler hint
   815         valueResult:= BadTurn;
   815         valueResult:= BadTurn;
   816 
   816 
   817     TestBaseballBat:= valueResult;
   817     TestBaseballBat:= valueResult;
   818 end;
   818 end;
   819 
   819 
   820 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   820 function TestFirePunch(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   821 var valueResult, v1, v2, i: LongInt;
   821 var valueResult, v1, v2, i: LongInt;
   822     x, y, trackFall: LongInt;
   822     x, y, trackFall: LongInt;
   823 begin
   823 begin
   824     Targ:= Targ; // avoid compiler hint
   824     Targ:= Targ; // avoid compiler hint
   825 
   825 
   873 
   873 
   874     TestFirePunch:= valueResult;
   874     TestFirePunch:= valueResult;
   875 end;
   875 end;
   876 
   876 
   877 
   877 
   878 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   878 function TestWhip(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   879 var valueResult, v1, v2: LongInt;
   879 var valueResult, v1, v2: LongInt;
   880     x, y, trackFall: LongInt;
   880     x, y, trackFall: LongInt;
   881 begin
   881 begin
   882     Targ:= Targ; // avoid compiler hint
   882     Targ:= Targ; // avoid compiler hint
   883 
   883 
   928         inc(valueResult);
   928         inc(valueResult);
   929 
   929 
   930     TestWhip:= valueResult;
   930     TestWhip:= valueResult;
   931 end;
   931 end;
   932 
   932 
   933 function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   933 function TestKamikaze(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   934 const step = 8;
   934 const step = 8;
   935 var valueResult, i, v, tx: LongInt;
   935 var valueResult, i, v, tx: LongInt;
   936     trackFall: LongInt;
   936     trackFall: LongInt;
   937     t, d, x, y, dx, dy, cx: real;
   937     t, d, x, y, dx, dy, cx: real;
   938 begin
   938 begin
   950     valueResult:= 0;
   950     valueResult:= 0;
   951     v:= 0;
   951     v:= 0;
   952 
   952 
   953     x:= hwFloat2Float(Me^.X);
   953     x:= hwFloat2Float(Me^.X);
   954     y:= hwFloat2Float(Me^.Y);
   954     y:= hwFloat2Float(Me^.Y);
   955     d:= sqrt(sqr(Targ.X - x) + sqr(Targ.Y - y));
   955     d:= sqrt(sqr(Targ.Point.X - x) + sqr(Targ.Point.Y - y));
   956     if d < 10 then
   956     if d < 10 then
   957         begin
   957         begin
   958         dx:= 0;
   958         dx:= 0;
   959         dy:= 8;
   959         dy:= 8;
   960         ap.Angle:= 2048
   960         ap.Angle:= 2048
   961         end
   961         end
   962     else
   962     else
   963         begin
   963         begin
   964         t:= step / d;
   964         t:= step / d;
   965         dx:= (Targ.X - x) * t;
   965         dx:= (Targ.Point.X - x) * t;
   966         dy:= (Targ.Y - y) * t;
   966         dy:= (Targ.Point.Y - y) * t;
   967 
   967 
   968         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
   968         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
   969         end;
   969         end;
   970 
   970 
   971     if dx >= 0 then cx:= 0.45 else cx:= -0.45;
   971     if dx >= 0 then cx:= 0.45 else cx:= -0.45;
  1012         inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30));
  1012         inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30));
  1013 
  1013 
  1014     TestKamikaze:= valueResult;
  1014     TestKamikaze:= valueResult;
  1015 end;
  1015 end;
  1016 
  1016 
  1017 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1017 function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1018 var rate: LongInt;
  1018 var rate: LongInt;
  1019 begin
  1019 begin
  1020 Level:= Level; // avoid compiler hint
  1020 Level:= Level; // avoid compiler hint
  1021 Targ:= Targ;
  1021 Targ:= Targ;
  1022 
  1022 
  1029 if rate = 0 then
  1029 if rate = 0 then
  1030     rate:= BadTurn;
  1030     rate:= BadTurn;
  1031 TestHammer:= rate;
  1031 TestHammer:= rate;
  1032 end;
  1032 end;
  1033 
  1033 
  1034 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1034 function TestAirAttack(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1035 const cShift = 4;
  1035 const cShift = 4;
  1036 var bombsSpeed, X, Y, dY: real;
  1036 var bombsSpeed, X, Y, dY: real;
  1037     b: array[0..9] of boolean;
  1037     b: array[0..9] of boolean;
  1038     dmg: array[0..9] of LongInt;
  1038     dmg: array[0..9] of LongInt;
  1039     fexit: boolean;
  1039     fexit: boolean;
  1043 ap.Time:= 0;
  1043 ap.Time:= 0;
  1044 if (Level > 3) then
  1044 if (Level > 3) then
  1045     exit(BadTurn);
  1045     exit(BadTurn);
  1046 
  1046 
  1047 ap.Angle:= 0;
  1047 ap.Angle:= 0;
  1048 ap.AttackPutX:= Targ.X;
  1048 ap.AttackPutX:= Targ.Point.X;
  1049 ap.AttackPutY:= Targ.Y;
  1049 ap.AttackPutY:= Targ.Point.Y;
  1050 
  1050 
  1051 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1051 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1052 X:= Targ.X - 135 - cShift; // hh center - cShift
  1052 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1053 X:= X - bombsSpeed * sqrt(((Targ.Y + 128) * 2) / cGravityf);
  1053 X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / cGravityf);
  1054 Y:= -128;
  1054 Y:= -128;
  1055 dY:= 0;
  1055 dY:= 0;
  1056 
  1056 
  1057 for i:= 0 to 9 do
  1057 for i:= 0 to 9 do
  1058     begin
  1058     begin
  1080             end;
  1080             end;
  1081 until fexit or (Y > cWaterLine);
  1081 until fexit or (Y > cWaterLine);
  1082 
  1082 
  1083 for i:= 0 to 5 do inc(valueResult, dmg[i]);
  1083 for i:= 0 to 5 do inc(valueResult, dmg[i]);
  1084 t:= valueResult;
  1084 t:= valueResult;
  1085 ap.AttackPutX:= Targ.X - 60;
  1085 ap.AttackPutX:= Targ.Point.X - 60;
  1086 
  1086 
  1087 for i:= 0 to 3 do
  1087 for i:= 0 to 3 do
  1088     begin
  1088     begin
  1089     dec(t, dmg[i]);
  1089     dec(t, dmg[i]);
  1090     inc(t, dmg[i + 6]);
  1090     inc(t, dmg[i + 6]);
  1091     if t > valueResult then
  1091     if t > valueResult then
  1092         begin
  1092         begin
  1093         valueResult:= t;
  1093         valueResult:= t;
  1094         ap.AttackPutX:= Targ.X - 30 - cShift + i * 30
  1094         ap.AttackPutX:= Targ.Point.X - 30 - cShift + i * 30
  1095         end
  1095         end
  1096     end;
  1096     end;
  1097 
  1097 
  1098 if valueResult <= 0 then
  1098 if valueResult <= 0 then
  1099     valueResult:= BadTurn;
  1099     valueResult:= BadTurn;
  1100 TestAirAttack:= valueResult;
  1100 TestAirAttack:= valueResult;
  1101 end;
  1101 end;
  1102 
  1102 
  1103 
  1103 
  1104 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1104 function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1105 var
  1105 var
  1106     i, failNum: longword;
  1106     i, failNum: longword;
  1107     maxTop: longword;
  1107     maxTop: longword;
  1108 begin
  1108 begin
  1109     TestTeleport := BadTurn;
  1109     TestTeleport := BadTurn;
  1112     //FillBonuses(true, [gtCase]);
  1112     //FillBonuses(true, [gtCase]);
  1113     if bonuses.Count = 0 then
  1113     if bonuses.Count = 0 then
  1114         begin
  1114         begin
  1115         if Me^.Health <= 100  then
  1115         if Me^.Health <= 100  then
  1116             begin
  1116             begin
  1117             maxTop := Targ.Y - cHHRadius * 2;
  1117             maxTop := Targ.Point.Y - cHHRadius * 2;
  1118 
  1118 
  1119             while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
  1119             while not TestColl(Targ.Point.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
  1120                 dec(maxTop, cHHRadius*2);
  1120                 dec(maxTop, cHHRadius*2);
  1121             if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then
  1121             if not TestColl(Targ.Point.X, maxTop + cHHRadius, cHHRadius) then
  1122                 begin
  1122                 begin
  1123                 ap.AttackPutX := Targ.X;
  1123                 ap.AttackPutX := Targ.Point.X;
  1124                 ap.AttackPutY := maxTop + cHHRadius;
  1124                 ap.AttackPutY := maxTop + cHHRadius;
  1125                 TestTeleport := Targ.Y - maxTop;
  1125                 TestTeleport := Targ.Point.Y - maxTop;
  1126                 end;
  1126                 end;
  1127             end;
  1127             end;
  1128         end
  1128         end
  1129     else
  1129     else
  1130         begin
  1130         begin
  1163         ap.Power:= v
  1163         ap.Power:= v
  1164         end
  1164         end
  1165     end;
  1165     end;
  1166 end;
  1166 end;
  1167 
  1167 
  1168 function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1168 function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1169 var valueResult, v1, v2: LongInt;
  1169 var valueResult, v1, v2: LongInt;
  1170     cake: TGear;
  1170     cake: TGear;
  1171 begin
  1171 begin
  1172     Targ:= Targ; // avoid compiler hint
  1172     Targ:= Targ; // avoid compiler hint
  1173 
  1173