hedgewars/uAIAmmoTests.pas
branchwebgl
changeset 9127 e350500c4edb
parent 8839 caa57115d7ea
parent 9080 9b42757d7e71
child 9136 78f087fd3e5b
equal deleted inserted replaced
8860:bde641cf53c8 9127:e350500c4edb
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
     4  *
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; version 2 of the License
     7  * the Free Software Foundation; version 2 of the License
     8  *
     8  *
    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;
   162             y:= y + dY;
   162             y:= y + dY;
   163             dX:= dX + windSpeed;
   163             dX:= dX + windSpeed;
   164             dY:= dY + cGravityf;
   164             dY:= dY + cGravityf;
   165             dec(t)
   165             dec(t)
   166         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   166         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   167                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0);
   167                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0);
   168 
   168 
   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) and (Targ.Score > 0) 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;
   182             ap.ExplY:= EY;
   182             ap.ExplY:= EY;
   183             valueResult:= value
   183             valueResult:= value
   184             end;
   184             end;
   185         end
   185         end
   186 //until (value > 204800) or (rTime > 4250); not so useful since adding score to the drowning
   186 //until (value > 204800) or (rTime > 4250); not so useful since adding score to the drowning
   187 until rTime > 4250;
   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;
   225                 y:= y + dY;
   225                 y:= y + dY;
   226                 dX:= dX + windSpeed;
   226                 dX:= dX + windSpeed;
   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, 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 TestCollWithLand(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 TestCollWithLand(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
       
   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);
   252             if Level = 1 then
   254             if Level = 1 then
   253                 value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   255                 value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   254             else value:= RateExplosion(Me, EX, EY, 101);
   256             else value:= RateExplosion(Me, EX, EY, 101);
   255             if valueResult <= value then
   257             if valueResult <= value then
   256                 begin
   258                 begin
   260                 ap.ExplX:= EX;
   262                 ap.ExplX:= EX;
   261                 ap.ExplY:= EY;
   263                 ap.ExplY:= EY;
   262                 valueResult:= value-2500 // trying to make it slightly less attractive than a bazooka, to prevent waste.  AI could use awareness of weapon count
   264                 valueResult:= value-2500 // trying to make it slightly less attractive than a bazooka, to prevent waste.  AI could use awareness of weapon count
   263                 end;
   265                 end;
   264             end
   266             end
   265     until rTime > 4250;
   267     until rTime > 5050 - Level * 800;
   266     TestDrillRocket:= valueResult
   268     TestDrillRocket:= valueResult
   267 end;
   269 end;
   268 
   270 
   269 
   271 
   270 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;
   271 var Vx, Vy, r: real;
   273 var Vx, Vy, r: real;
   272     rTime: LongInt;
   274     rTime: LongInt;
   273     EX, EY: LongInt;
   275     EX, EY: LongInt;
   274     valueResult: LongInt;
   276     valueResult: LongInt;
   275     x, y, dX, dY, meX, meY: real;
   277     x, y, dX, dY, meX, meY: real;
   283 rTime:= 350;
   285 rTime:= 350;
   284 ap.ExplR:= 0;
   286 ap.ExplR:= 0;
   285 valueResult:= BadTurn;
   287 valueResult:= BadTurn;
   286 repeat
   288 repeat
   287     rTime:= rTime + 300 + Level * 50 + random(1000);
   289     rTime:= rTime + 300 + Level * 50 + random(1000);
   288     Vx:= - windSpeed * rTime * 0.5 + ((Targ.X + AIrndSign(2)) - meX) / rTime;
   290     Vx:= - windSpeed * rTime * 0.5 + ((Targ.Point.X + AIrndSign(2)) - meX) / rTime;
   289     Vy:= cGravityf * rTime * 0.5 - (Targ.Y - meY) / rTime;
   291     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - meY) / rTime;
   290     r:= sqr(Vx) + sqr(Vy);
   292     r:= sqr(Vx) + sqr(Vy);
   291     if not (r > 1) then
   293     if not (r > 1) then
   292         begin
   294         begin
   293         x:= meX;
   295         x:= meX;
   294         y:= meY;
   296         y:= meY;
   300             y:= y + dY;
   302             y:= y + dY;
   301             dX:= dX + windSpeed;
   303             dX:= dX + windSpeed;
   302             dY:= dY + cGravityf;
   304             dY:= dY + cGravityf;
   303             dec(t)
   305             dec(t)
   304         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   306         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   305                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0);
   307                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0);
   306         EX:= trunc(x);
   308         EX:= trunc(x);
   307         EY:= trunc(y);
   309         EY:= trunc(y);
   308 
   310 
   309         value:= RateShove(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);
   310         // LOL copypasta: this is score for digging with... snowball
   312         // LOL copypasta: this is score for digging with... snowball
   311         //if value = 0 then
   313         //if value = 0 then
   312         //    value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
   314         //    value:= - Metric(Targ.Point.X, Targ.Point.Y, EX, EY) div 64;
   313 
   315 
   314         if valueResult <= value then
   316         if valueResult <= value then
   315             begin
   317             begin
   316             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   318             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
   317             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
   319             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
   319             ap.ExplX:= EX;
   321             ap.ExplX:= EX;
   320             ap.ExplY:= EY;
   322             ap.ExplY:= EY;
   321             valueResult:= value
   323             valueResult:= value
   322             end;
   324             end;
   323      end
   325      end
   324 until (rTime > 4250);
   326 until (rTime > 5050 - Level * 800);
   325 TestSnowball:= valueResult
   327 TestSnowball:= valueResult
   326 end;
   328 end;
   327 
   329 
   328 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;
   329 var Vx, Vy, r: real;
   331 var Vx, Vy, r: real;
   330     Score, EX, EY, valueResult: LongInt;
   332     Score, EX, EY, valueResult: LongInt;
   331     TestTime: Longword;
   333     TestTime: Longword;
   332     x, y, dY, meX, meY: real;
   334     x, y, dY, meX, meY: real;
   333     t: LongInt;
   335     t: LongInt;
   337 valueResult:= BadTurn;
   339 valueResult:= BadTurn;
   338 TestTime:= 0;
   340 TestTime:= 0;
   339 ap.ExplR:= 0;
   341 ap.ExplR:= 0;
   340 repeat
   342 repeat
   341     inc(TestTime, 300);
   343     inc(TestTime, 300);
   342     Vx:= (Targ.X - meX) / TestTime;
   344     Vx:= (Targ.Point.X - meX) / TestTime;
   343     Vy:= cGravityf * (TestTime div 2) - Targ.Y - meY / TestTime;
   345     Vy:= cGravityf * (TestTime div 2) - Targ.Point.Y - meY / TestTime;
   344     r:= sqr(Vx) + sqr(Vy);
   346     r:= sqr(Vx) + sqr(Vy);
   345     if not (r > 1) then
   347     if not (r > 1) then
   346         begin
   348         begin
   347         x:= meX;
   349         x:= meX;
   348         y:= meY;
   350         y:= meY;
   352             x:= x + Vx;
   354             x:= x + Vx;
   353             y:= y + dY;
   355             y:= y + dY;
   354             dY:= dY + cGravityf;
   356             dY:= dY + cGravityf;
   355             dec(t)
   357             dec(t)
   356         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
   358         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
   357                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0);
   359                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
   358         EX:= trunc(x);
   360         EX:= trunc(x);
   359         EY:= trunc(y);
   361         EY:= trunc(y);
   360         if t < 50 then
   362         if t < 50 then
   361             Score:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
   363             Score:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
   362         else
   364         else
   370             ap.ExplX:= EX;
   372             ap.ExplX:= EX;
   371             ap.ExplY:= EY;
   373             ap.ExplY:= EY;
   372             valueResult:= Score
   374             valueResult:= Score
   373             end;
   375             end;
   374         end
   376         end
   375 until (TestTime > 4250);
   377 until (TestTime > 5050 - Level * 800);
   376 TestMolotov:= valueResult
   378 TestMolotov:= valueResult
   377 end;
   379 end;
   378 
   380 
   379 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;
   380 const tDelta = 24;
   382 const tDelta = 24;
   381 var Vx, Vy, r: real;
   383 var Vx, Vy, r: real;
   382     Score, EX, EY, valueResult: LongInt;
   384     Score, EX, EY, valueResult: LongInt;
   383     TestTime: Longword;
   385     TestTime: Longword;
   384     x, y, meX, meY, dY: real;
   386     x, y, meX, meY, dY: real;
   389 ap.ExplR:= 0;
   391 ap.ExplR:= 0;
   390 meX:= hwFloat2Float(Me^.X);
   392 meX:= hwFloat2Float(Me^.X);
   391 meY:= hwFloat2Float(Me^.Y);
   393 meY:= hwFloat2Float(Me^.Y);
   392 repeat
   394 repeat
   393     inc(TestTime, 1000);
   395     inc(TestTime, 1000);
   394     Vx:= (Targ.X - meX) / (TestTime + tDelta);
   396     Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
   395     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Y - meY) / (TestTime + tDelta);
   397     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Point.Y - meY) / (TestTime + tDelta);
   396     r:= sqr(Vx) + sqr(Vy);
   398     r:= sqr(Vx) + sqr(Vy);
   397     if not (r > 1) then
   399     if not (r > 1) then
   398         begin
   400         begin
   399         x:= meX;
   401         x:= meX;
   400         y:= meY;
   402         y:= meY;
   404             x:= x + Vx;
   406             x:= x + Vx;
   405             y:= y + dY;
   407             y:= y + dY;
   406             dY:= dY + cGravityf;
   408             dY:= dY + cGravityf;
   407             dec(t)
   409             dec(t)
   408         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   410         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   409                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0);
   411                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
   410     EX:= trunc(x);
   412     EX:= trunc(x);
   411     EY:= trunc(y);
   413     EY:= trunc(y);
   412     if t < 50 then
   414     if t < 50 then
   413         if Level = 1 then
   415         if Level = 1 then
   414             Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   416             Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   416     else
   418     else
   417         Score:= BadTurn;
   419         Score:= BadTurn;
   418 
   420 
   419     if (valueResult < Score) and (Score > 0) then
   421     if (valueResult < Score) and (Score > 0) then
   420         begin
   422         begin
   421         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   423         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 3));
   422         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   424         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 20);
   423         ap.Time:= TestTime;
   425         ap.Time:= TestTime;
   424         ap.ExplR:= 100;
   426         ap.ExplR:= 100;
   425         ap.ExplX:= EX;
   427         ap.ExplX:= EX;
   426         ap.ExplY:= EY;
   428         ap.ExplY:= EY;
   427         valueResult:= Score
   429         valueResult:= Score
   428         end;
   430         end;
   429     end
   431     end
   430 //until (Score > 204800) or (TestTime > 4000);
   432 //until (Score > 204800) or (TestTime > 4000);
   431 until TestTime > 4000;
   433 until TestTime > 4500 - Level * 512;
   432 TestGrenade:= valueResult
   434 TestGrenade:= valueResult
   433 end;
   435 end;
   434 
   436 
   435 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;
   436 const tDelta = 24;
   438 const tDelta = 24;
   437 var Vx, Vy, r: real;
   439 var Vx, Vy, r: real;
   438     Score, EX, EY, valueResult: LongInt;
   440     Score, EX, EY, valueResult: LongInt;
   439     TestTime: Longword;
   441     TestTime: Longword;
   440     x, y, dY, meX, meY: real;
   442     x, y, dY, meX, meY: real;
   446 meX:= hwFloat2Float(Me^.X);
   448 meX:= hwFloat2Float(Me^.X);
   447 meY:= hwFloat2Float(Me^.Y);
   449 meY:= hwFloat2Float(Me^.Y);
   448 repeat
   450 repeat
   449     inc(TestTime, 900);
   451     inc(TestTime, 900);
   450     // 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
   451     if meX<Targ.X then
   453     if meX<Targ.Point.X then
   452         Vx:= ((Targ.X+10) - meX) / (TestTime + tDelta)
   454         Vx:= ((Targ.Point.X+10) - meX) / (TestTime + tDelta)
   453     else
   455     else
   454         Vx:= ((Targ.X-10) - meX) / (TestTime + tDelta);
   456         Vx:= ((Targ.Point.X-10) - meX) / (TestTime + tDelta);
   455     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);
   456     r:= sqr(Vx)+sqr(Vy);
   458     r:= sqr(Vx)+sqr(Vy);
   457     if not (r > 1) then
   459     if not (r > 1) then
   458         begin
   460         begin
   459         x:= meX;
   461         x:= meX;
   460         y:= meY;
   462         y:= meY;
   464         x:= x + Vx;
   466         x:= x + Vx;
   465         y:= y + dY;
   467         y:= y + dY;
   466         dY:= dY + cGravityf;
   468         dY:= dY + cGravityf;
   467         dec(t)
   469         dec(t)
   468     until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   470     until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   469            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0);
   471            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
   470     EX:= trunc(x);
   472     EX:= trunc(x);
   471     EY:= trunc(y);
   473     EY:= trunc(y);
   472     if t < 50 then
   474     if t < 50 then
   473         Score:= RateExplosion(Me, EX, EY, 41)
   475         Score:= RateExplosion(Me, EX, EY, 41)
   474     else
   476     else
   475         Score:= BadTurn;
   477         Score:= BadTurn;
   476 
   478 
   477      if valueResult < Score then
   479      if Score > 0 then
   478         begin
   480         begin
   479         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   481         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 2));
   480         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   482         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   481         ap.Time:= TestTime div 1000 * 1000;
   483         ap.Time:= TestTime div 1000 * 1000;
   482         ap.ExplR:= 90;
   484         ap.ExplR:= 90;
   483         ap.ExplX:= EX;
   485         ap.ExplX:= EX;
   484         ap.ExplY:= EY;
   486         ap.ExplY:= EY;
   487      end
   489      end
   488 until (TestTime = 4100);
   490 until (TestTime = 4100);
   489 TestClusterBomb:= valueResult
   491 TestClusterBomb:= valueResult
   490 end;
   492 end;
   491 
   493 
   492 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;
   493 const tDelta = 24;
   495 const tDelta = 24;
   494 var Vx, Vy, r: real;
   496 var Vx, Vy, r: real;
   495     Score, EX, EY, valueResult: LongInt;
   497     Score, EX, EY, valueResult: LongInt;
   496     TestTime: Longword;
   498     TestTime: Longword;
   497     x, y, dY, meX, meY: real;
   499     x, y, dY, meX, meY: real;
   502 ap.ExplR:= 0;
   504 ap.ExplR:= 0;
   503 meX:= hwFloat2Float(Me^.X);
   505 meX:= hwFloat2Float(Me^.X);
   504 meY:= hwFloat2Float(Me^.Y);
   506 meY:= hwFloat2Float(Me^.Y);
   505 repeat
   507 repeat
   506     inc(TestTime, 900);
   508     inc(TestTime, 900);
   507     Vx:= (Targ.X - meX) / (TestTime + tDelta);
   509     Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
   508     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);
   509     r:= sqr(Vx)+sqr(Vy);
   511     r:= sqr(Vx)+sqr(Vy);
   510     if not (r > 1) then
   512     if not (r > 1) then
   511         begin
   513         begin
   512         x:= meX;
   514         x:= meX;
   513         y:= meY;
   515         y:= meY;
   517             x:= x + Vx;
   519             x:= x + Vx;
   518             y:= y + dY;
   520             y:= y + dY;
   519             dY:= dY + cGravityf;
   521             dY:= dY + cGravityf;
   520             dec(t)
   522             dec(t)
   521        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
   523        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
   522                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0);
   524                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
   523 
   525 
   524         EX:= trunc(x);
   526         EX:= trunc(x);
   525         EY:= trunc(y);
   527         EY:= trunc(y);
   526         if t < 50 then
   528         if t < 50 then
   527             Score:= RateExplosion(Me, EX, EY, 200) + RateExplosion(Me, EX, EY + 120, 200)
   529             Score:= RateExplosion(Me, EX, EY, 200) + RateExplosion(Me, EX, EY + 120, 200)
   563             end
   565             end
   564             else
   566             else
   565                 Solve:= 0
   567                 Solve:= 0
   566     end;
   568     end;
   567 
   569 
   568 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;
   569 //const tDelta = 24;
   571 //const tDelta = 24;
   570 var Vx, Vy: real;
   572 var Vx, Vy: real;
   571     Score, EX, EY: LongInt;
   573     Score, EX, EY: LongInt;
   572     TestTime: Longword;
   574     TestTime: Longword;
   573     x, y, dY, meX, meY: real;
   575     x, y, dY, meX, meY: real;
   579     meY:= hwFloat2Float(Me^.Y);
   581     meY:= hwFloat2Float(Me^.Y);
   580 
   582 
   581     if (Level > 2) then
   583     if (Level > 2) then
   582         exit(BadTurn);
   584         exit(BadTurn);
   583 
   585 
   584     TestTime:= Solve(Targ.X, Targ.Y, trunc(meX), trunc(meY));
   586     TestTime:= Solve(Targ.Point.X, Targ.Point.Y, trunc(meX), trunc(meY));
   585 
   587 
   586     if TestTime = 0 then
   588     if TestTime = 0 then
   587         exit(BadTurn);
   589         exit(BadTurn);
   588 
   590 
   589     Vx:= (Targ.X - meX) / TestTime;
   591     Vx:= (Targ.Point.X - meX) / TestTime;
   590     Vy:= cGravityf * (TestTime div 2) - (Targ.Y - meY) / TestTime;
   592     Vy:= cGravityf * (TestTime div 2) - (Targ.Point.Y - meY) / TestTime;
   591 
   593 
   592     x:= meX;
   594     x:= meX;
   593     y:= meY;
   595     y:= meY;
   594     dY:= -Vy;
   596     dY:= -Vy;
   595 
   597 
   598         y:= y + dY;
   600         y:= y + dY;
   599         dY:= dY + cGravityf;
   601         dY:= dY + cGravityf;
   600         EX:= trunc(x);
   602         EX:= trunc(x);
   601         EY:= trunc(y);
   603         EY:= trunc(y);
   602     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or
   604     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or
   603            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, EX, EY, 4))) or (EY > cWaterLine);
   605            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine);
   604 
   606 
   605     if (EY < cWaterLine) and (dY >= 0) then
   607     if (EY < cWaterLine) and (dY >= 0) then
   606         begin
   608         begin
   607         Score:= RateExplosion(Me, EX, EY, 91);
   609         Score:= RateExplosion(Me, EX, EY, 91);
   608         if (Score = 0) then
   610         if (Score = 0) then
   609             if (dY > 0.15) then
   611             if (dY > 0.15) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then
   610                 Score:= - abs(Targ.Y - EY) div 32
   612                 Score:= - abs(Targ.Point.Y - EY) div 32
   611             else
   613             else
   612                 Score:= BadTurn
   614                 Score:= BadTurn
   613         else if (Score < 0) then
   615         else if (Score < 0) then
   614             Score:= BadTurn
   616             Score:= BadTurn
   615         end
   617         end
   616     else
   618     else
   617         Score:= BadTurn;
   619         Score:= BadTurn;
   618 
   620 
   619     if BadTurn < Score then
   621     if Score > 0 then
   620         begin
   622         begin
   621         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   623         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   622         ap.Power:= 1;
   624         ap.Power:= 1;
   623         ap.ExplR:= 100;
   625         ap.ExplR:= 100;
   624         ap.ExplX:= EX;
   626         ap.ExplX:= EX;
   625         ap.ExplY:= EY;
   627         ap.ExplY:= EY;
   626         TestMortar:= Score
   628         TestMortar:= Score
   627         end;
   629         end;
   628 end;
   630 end;
   629 
   631 
   630 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;
   631 const
   633 const
   632     MIN_RANGE =  80;
   634     MIN_RANGE =  80;
   633     MAX_RANGE = 400;
   635     MAX_RANGE = 400;
   634 var Vx, Vy, x, y: real;
   636 var Vx, Vy, x, y: real;
   635     rx, ry, valueResult: LongInt;
   637     rx, ry, valueResult: LongInt;
   639 ap.ExplR:= 0;
   641 ap.ExplR:= 0;
   640 ap.Time:= 0;
   642 ap.Time:= 0;
   641 ap.Power:= 1;
   643 ap.Power:= 1;
   642 x:= hwFloat2Float(Me^.X);
   644 x:= hwFloat2Float(Me^.X);
   643 y:= hwFloat2Float(Me^.Y);
   645 y:= hwFloat2Float(Me^.Y);
   644 range:= Metric(trunc(x), trunc(y), Targ.X, Targ.Y);
   646 range:= Metric(trunc(x), trunc(y), Targ.Point.X, Targ.Point.Y);
   645 if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
   647 if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
   646     exit(BadTurn);
   648     exit(BadTurn);
   647 
   649 
   648 Vx:= (Targ.X - x) * 1 / 1024;
   650 Vx:= (Targ.Point.X - x) * 1 / 1024;
   649 Vy:= (Targ.Y - y) * 1 / 1024;
   651 Vy:= (Targ.Point.Y - y) * 1 / 1024;
   650 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   652 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   651 repeat
   653 repeat
   652     x:= x + vX;
   654     x:= x + vX;
   653     y:= y + vY;
   655     y:= y + vY;
   654     rx:= trunc(x);
   656     rx:= trunc(x);
   655     ry:= trunc(y);
   657     ry:= trunc(y);
   656     if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or
   658     if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or
   657         ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, rx, ry, 2)) then
   659         ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 2)) then
   658     begin
   660     begin
   659         x:= x + vX * 8;
   661         x:= x + vX * 8;
   660         y:= y + vY * 8;
   662         y:= y + vY * 8;
   661         valueResult:= RateShotgun(Me, vX, vY, rx, ry);
   663         valueResult:= RateShotgun(Me, vX, vY, rx, ry);
   662 
   664 
   663         if valueResult = 0 then
   665         if (valueResult = 0) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then
   664             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
   665         else
   667         else
   666             dec(valueResult, Level * 4000);
   668             dec(valueResult, Level * 4000);
   667         // 27/20 is reuse bonus
   669         // 27/20 is reuse bonus
   668         exit(valueResult * 27 div 20)
   670         exit(valueResult * 27 div 20)
   669     end
   671     end
   670 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)
   671     or (x < 0)
   673     or (x < 0)
   672     or (y < 0)
   674     or (y < 0)
   673     or (trunc(x) > LAND_WIDTH)
   675     or (trunc(x) > LAND_WIDTH)
   674     or (trunc(y) > LAND_HEIGHT);
   676     or (trunc(y) > LAND_HEIGHT);
   675 
   677 
   676 TestShotgun:= BadTurn
   678 TestShotgun:= BadTurn
   677 end;
   679 end;
   678 
   680 
   679 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;
   680 var Vx, Vy, x, y, t, dmgMod: real;
   682 var Vx, Vy, x, y, t: real;
   681     d: Longword;
   683     d: Longword;
   682     fallDmg, valueResult: LongInt;
   684     fallDmg, valueResult: LongInt;
   683 begin
   685 begin
   684 if Level > 4 then exit(BadTurn);
   686 if (Level > 4) or (Targ.Score < 0) or (Targ.Kind <> gtHedgehog) then exit(BadTurn);
   685 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
       
   686 Level:= Level; // avoid compiler hint
   687 Level:= Level; // avoid compiler hint
   687 ap.ExplR:= 0;
   688 ap.ExplR:= 1;
   688 ap.Time:= 0;
   689 ap.Time:= 0;
   689 ap.Power:= 1;
   690 ap.Power:= 1;
   690 
   691 
   691 x:= hwFloat2Float(Me^.X);
   692 x:= hwFloat2Float(Me^.X);
   692 y:= hwFloat2Float(Me^.Y);
   693 y:= hwFloat2Float(Me^.Y);
   693 
   694 
   694 if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 20 then
   695 if Abs(trunc(x) - Targ.Point.X) + Abs(trunc(y) - Targ.Point.Y) < 20 then
   695     exit(BadTurn);
   696     exit(BadTurn);
   696 
   697 
   697 t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
   698 t:= 2 / sqrt(sqr(Targ.Point.X - x)+sqr(Targ.Point.Y-y));
   698 Vx:= (Targ.X - x) * t;
   699 Vx:= (Targ.Point.X - x) * t;
   699 Vy:= (Targ.Y - y) * t;
   700 Vy:= (Targ.Point.Y - y) * t;
   700 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   701 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   701 d:= 0;
   702 d:= 0;
   702 
   703 
   703 repeat
   704 repeat
   704     x:= x + vX;
   705     x:= x + vX;
   705     y:= y + vY;
   706     y:= y + vY;
   706     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   707     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   707     and (Land[trunc(y), trunc(x)] <> 0) then
   708     and (Land[trunc(y), trunc(x)] <> 0) then
   708         inc(d);
   709         inc(d);
   709 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5)
   710 until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5)
   710     or (x < 0)
   711     or (x < 0)
   711     or (y < 0)
   712     or (y < 0)
   712     or (trunc(x) > LAND_WIDTH)
   713     or (trunc(x) > LAND_WIDTH)
   713     or (trunc(y) > LAND_HEIGHT)
   714     or (trunc(y) > LAND_HEIGHT)
   714     or (d > 48);
   715     or (d > 48);
   715 
   716 
   716 if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5 then
   717 if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5 then
   717     begin
   718      valueResult:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall)
   718     fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00125 * 20, vY * 0.00125 * 20);
   719 else valueResult:= BadTurn;
   719     if fallDmg < 0 then
       
   720         valueResult:= 204800
       
   721     else valueResult:= Max(0, (4 - d div 12) * trunc((7 + fallDmg) * dmgMod) * 1024)
       
   722     end
       
   723 else
       
   724     valueResult:= BadTurn;
       
   725 TestDesertEagle:= valueResult
   720 TestDesertEagle:= valueResult
   726 end;
   721 end;
   727 
   722 
   728 
   723 
   729 function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   724 function TestSniperRifle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   730 var Vx, Vy, x, y, t, dmg, dmgMod: real;
   725 var Vx, Vy, x, y, t, dmg: real;
   731     d: Longword;
   726     d: Longword;
   732     fallDmg: LongInt;
   727     fallDmg: LongInt;
   733 begin
   728 begin
   734 if Level > 3 then exit(BadTurn);
   729 if (Level > 3) or (Targ.Score < 0) or (Targ.Kind <> gtHedgehog) then exit(BadTurn);
   735 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
       
   736 Level:= Level; // avoid compiler hint
   730 Level:= Level; // avoid compiler hint
   737 ap.ExplR:= 0;
   731 ap.ExplR:= 0;
   738 ap.Time:= 0;
   732 ap.Time:= 0;
   739 ap.Power:= 1;
   733 ap.Power:= 1;
   740 x:= hwFloat2Float(Me^.X);
   734 x:= hwFloat2Float(Me^.X);
   741 y:= hwFloat2Float(Me^.Y);
   735 y:= hwFloat2Float(Me^.Y);
   742 if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then
   736 if Abs(trunc(x) - Targ.Point.X) + Abs(trunc(y) - Targ.Point.Y) < 40 then
   743     exit(BadTurn);
   737     exit(BadTurn);
   744 
   738 
   745 dmg:= sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
   739 dmg:= sqrt(sqr(Targ.Point.X - x)+sqr(Targ.Point.Y-y));
   746 t:= 1.5 / dmg;
   740 t:= 1.5 / dmg;
   747 dmg:= dmg * 0.025; // div 40
   741 dmg:= dmg * 0.025; // div 40
   748 Vx:= (Targ.X - x) * t;
   742 Vx:= (Targ.Point.X - x) * t;
   749 Vy:= (Targ.Y - y) * t;
   743 Vy:= (Targ.Point.Y - y) * t;
   750 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   744 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
   751 d:= 0;
   745 d:= 0;
   752 
   746 
   753 repeat
   747 repeat
   754     x:= x + vX;
   748     x:= x + vX;
   755     y:= y + vY;
   749     y:= y + vY;
   756     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   750     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
   757     and (Land[trunc(y), trunc(x)] <> 0) then
   751     and (Land[trunc(y), trunc(x)] <> 0) then
   758         inc(d);
   752         inc(d);
   759 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
   753 until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4)
   760     or (x < 0)
   754     or (x < 0)
   761     or (y < 0)
   755     or (y < 0)
   762     or (trunc(x) > LAND_WIDTH)
   756     or (trunc(x) > LAND_WIDTH)
   763     or (trunc(y) > LAND_HEIGHT)
   757     or (trunc(y) > LAND_HEIGHT)
   764     or (d > 22);
   758     or (d > 22);
   765 
   759 
   766 if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then
   760 if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4 then
   767     begin
   761      TestSniperRifle:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, trunc(dmg), 20, vX*0.166, vY*0.166, afTrackFall)
   768     fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg);
   762 else TestSniperRifle:= BadTurn;
   769     if fallDmg < 0 then
   763 end;
   770         TestSniperRifle:= BadTurn
   764 
   771     else
   765 
   772         TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024)
   766 function TestBaseballBat(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   773     end
       
   774 else
       
   775     TestSniperRifle:= BadTurn
       
   776 end;
       
   777 
       
   778 
       
   779 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
       
   780 var valueResult, a, v1, v2: LongInt;
   767 var valueResult, a, v1, v2: LongInt;
   781     x, y, trackFall: LongInt;
   768     x, y, trackFall: LongInt;
   782     dx, dy: real;
   769     dx, dy: real;
   783 begin
   770 begin
   784     Targ:= Targ; // avoid compiler hint
   771     Targ:= Targ; // avoid compiler hint
   798     while a >= 0 do
   785     while a >= 0 do
   799         begin
   786         begin
   800         dx:= sin(a / cMaxAngle * pi) * 0.5;
   787         dx:= sin(a / cMaxAngle * pi) * 0.5;
   801         dy:= cos(a / cMaxAngle * pi) * 0.5;
   788         dy:= cos(a / cMaxAngle * pi) * 0.5;
   802 
   789 
   803         v1:= RateShove(x - 10, y + 2
   790         v1:= RateShove(Me, x - 10, y + 2
   804                 , 32, 30, 115
   791                 , 32, 30, 115
   805                 , -dx, -dy, trackFall);
   792                 , -dx, -dy, trackFall);
   806         v2:= RateShove(x + 10, y + 2
   793         v2:= RateShove(Me, x + 10, y + 2
   807                 , 32, 30, 115
   794                 , 32, 30, 115
   808                 , dx, -dy, trackFall);
   795                 , dx, -dy, trackFall);
   809         if (v1 > valueResult) or (v2 > valueResult) then
   796         if (v1 > valueResult) or (v2 > valueResult) then
   810             if (v2 > v1)
   797             if (v2 > v1)
   811                 or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   798                 or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   826         valueResult:= BadTurn;
   813         valueResult:= BadTurn;
   827 
   814 
   828     TestBaseballBat:= valueResult;
   815     TestBaseballBat:= valueResult;
   829 end;
   816 end;
   830 
   817 
   831 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   818 function TestFirePunch(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   832 var valueResult, v1, v2, i: LongInt;
   819 var valueResult, v1, v2, i: LongInt;
   833     x, y, trackFall: LongInt;
   820     x, y, trackFall: LongInt;
   834 begin
   821 begin
   835     Targ:= Targ; // avoid compiler hint
   822     Targ:= Targ; // avoid compiler hint
   836 
   823 
   844     y:= hwRound(Me^.Y) + 4;
   831     y:= hwRound(Me^.Y) + 4;
   845 
   832 
   846     v1:= 0;
   833     v1:= 0;
   847     for i:= 0 to 8 do
   834     for i:= 0 to 8 do
   848         begin
   835         begin
   849         v1:= v1 + RateShove(x - 5, y - 10 * i
   836         v1:= v1 + RateShove(Me, x - 5, y - 10 * i
   850                 , 19, 30, 40
   837                 , 19, 30, 40
   851                 , -0.45, -0.9, trackFall or afSetSkip);
   838                 , -0.45, -0.9, trackFall or afSetSkip);
   852         end;
   839         end;
   853     v1:= v1 + RateShove(x - 5, y - 90
   840     v1:= v1 + RateShove(Me, x - 5, y - 90
   854             , 19, 30, 40
   841             , 19, 30, 40
   855             , -0.45, -0.9, trackFall);
   842             , -0.45, -0.9, trackFall);
   856 
   843 
   857 
   844 
   858     // now try opposite direction
   845     // now try opposite direction
   859     v2:= 0;
   846     v2:= 0;
   860     for i:= 0 to 8 do
   847     for i:= 0 to 8 do
   861         begin
   848         begin
   862         v2:= v2 + RateShove(x + 5, y - 10 * i
   849         v2:= v2 + RateShove(Me, x + 5, y - 10 * i
   863                 , 19, 30, 40
   850                 , 19, 30, 40
   864                 , 0.45, -0.9, trackFall or afSetSkip);
   851                 , 0.45, -0.9, trackFall or afSetSkip);
   865         end;
   852         end;
   866     v2:= v2 + RateShove(x + 5, y - 90
   853     v2:= v2 + RateShove(Me, x + 5, y - 90
   867             , 19, 30, 40
   854             , 19, 30, 40
   868             , 0.45, -0.9, trackFall);
   855             , 0.45, -0.9, trackFall);
   869 
   856 
   870     if (v2 > v1)
   857     if (v2 > v1)
   871         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   858         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   884 
   871 
   885     TestFirePunch:= valueResult;
   872     TestFirePunch:= valueResult;
   886 end;
   873 end;
   887 
   874 
   888 
   875 
   889 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   876 function TestWhip(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   890 var valueResult, v1, v2: LongInt;
   877 var valueResult, v1, v2: LongInt;
   891     x, y, trackFall: LongInt;
   878     x, y, trackFall: LongInt;
   892 begin
   879 begin
   893     Targ:= Targ; // avoid compiler hint
   880     Targ:= Targ; // avoid compiler hint
   894 
   881 
   903 
   890 
   904     // check left direction
   891     // check left direction
   905     {first RateShove checks farthermost of two whip's AmmoShove attacks
   892     {first RateShove checks farthermost of two whip's AmmoShove attacks
   906     to encourage distant attacks (damaged hog is excluded from view of second
   893     to encourage distant attacks (damaged hog is excluded from view of second
   907     RateShove call)}
   894     RateShove call)}
   908     v1:= RateShove(x - 13, y
   895     v1:= RateShove(Me, x - 13, y
   909             , 30, 30, 25
   896             , 30, 30, 25
   910             , -1, -0.8, trackFall or afSetSkip);
   897             , -1, -0.8, trackFall or afSetSkip);
   911     v1:= v1 +
   898     v1:= v1 +
   912         RateShove(x - 2, y
   899         RateShove(Me, x - 2, y
   913             , 30, 30, 25
   900             , 30, 30, 25
   914             , -1, -0.8, trackFall);
   901             , -1, -0.8, trackFall);
   915     // now try opposite direction
   902     // now try opposite direction
   916     v2:= RateShove(x + 13, y
   903     v2:= RateShove(Me, x + 13, y
   917             , 30, 30, 25
   904             , 30, 30, 25
   918             , 1, -0.8, trackFall or afSetSkip);
   905             , 1, -0.8, trackFall or afSetSkip);
   919     v2:= v2 +
   906     v2:= v2 +
   920         RateShove(x + 2, y
   907         RateShove(Me, x + 2, y
   921             , 30, 30, 25
   908             , 30, 30, 25
   922             , 1, -0.8, trackFall);
   909             , 1, -0.8, trackFall);
   923 
   910 
   924     if (v2 > v1)
   911     if (v2 > v1)
   925         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   912         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   939         inc(valueResult);
   926         inc(valueResult);
   940 
   927 
   941     TestWhip:= valueResult;
   928     TestWhip:= valueResult;
   942 end;
   929 end;
   943 
   930 
   944 function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
   931 function TestKamikaze(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
   945 const step = 8;
   932 const step = 8;
   946 var valueResult, i, v, tx: LongInt;
   933 var valueResult, i, v, tx: LongInt;
   947     trackFall: LongInt;
   934     trackFall: LongInt;
   948     t, d, x, y, dx, dy, cx: real;
   935     t, d, x, y, dx, dy, cx: real;
   949 begin
   936 begin
   961     valueResult:= 0;
   948     valueResult:= 0;
   962     v:= 0;
   949     v:= 0;
   963 
   950 
   964     x:= hwFloat2Float(Me^.X);
   951     x:= hwFloat2Float(Me^.X);
   965     y:= hwFloat2Float(Me^.Y);
   952     y:= hwFloat2Float(Me^.Y);
   966     d:= sqrt(sqr(Targ.X - x) + sqr(Targ.Y - y));
   953     d:= sqrt(sqr(Targ.Point.X - x) + sqr(Targ.Point.Y - y));
   967     if d < 10 then
   954     if d < 10 then
   968         begin
   955         begin
   969         dx:= 0;
   956         dx:= 0;
   970         dy:= 8;
   957         dy:= 8;
   971         ap.Angle:= 2048
   958         ap.Angle:= 2048
   972         end
   959         end
   973     else
   960     else
   974         begin
   961         begin
   975         t:= step / d;
   962         t:= step / d;
   976         dx:= (Targ.X - x) * t;
   963         dx:= (Targ.Point.X - x) * t;
   977         dy:= (Targ.Y - y) * t;
   964         dy:= (Targ.Point.Y - y) * t;
   978 
   965 
   979         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
   966         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
   980         end;
   967         end;
   981 
   968 
   982     if dx >= 0 then cx:= 0.45 else cx:= -0.45;
   969     if dx >= 0 then cx:= 0.45 else cx:= -0.45;
   983 
   970 
   984     for i:= 0 to 512 div step - 2 do
   971     for i:= 0 to 512 div step - 2 do
   985         begin
   972         begin
   986         valueResult:= valueResult +
   973         valueResult:= valueResult +
   987             RateShove(trunc(x), trunc(y)
   974             RateShove(Me, trunc(x), trunc(y)
   988                 , 30, 30, 25
   975                 , 30, 30, 25
   989                 , cx, -0.9, trackFall or afSetSkip);
   976                 , cx, -0.9, trackFall or afSetSkip);
   990 
   977 
   991         x:= x + dx;
   978         x:= x + dx;
   992         y:= y + dy;
   979         y:= y + dy;
   994     if dx = 0 then
   981     if dx = 0 then
   995         begin
   982         begin
   996         x:= hwFloat2Float(Me^.X);
   983         x:= hwFloat2Float(Me^.X);
   997         y:= hwFloat2Float(Me^.Y);
   984         y:= hwFloat2Float(Me^.Y);
   998         tx:= trunc(x);
   985         tx:= trunc(x);
   999         v:= RateShove(tx, trunc(y)
   986         v:= RateShove(Me, tx, trunc(y)
  1000                 , 30, 30, 25
   987                 , 30, 30, 25
  1001                 , -cx, -0.9, trackFall);
   988                 , -cx, -0.9, trackFall);
  1002         for i:= 1 to 512 div step - 2 do
   989         for i:= 1 to 512 div step - 2 do
  1003             begin
   990             begin
  1004             y:= y + dy;
   991             y:= y + dy;
  1005             v:= v +
   992             v:= v +
  1006                 RateShove(tx, trunc(y)
   993                 RateShove(Me, tx, trunc(y)
  1007                     , 30, 30, 25
   994                     , 30, 30, 25
  1008                     , -cx, -0.9, trackFall or afSetSkip);
   995                     , -cx, -0.9, trackFall or afSetSkip);
  1009             end
   996             end
  1010         end;
   997         end;
  1011     if v > valueResult then
   998     if v > valueResult then
  1012         begin
   999         begin
  1013         ap.Angle:= -2048;
  1000         ap.Angle:= -2048;
  1014         valueResult:= v
  1001         valueResult:= v
  1015         end;
  1002         end;
  1016 
  1003 
  1017     v:= RateShove(trunc(x), trunc(y)
  1004     v:= RateShove(Me, trunc(x), trunc(y)
  1018             , 30, 30, 25
  1005             , 30, 30, 25
  1019             , cx, -0.9, trackFall);
  1006             , cx, -0.9, trackFall);
  1020     valueResult:= valueResult + v - KillScore * friendlyfactor div 100 * 1024;
  1007     valueResult:= valueResult + v - KillScore * friendlyfactor div 100 * 1024;
  1021 
  1008 
  1022     if v < 65536 then
  1009     if v < 65536 then
  1023         inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30));
  1010         inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30));
  1024 
  1011 
  1025     TestKamikaze:= valueResult;
  1012     TestKamikaze:= valueResult;
  1026 end;
  1013 end;
  1027 
  1014 
  1028 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1015 function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1029 var rate: LongInt;
  1016 var rate: LongInt;
  1030 begin
  1017 begin
  1031 Level:= Level; // avoid compiler hint
  1018 Level:= Level; // avoid compiler hint
  1032 Targ:= Targ;
  1019 Targ:= Targ;
  1033 
  1020 
  1040 if rate = 0 then
  1027 if rate = 0 then
  1041     rate:= BadTurn;
  1028     rate:= BadTurn;
  1042 TestHammer:= rate;
  1029 TestHammer:= rate;
  1043 end;
  1030 end;
  1044 
  1031 
  1045 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1032 function TestAirAttack(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1046 const cShift = 4;
  1033 const cShift = 4;
  1047 var bombsSpeed, X, Y, dY: real;
  1034 var bombsSpeed, X, Y, dY: real;
  1048     b: array[0..9] of boolean;
  1035     b: array[0..9] of boolean;
  1049     dmg: array[0..9] of LongInt;
  1036     dmg: array[0..9] of LongInt;
  1050     fexit: boolean;
  1037     fexit: boolean;
  1054 ap.Time:= 0;
  1041 ap.Time:= 0;
  1055 if (Level > 3) then
  1042 if (Level > 3) then
  1056     exit(BadTurn);
  1043     exit(BadTurn);
  1057 
  1044 
  1058 ap.Angle:= 0;
  1045 ap.Angle:= 0;
  1059 ap.AttackPutX:= Targ.X;
  1046 ap.AttackPutX:= Targ.Point.X;
  1060 ap.AttackPutY:= Targ.Y;
  1047 ap.AttackPutY:= Targ.Point.Y;
  1061 
  1048 
  1062 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1049 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1063 X:= Targ.X - 135 - cShift; // hh center - cShift
  1050 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1064 X:= X - bombsSpeed * sqrt(((Targ.Y + 128) * 2) / cGravityf);
  1051 X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / cGravityf);
  1065 Y:= -128;
  1052 Y:= -128;
  1066 dY:= 0;
  1053 dY:= 0;
  1067 
  1054 
  1068 for i:= 0 to 9 do
  1055 for i:= 0 to 9 do
  1069     begin
  1056     begin
  1091             end;
  1078             end;
  1092 until fexit or (Y > cWaterLine);
  1079 until fexit or (Y > cWaterLine);
  1093 
  1080 
  1094 for i:= 0 to 5 do inc(valueResult, dmg[i]);
  1081 for i:= 0 to 5 do inc(valueResult, dmg[i]);
  1095 t:= valueResult;
  1082 t:= valueResult;
  1096 ap.AttackPutX:= Targ.X - 60;
  1083 ap.AttackPutX:= Targ.Point.X - 60;
  1097 
  1084 
  1098 for i:= 0 to 3 do
  1085 for i:= 0 to 3 do
  1099     begin
  1086     begin
  1100     dec(t, dmg[i]);
  1087     dec(t, dmg[i]);
  1101     inc(t, dmg[i + 6]);
  1088     inc(t, dmg[i + 6]);
  1102     if t > valueResult then
  1089     if t > valueResult then
  1103         begin
  1090         begin
  1104         valueResult:= t;
  1091         valueResult:= t;
  1105         ap.AttackPutX:= Targ.X - 30 - cShift + i * 30
  1092         ap.AttackPutX:= Targ.Point.X - 30 - cShift + i * 30
  1106         end
  1093         end
  1107     end;
  1094     end;
  1108 
  1095 
  1109 if valueResult <= 0 then
  1096 if valueResult <= 0 then
  1110     valueResult:= BadTurn;
  1097     valueResult:= BadTurn;
  1111 TestAirAttack:= valueResult;
  1098 TestAirAttack:= valueResult;
  1112 end;
  1099 end;
  1113 
  1100 
  1114 
  1101 
  1115 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1102 function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1116 var
  1103 var
  1117     i, failNum: longword;
  1104     i, failNum: longword;
  1118     maxTop: longword;
  1105     maxTop: longword;
  1119 begin
  1106 begin
  1120     TestTeleport := BadTurn;
  1107     TestTeleport := BadTurn;
  1123     //FillBonuses(true, [gtCase]);
  1110     //FillBonuses(true, [gtCase]);
  1124     if bonuses.Count = 0 then
  1111     if bonuses.Count = 0 then
  1125         begin
  1112         begin
  1126         if Me^.Health <= 100  then
  1113         if Me^.Health <= 100  then
  1127             begin
  1114             begin
  1128             maxTop := Targ.Y - cHHRadius * 2;
  1115             maxTop := Targ.Point.Y - cHHRadius * 2;
  1129 
  1116 
  1130             while (not TestColl(Targ.X, maxTop, cHHRadius)) and (maxTop > topY + cHHRadius * 2 + 1) do
  1117             while not TestColl(Targ.Point.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
  1131                 dec(maxTop, cHHRadius*2);
  1118                 dec(maxTop, cHHRadius*2);
  1132             if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then
  1119             if not TestColl(Targ.Point.X, maxTop + cHHRadius, cHHRadius) then
  1133                 begin
  1120                 begin
  1134                 ap.AttackPutX := Targ.X;
  1121                 ap.AttackPutX := Targ.Point.X;
  1135                 ap.AttackPutY := maxTop + cHHRadius;
  1122                 ap.AttackPutY := maxTop + cHHRadius;
  1136                 TestTeleport := Targ.Y - maxTop;
  1123                 TestTeleport := Targ.Point.Y - maxTop;
  1137                 end;
  1124                 end;
  1138             end;
  1125             end;
  1139         end
  1126         end
  1140     else
  1127     else
  1141         begin
  1128         begin
  1174         ap.Power:= v
  1161         ap.Power:= v
  1175         end
  1162         end
  1176     end;
  1163     end;
  1177 end;
  1164 end;
  1178 
  1165 
  1179 function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
  1166 function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
  1180 var valueResult, v1, v2: LongInt;
  1167 var valueResult, v1, v2: LongInt;
  1181     cake: TGear;
  1168     cake: TGear;
  1182 begin
  1169 begin
  1183     Targ:= Targ; // avoid compiler hint
  1170     Targ:= Targ; // avoid compiler hint
  1184 
  1171