hedgewars/uAIAmmoTests.pas
changeset 8933 19be64b0f36e
parent 8924 13ac59499066
child 8950 3bf81ed1f984
equal deleted inserted replaced
8925:f52c6f9800ca 8933:19be64b0f36e
    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;
    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;
    29 
    29 
   161             x:= x + dX;
   161             x:= x + dX;
   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^.Hedgehog^.Gear, 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);
   224                 x:= x + dX;
   224                 x:= x + dX;
   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^.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.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then
   233                 begin
   233                 begin
   234                 timer := 500;
   234                 timer := 500;
   301             x:= x + dX;
   301             x:= x + dX;
   302             y:= y + dY;
   302             y:= y + dY;
   303             dX:= dX + windSpeed;
   303             dX:= dX + windSpeed;
   304             dY:= dY + cGravityf;
   304             dY:= dY + cGravityf;
   305             dec(t)
   305             dec(t)
   306         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
   307                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, 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);
   308         EX:= trunc(x);
   308         EX:= trunc(x);
   309         EY:= trunc(y);
   309         EY:= trunc(y);
   310 
   310 
   311         value:= RateShove(trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
   311         value:= RateShove(trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
   353         repeat
   353         repeat
   354             x:= x + Vx;
   354             x:= x + Vx;
   355             y:= y + dY;
   355             y:= y + dY;
   356             dY:= dY + cGravityf;
   356             dY:= dY + cGravityf;
   357             dec(t)
   357             dec(t)
   358         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
   359                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, 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);
   360         EX:= trunc(x);
   360         EX:= trunc(x);
   361         EY:= trunc(y);
   361         EY:= trunc(y);
   362         if t < 50 then
   362         if t < 50 then
   363             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
   364         else
   364         else
   365             Score:= BadTurn;
   365             Score:= BadTurn;
   366                   
   366 
   367         if valueResult < Score then
   367         if valueResult < Score then
   368             begin
   368             begin
   369             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   369             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   370             ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   370             ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   371             ap.ExplR:= 100;
   371             ap.ExplR:= 100;
   397     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Y - meY) / (TestTime + tDelta);
   397     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.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;
   403         dY:= -Vy;
   403         dY:= -Vy;
   404         t:= TestTime;
   404         t:= TestTime;
   405         repeat
   405         repeat
   406             x:= x + Vx;
   406             x:= x + Vx;
   407             y:= y + dY;
   407             y:= y + dY;
   408             dY:= dY + cGravityf;
   408             dY:= dY + cGravityf;
   409             dec(t)
   409             dec(t)
   410         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
   411                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, 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);
   412     EX:= trunc(x);
   412     EX:= trunc(x);
   413     EY:= trunc(y);
   413     EY:= trunc(y);
   414     if t < 50 then 
   414     if t < 50 then
   415         if Level = 1 then
   415         if Level = 1 then
   416             Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   416             Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
   417         else Score:= RateExplosion(Me, EX, EY, 101)
   417         else Score:= RateExplosion(Me, EX, EY, 101)
   418     else 
   418     else
   419         Score:= BadTurn;
   419         Score:= BadTurn;
   420 
   420 
   421     if (valueResult < Score) and (Score > 0) then
   421     if (valueResult < Score) and (Score > 0) then
   422         begin
   422         begin
   423         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 3));
   423         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 3));
   465     repeat
   465     repeat
   466         x:= x + Vx;
   466         x:= x + Vx;
   467         y:= y + dY;
   467         y:= y + dY;
   468         dY:= dY + cGravityf;
   468         dY:= dY + cGravityf;
   469         dec(t)
   469         dec(t)
   470     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
   471            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, 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);
   472     EX:= trunc(x);
   472     EX:= trunc(x);
   473     EY:= trunc(y);
   473     EY:= trunc(y);
   474     if t < 50 then 
   474     if t < 50 then
   475         Score:= RateExplosion(Me, EX, EY, 41)
   475         Score:= RateExplosion(Me, EX, EY, 41)
   476     else 
   476     else
   477         Score:= BadTurn;
   477         Score:= BadTurn;
   478 
   478 
   479      if valueResult < Score then
   479      if valueResult < Score then
   480         begin
   480         begin
   481         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 2));
   481         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 2));
   518         repeat
   518         repeat
   519             x:= x + Vx;
   519             x:= x + Vx;
   520             y:= y + dY;
   520             y:= y + dY;
   521             dY:= dY + cGravityf;
   521             dY:= dY + cGravityf;
   522             dec(t)
   522             dec(t)
   523        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
   524                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, 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);
   525         
   525 
   526         EX:= trunc(x);
   526         EX:= trunc(x);
   527         EY:= trunc(y);
   527         EY:= trunc(y);
   528         if t < 50 then 
   528         if t < 50 then
   529             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)
   530         else 
   530         else
   531             Score:= BadTurn;
   531             Score:= BadTurn;
   532             
   532 
   533         if valueResult < Score then
   533         if valueResult < Score then
   534             begin
   534             begin
   535             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   535             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
   536             ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   536             ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
   537             ap.Time:= TestTime div 1000 * 1000;
   537             ap.Time:= TestTime div 1000 * 1000;
   564             Solve:= trunc(T)
   564             Solve:= trunc(T)
   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: TPoint; 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;
   599         x:= x + Vx;
   599         x:= x + Vx;
   600         y:= y + dY;
   600         y:= y + dY;
   601         dY:= dY + cGravityf;
   601         dY:= dY + cGravityf;
   602         EX:= trunc(x);
   602         EX:= trunc(x);
   603         EY:= trunc(y);
   603         EY:= trunc(y);
   604     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or 
   604     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or
   605            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine);
   605            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine);
   606 
   606 
   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);
   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);
   657     ry:= trunc(y);
   657     ry:= trunc(y);
   658     if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or 
   658     if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or
   659         ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 2)) then
   659         ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 2)) then
   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 then
   666             valueResult:= 1024 - Metric(Targ.X, Targ.Y, rx, ry) div 64
   666             valueResult:= 1024 - Metric(Targ.X, Targ.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.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
   768 if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then
   768 if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then
   769     begin
   769     begin
   770     fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg);
   770     fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg);
   771     if fallDmg < 0 then
   771     if fallDmg < 0 then
   772         TestSniperRifle:= BadTurn
   772         TestSniperRifle:= BadTurn
   773     else 
   773     else
   774         TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024)
   774         TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024)
   775     end
   775     end
   776 else
   776 else
   777     TestSniperRifle:= BadTurn
   777     TestSniperRifle:= BadTurn
   778 end;
   778 end;
   807                 , -dx, -dy, trackFall);
   807                 , -dx, -dy, trackFall);
   808         v2:= RateShove(x + 10, y + 2
   808         v2:= RateShove(x + 10, y + 2
   809                 , 32, 30, 115
   809                 , 32, 30, 115
   810                 , dx, -dy, trackFall);
   810                 , dx, -dy, trackFall);
   811         if (v1 > valueResult) or (v2 > valueResult) then
   811         if (v1 > valueResult) or (v2 > valueResult) then
   812             if (v2 > v1) 
   812             if (v2 > v1)
   813                 or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   813                 or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   814                 begin
   814                 begin
   815                 ap.Angle:= a;
   815                 ap.Angle:= a;
   816                 valueResult:= v2
   816                 valueResult:= v2
   817                 end
   817                 end
   818             else 
   818             else
   819                 begin
   819                 begin
   820                 ap.Angle:= -a;
   820                 ap.Angle:= -a;
   821                 valueResult:= v1
   821                 valueResult:= v1
   822                 end;
   822                 end;
   823 
   823 
   824         a:= a - 15 - random(cMaxAngle div 16)
   824         a:= a - 15 - random(cMaxAngle div 16)
   825         end;
   825         end;
   826    
   826 
   827     if valueResult <= 0 then
   827     if valueResult <= 0 then
   828         valueResult:= BadTurn;
   828         valueResult:= BadTurn;
   829 
   829 
   830     TestBaseballBat:= valueResult;
   830     TestBaseballBat:= valueResult;
   831 end;
   831 end;
   867         end;
   867         end;
   868     v2:= v2 + RateShove(x + 5, y - 90
   868     v2:= v2 + RateShove(x + 5, y - 90
   869             , 19, 30, 40
   869             , 19, 30, 40
   870             , 0.45, -0.9, trackFall);
   870             , 0.45, -0.9, trackFall);
   871 
   871 
   872     if (v2 > v1) 
   872     if (v2 > v1)
   873         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   873         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   874         begin
   874         begin
   875         ap.Angle:= 1;
   875         ap.Angle:= 1;
   876         valueResult:= v2
   876         valueResult:= v2
   877         end
   877         end
   878     else 
   878     else
   879         begin
   879         begin
   880         ap.Angle:= -1;
   880         ap.Angle:= -1;
   881         valueResult:= v1
   881         valueResult:= v1
   882         end;
   882         end;
   883     
   883 
   884     if valueResult <= 0 then
   884     if valueResult <= 0 then
   885         valueResult:= BadTurn;
   885         valueResult:= BadTurn;
   886 
   886 
   887     TestFirePunch:= valueResult;
   887     TestFirePunch:= valueResult;
   888 end;
   888 end;
   902     ap.Power:= 1;
   902     ap.Power:= 1;
   903     x:= hwRound(Me^.X);
   903     x:= hwRound(Me^.X);
   904     y:= hwRound(Me^.Y);
   904     y:= hwRound(Me^.Y);
   905 
   905 
   906     // check left direction
   906     // check left direction
   907     {first RateShove checks farthermost of two whip's AmmoShove attacks 
   907     {first RateShove checks farthermost of two whip's AmmoShove attacks
   908     to encourage distant attacks (damaged hog is excluded from view of second 
   908     to encourage distant attacks (damaged hog is excluded from view of second
   909     RateShove call)}
   909     RateShove call)}
   910     v1:= RateShove(x - 13, y
   910     v1:= RateShove(x - 13, y
   911             , 30, 30, 25
   911             , 30, 30, 25
   912             , -1, -0.8, trackFall or afSetSkip);
   912             , -1, -0.8, trackFall or afSetSkip);
   913     v1:= v1 +
   913     v1:= v1 +
   921     v2:= v2 +
   921     v2:= v2 +
   922         RateShove(x + 2, y
   922         RateShove(x + 2, y
   923             , 30, 30, 25
   923             , 30, 30, 25
   924             , 1, -0.8, trackFall);
   924             , 1, -0.8, trackFall);
   925 
   925 
   926     if (v2 > v1) 
   926     if (v2 > v1)
   927         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   927         or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
   928         begin
   928         begin
   929         ap.Angle:= 1;
   929         ap.Angle:= 1;
   930         valueResult:= v2
   930         valueResult:= v2
   931         end
   931         end
   932     else 
   932     else
   933         begin
   933         begin
   934         ap.Angle:= -1;
   934         ap.Angle:= -1;
   935         valueResult:= v1
   935         valueResult:= v1
   936         end;
   936         end;
   937     
   937 
   938     if valueResult <= 0 then
   938     if valueResult <= 0 then
   939         valueResult:= BadTurn
   939         valueResult:= BadTurn
   940     else
   940     else
   941         inc(valueResult);
   941         inc(valueResult);
   942 
   942 
   951 begin
   951 begin
   952     ap.ExplR:= 0;
   952     ap.ExplR:= 0;
   953     ap.Time:= 0;
   953     ap.Time:= 0;
   954     ap.Power:= 1;
   954     ap.Power:= 1;
   955 
   955 
   956     if Level = 1 then 
   956     if Level = 1 then
   957         trackFall:= afTrackFall
   957         trackFall:= afTrackFall
   958     else if Level = 2 then
   958     else if Level = 2 then
   959         trackFall:= 0
   959         trackFall:= 0
   960     else
   960     else
   961         exit(BadTurn);
   961         exit(BadTurn);
   962         
   962 
   963     valueResult:= 0;
   963     valueResult:= 0;
   964     v:= 0;
   964     v:= 0;
   965 
   965 
   966     x:= hwFloat2Float(Me^.X);
   966     x:= hwFloat2Float(Me^.X);
   967     y:= hwFloat2Float(Me^.Y);
   967     y:= hwFloat2Float(Me^.Y);
   978         dx:= (Targ.X - x) * t;
   978         dx:= (Targ.X - x) * t;
   979         dy:= (Targ.Y - y) * t;
   979         dy:= (Targ.Y - y) * t;
   980 
   980 
   981         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
   981         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
   982         end;
   982         end;
   983     
   983 
   984     if dx >= 0 then cx:= 0.45 else cx:= -0.45;
   984     if dx >= 0 then cx:= 0.45 else cx:= -0.45;
   985 
   985 
   986     for i:= 0 to 512 div step - 2 do
   986     for i:= 0 to 512 div step - 2 do
   987         begin
   987         begin
   988         valueResult:= valueResult + 
   988         valueResult:= valueResult +
   989             RateShove(trunc(x), trunc(y)
   989             RateShove(trunc(x), trunc(y)
   990                 , 30, 30, 25
   990                 , 30, 30, 25
   991                 , cx, -0.9, trackFall or afSetSkip);
   991                 , cx, -0.9, trackFall or afSetSkip);
   992                 
   992 
   993         x:= x + dx;
   993         x:= x + dx;
   994         y:= y + dy;
   994         y:= y + dy;
   995         end;
   995         end;
   996     if dx = 0 then
   996     if dx = 0 then
   997         begin
   997         begin
  1002                 , 30, 30, 25
  1002                 , 30, 30, 25
  1003                 , -cx, -0.9, trackFall);
  1003                 , -cx, -0.9, trackFall);
  1004         for i:= 1 to 512 div step - 2 do
  1004         for i:= 1 to 512 div step - 2 do
  1005             begin
  1005             begin
  1006             y:= y + dy;
  1006             y:= y + dy;
  1007             v:= v + 
  1007             v:= v +
  1008                 RateShove(tx, trunc(y)
  1008                 RateShove(tx, trunc(y)
  1009                     , 30, 30, 25
  1009                     , 30, 30, 25
  1010                     , -cx, -0.9, trackFall or afSetSkip);
  1010                     , -cx, -0.9, trackFall or afSetSkip);
  1011             end
  1011             end
  1012         end;
  1012         end;
  1035 
  1035 
  1036 ap.ExplR:= 0;
  1036 ap.ExplR:= 0;
  1037 ap.Time:= 0;
  1037 ap.Time:= 0;
  1038 ap.Power:= 1;
  1038 ap.Power:= 1;
  1039 ap.Angle:= 0;
  1039 ap.Angle:= 0;
  1040          
  1040 
  1041 rate:= RateHammer(Me);
  1041 rate:= RateHammer(Me);
  1042 if rate = 0 then
  1042 if rate = 0 then
  1043     rate:= BadTurn;
  1043     rate:= BadTurn;
  1044 TestHammer:= rate;
  1044 TestHammer:= rate;
  1045 end;
  1045 end;
  1126     if bonuses.Count = 0 then
  1126     if bonuses.Count = 0 then
  1127         begin
  1127         begin
  1128         if Me^.Health <= 100  then
  1128         if Me^.Health <= 100  then
  1129             begin
  1129             begin
  1130             maxTop := Targ.Y - cHHRadius * 2;
  1130             maxTop := Targ.Y - cHHRadius * 2;
  1131             
  1131 
  1132             while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
  1132             while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
  1133                 dec(maxTop, cHHRadius*2);
  1133                 dec(maxTop, cHHRadius*2);
  1134             if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then
  1134             if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then
  1135                 begin
  1135                 begin
  1136                 ap.AttackPutX := Targ.X;
  1136                 ap.AttackPutX := Targ.X;
  1145         repeat
  1145         repeat
  1146             i := random(bonuses.Count);
  1146             i := random(bonuses.Count);
  1147             inc(failNum);
  1147             inc(failNum);
  1148         until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius)
  1148         until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius)
  1149         or (failNum = bonuses.Count*2);
  1149         or (failNum = bonuses.Count*2);
  1150         
  1150 
  1151         if failNum < bonuses.Count*2 then
  1151         if failNum < bonuses.Count*2 then
  1152             begin
  1152             begin
  1153             ap.AttackPutX := bonuses.ar[i].X;
  1153             ap.AttackPutX := bonuses.ar[i].X;
  1154             ap.AttackPutY := bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius;
  1154             ap.AttackPutY := bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius;
  1155             TestTeleport := 0;
  1155             TestTeleport := 0;
  1167 
  1167 
  1168 for i:= 0 to 2040 do
  1168 for i:= 0 to 2040 do
  1169     begin
  1169     begin
  1170     cakeStep(Gear);
  1170     cakeStep(Gear);
  1171     v:= RateExplosion(Me, hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg * 2, afTrackFall);
  1171     v:= RateExplosion(Me, hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg * 2, afTrackFall);
  1172     if v > ap.Power then 
  1172     if v > ap.Power then
  1173         begin
  1173         begin
  1174         ap.ExplX:= hwRound(Gear^.X);
  1174         ap.ExplX:= hwRound(Gear^.X);
  1175         ap.ExplY:= hwRound(Gear^.Y);
  1175         ap.ExplY:= hwRound(Gear^.Y);
  1176         ap.Power:= v
  1176         ap.Power:= v
  1177         end
  1177         end