hedgewars/uAIAmmoTests.pas
changeset 15690 c4d7eb75fd8a
parent 15689 975232e840c7
child 15691 c6675acd3c82
equal deleted inserted replaced
15689:975232e840c7 15690:c4d7eb75fd8a
    29     amtest_LaserSight      = $00000010; // supports laser sighting
    29     amtest_LaserSight      = $00000010; // supports laser sighting
    30     amtest_NoVampiric      = $00000020; // don't use vampirism with this ammo
    30     amtest_NoVampiric      = $00000020; // don't use vampirism with this ammo
    31     amtest_NoInvulnerable  = $00000040; // don't use invulnerable with this with ammo
    31     amtest_NoInvulnerable  = $00000040; // don't use invulnerable with this with ammo
    32 
    32 
    33 var aiWindSpeed: real;
    33 var aiWindSpeed: real;
       
    34     aiGravity: hwFloat;
       
    35     aiGravityf: real;
    34     aiLaserSighting: boolean;
    36     aiLaserSighting: boolean;
    35 
    37 
    36 type TAttackParams = record
    38 type TAttackParams = record
    37         Time, Bounce, AttacksNum: Longword;
    39         Time, Bounce, AttacksNum: Longword;
    38         Angle, Power: LongInt;
    40         Angle, Power: LongInt;
   177 repeat
   179 repeat
   178     rTime:= rTime + 300 + Level * 50 + random(300);
   180     rTime:= rTime + 300 + Level * 50 + random(300);
   179     if (WorldEdge = weWrap) and (random(2)=0) then
   181     if (WorldEdge = weWrap) and (random(2)=0) then
   180          Vx:= - aiWindSpeed * rTime * 0.5 + (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - mX) / rTime
   182          Vx:= - aiWindSpeed * rTime * 0.5 + (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - mX) / rTime
   181     else Vx:= - aiWindSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - mX) / rTime;
   183     else Vx:= - aiWindSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - mX) / rTime;
   182     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - mY) / rTime;
   184     Vy:= aiGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - mY) / rTime;
   183     r:= sqr(Vx) + sqr(Vy);
   185     r:= sqr(Vx) + sqr(Vy);
   184     if not (r > 1) then
   186     if not (r > 1) then
   185         begin
   187         begin
   186         x:= mX;
   188         x:= mX;
   187         y:= mY;
   189         y:= mY;
   193             x:= x + dX;
   195             x:= x + dX;
   194 
   196 
   195             y:= y + dY;
   197             y:= y + dY;
   196             dX:= dX + aiWindSpeed;
   198             dX:= dX + aiWindSpeed;
   197             //dX:= CheckBounce(x,dX);
   199             //dX:= CheckBounce(x,dX);
   198             dY:= dY + cGravityf;
   200             dY:= dY + aiGravityf;
   199             dec(t)
   201             dec(t)
   200         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   202         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   201                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t < -cExtraTime);
   203                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t < -cExtraTime);
   202 
   204 
   203         EX:= trunc(x);
   205         EX:= trunc(x);
   238     // parabola flight before activation
   240     // parabola flight before activation
   239     t:= 500;
   241     t:= 500;
   240     repeat
   242     repeat
   241         x:= x + dx;
   243         x:= x + dx;
   242         y:= y + dy;
   244         y:= y + dy;
   243         dy:= dy + cGravityf;
   245         dy:= dy + aiGravityf;
   244         f:= ((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   246         f:= ((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   245            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5));
   247            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5));
   246         dec(t)
   248         dec(t)
   247     until (t = 0) or (y >= cWaterLine) or f;
   249     until (t = 0) or (y >= cWaterLine) or f;
   248 
   250 
   367     repeat
   369     repeat
   368         rTime:= rTime + 300 + Level * 50 + random(300);
   370         rTime:= rTime + 300 + Level * 50 + random(300);
   369         if (WorldEdge = weWrap) and (random(2)=0) then
   371         if (WorldEdge = weWrap) and (random(2)=0) then
   370              Vx:= - aiWindSpeed * rTime * 0.5 + (targXWrap + AIrndSign(2) - mX) / rTime
   372              Vx:= - aiWindSpeed * rTime * 0.5 + (targXWrap + AIrndSign(2) - mX) / rTime
   371         else Vx:= - aiWindSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime;
   373         else Vx:= - aiWindSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime;
   372         Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - 35 - mY) / rTime;
   374         Vy:= aiGravityf * rTime * 0.5 - (Targ.Point.Y - 35 - mY) / rTime;
   373         r:= sqr(Vx) + sqr(Vy);
   375         r:= sqr(Vx) + sqr(Vy);
   374         if not (r > 1) then
   376         if not (r > 1) then
   375             begin
   377             begin
   376             x:= mX;
   378             x:= mX;
   377             y:= mY;
   379             y:= mY;
   381             repeat
   383             repeat
   382                 x:= CheckWrap(x);
   384                 x:= CheckWrap(x);
   383                 x:= x + dX;
   385                 x:= x + dX;
   384                 y:= y + dY;
   386                 y:= y + dY;
   385                 dX:= dX + aiWindSpeed;
   387                 dX:= dX + aiWindSpeed;
   386                 dY:= dY + cGravityf;
   388                 dY:= dY + aiGravityf;
   387                 dec(t)
   389                 dec(t)
   388             until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   390             until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   389                    ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine);
   391                    ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine);
   390 
   392 
   391             if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then
   393             if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then
   533 repeat
   535 repeat
   534     rTime:= rTime + 300 + Level * 50 + random(1000);
   536     rTime:= rTime + 300 + Level * 50 + random(1000);
   535     if (WorldEdge = weWrap) and (random(2)=0) then
   537     if (WorldEdge = weWrap) and (random(2)=0) then
   536          Vx:= - aiWindSpeed * rTime * 0.5 + ((targXWrap + AIrndSign(2)) - meX) / rTime
   538          Vx:= - aiWindSpeed * rTime * 0.5 + ((targXWrap + AIrndSign(2)) - meX) / rTime
   537     else Vx:= - aiWindSpeed * rTime * 0.5 + ((Targ.Point.X + AIrndSign(2)) - meX) / rTime;
   539     else Vx:= - aiWindSpeed * rTime * 0.5 + ((Targ.Point.X + AIrndSign(2)) - meX) / rTime;
   538     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - meY) / rTime;
   540     Vy:= aiGravityf * rTime * 0.5 - (Targ.Point.Y - meY) / rTime;
   539     r:= sqr(Vx) + sqr(Vy);
   541     r:= sqr(Vx) + sqr(Vy);
   540     if not (r > 1) then
   542     if not (r > 1) then
   541         begin
   543         begin
   542         x:= meX;
   544         x:= meX;
   543         y:= meY;
   545         y:= meY;
   547         repeat
   549         repeat
   548             x:= CheckWrap(x);
   550             x:= CheckWrap(x);
   549             x:= x + dX;
   551             x:= x + dX;
   550             y:= y + dY;
   552             y:= y + dY;
   551             dX:= dX + aiWindSpeed;
   553             dX:= dX + aiWindSpeed;
   552             dY:= dY + cGravityf;
   554             dY:= dY + aiGravityf;
   553             dec(t)
   555             dec(t)
   554         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   556         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   555                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0);
   557                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0);
   556         EX:= trunc(x);
   558         EX:= trunc(x);
   557         EY:= trunc(y);
   559         EY:= trunc(y);
   603          Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime
   605          Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime
   604     else
   606     else
   605          Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime;
   607          Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime;
   606     if (GameFlags and gfMoreWind) <> 0 then
   608     if (GameFlags and gfMoreWind) <> 0 then
   607          Vx:= -(aiWindSpeed / Density) * rTime * 0.5 + Vx;
   609          Vx:= -(aiWindSpeed / Density) * rTime * 0.5 + Vx;
   608     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
   610     Vy:= aiGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
   609     r:= sqr(Vx) + sqr(Vy);
   611     r:= sqr(Vx) + sqr(Vy);
   610 
   612 
   611     if not (r > 1) then
   613     if not (r > 1) then
   612         begin
   614         begin
   613         x:= meX;
   615         x:= meX;
   620             x:= x + dX;
   622             x:= x + dX;
   621             if (GameFlags and gfMoreWind) <> 0 then
   623             if (GameFlags and gfMoreWind) <> 0 then
   622                 dX:= dX + aiWindSpeed / Density;
   624                 dX:= dX + aiWindSpeed / Density;
   623 
   625 
   624             y:= y + dY;
   626             y:= y + dY;
   625             dY:= dY + cGravityf;
   627             dY:= dY + aiGravityf;
   626             dec(t)
   628             dec(t)
   627         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   629         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   628                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t < -timeLimit);
   630                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t < -timeLimit);
   629 
   631 
   630         EX:= trunc(x);
   632         EX:= trunc(x);
   688          Vx:= (targXWrap + AIrndOffset(Targ, Level) - meX) / (TestTime + tDelta)
   690          Vx:= (targXWrap + AIrndOffset(Targ, Level) - meX) / (TestTime + tDelta)
   689     else
   691     else
   690          Vx:= (Targ.Point.X + AIrndOffset(Targ, Level) - meX) / (TestTime + tDelta);
   692          Vx:= (Targ.Point.X + AIrndOffset(Targ, Level) - meX) / (TestTime + tDelta);
   691     if (GameFlags and gfMoreWind) <> 0 then
   693     if (GameFlags and gfMoreWind) <> 0 then
   692          Vx:= -(aiWindSpeed / Density) * (TestTime + tDelta) * 0.5 + Vx;
   694          Vx:= -(aiWindSpeed / Density) * (TestTime + tDelta) * 0.5 + Vx;
   693     Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Point.Y - meY) / (TestTime + tDelta);
   695     Vy:= aiGravityf * ((TestTime + tDelta) div 2) - (Targ.Point.Y - meY) / (TestTime + tDelta);
   694     r:= sqr(Vx) + sqr(Vy);
   696     r:= sqr(Vx) + sqr(Vy);
   695     if not (r > 1) then
   697     if not (r > 1) then
   696         begin
   698         begin
   697         x:= meX;
   699         x:= meX;
   698         y:= meY;
   700         y:= meY;
   703             x:= CheckWrap(x);
   705             x:= CheckWrap(x);
   704             x:= x + dX;
   706             x:= x + dX;
   705             if (GameFlags and gfMoreWind) <> 0 then
   707             if (GameFlags and gfMoreWind) <> 0 then
   706                 dX:= dX + aiWindSpeed / Density;
   708                 dX:= dX + aiWindSpeed / Density;
   707             y:= y + dY;
   709             y:= y + dY;
   708             dY:= dY + cGravityf;
   710             dY:= dY + aiGravityf;
   709             dec(t)
   711             dec(t)
   710         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   712         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   711                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
   713                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
   712     EX:= trunc(x);
   714     EX:= trunc(x);
   713     EY:= trunc(y);
   715     EY:= trunc(y);
   757     // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
   759     // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
   758     else if meX<Targ.Point.X then
   760     else if meX<Targ.Point.X then
   759         Vx:= ((Targ.Point.X+10) - meX) / (TestTime + tDelta)
   761         Vx:= ((Targ.Point.X+10) - meX) / (TestTime + tDelta)
   760     else
   762     else
   761         Vx:= ((Targ.Point.X-10) - meX) / (TestTime + tDelta);
   763         Vx:= ((Targ.Point.X-10) - meX) / (TestTime + tDelta);
   762     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
   764     Vy:= aiGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
   763     r:= sqr(Vx)+sqr(Vy);
   765     r:= sqr(Vx)+sqr(Vy);
   764     if not (r > 1) then
   766     if not (r > 1) then
   765         begin
   767         begin
   766         x:= meX;
   768         x:= meX;
   767         dX:= Vx;
   769         dX:= Vx;
   771     repeat
   773     repeat
   772         x:= x + dX;
   774         x:= x + dX;
   773         if (GameFlags and gfMoreWind) <> 0 then
   775         if (GameFlags and gfMoreWind) <> 0 then
   774             dX:= dX + aiWindSpeed / Density;
   776             dX:= dX + aiWindSpeed / Density;
   775         y:= y + dY;
   777         y:= y + dY;
   776         dY:= dY + cGravityf;
   778         dY:= dY + aiGravityf;
   777         dec(t)
   779         dec(t)
   778     until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   780     until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
   779            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
   781            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
   780     EX:= trunc(x);
   782     EX:= trunc(x);
   781     EY:= trunc(y);
   783     EY:= trunc(y);
   825     else
   827     else
   826         Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
   828         Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
   827     if (GameFlags and gfMoreWind) <> 0 then
   829     if (GameFlags and gfMoreWind) <> 0 then
   828         Vx:= -(aiWindSpeed / Density) * (TestTime + tDelta) * 0.5 + Vx;
   830         Vx:= -(aiWindSpeed / Density) * (TestTime + tDelta) * 0.5 + Vx;
   829 
   831 
   830     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
   832     Vy:= aiGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
   831     r:= sqr(Vx)+sqr(Vy);
   833     r:= sqr(Vx)+sqr(Vy);
   832     if not (r > 1) then
   834     if not (r > 1) then
   833         begin
   835         begin
   834         x:= meX;
   836         x:= meX;
   835         dX:= Vx;
   837         dX:= Vx;
   840             x:= CheckWrap(x);
   842             x:= CheckWrap(x);
   841             x:= x + dX;
   843             x:= x + dX;
   842             if (GameFlags and gfMoreWind) <> 0 then
   844             if (GameFlags and gfMoreWind) <> 0 then
   843                  dX:= dX + aiWindSpeed / Density;
   845                  dX:= dX + aiWindSpeed / Density;
   844             y:= y + dY;
   846             y:= y + dY;
   845             dY:= dY + cGravityf;
   847             dY:= dY + aiGravityf;
   846             dec(t)
   848             dec(t)
   847        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
   849        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
   848                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
   850                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
   849 
   851 
   850         EX:= trunc(x);
   852         EX:= trunc(x);
   872 
   874 
   873     function Solve(TX, TY, MX, MY: LongInt): LongWord;
   875     function Solve(TX, TY, MX, MY: LongInt): LongWord;
   874     var A, B, D, T: real;
   876     var A, B, D, T: real;
   875         C: LongInt;
   877         C: LongInt;
   876     begin
   878     begin
   877         A:= sqr(cGravityf);
   879         A:= sqr(aiGravityf);
   878         B:= - cGravityf * (TY - MY) - 1;
   880         B:= - aiGravityf * (TY - MY) - 1;
   879         C:= sqr(TY - MY) + sqr(TX - MX);
   881         C:= sqr(TY - MY) + sqr(TX - MX);
   880         D:= sqr(B) - A * C;
   882         D:= sqr(B) - A * C;
   881         if D >= 0 then
   883         if D >= 0 then
   882             begin
   884             begin
   883             D:= sqrt(D) - B;
   885             D:= sqrt(D) - B;
   914         exit(BadTurn);
   916         exit(BadTurn);
   915 
   917 
   916     Vx:= (Targ.Point.X - meX) / TestTime;
   918     Vx:= (Targ.Point.X - meX) / TestTime;
   917     if (GameFlags and gfMoreWind) <> 0 then
   919     if (GameFlags and gfMoreWind) <> 0 then
   918         Vx:= -(aiWindSpeed / Density) * TestTime * 0.5 + Vx;
   920         Vx:= -(aiWindSpeed / Density) * TestTime * 0.5 + Vx;
   919     Vy:= cGravityf * (TestTime div 2) - (Targ.Point.Y - meY) / TestTime;
   921     Vy:= aiGravityf * (TestTime div 2) - (Targ.Point.Y - meY) / TestTime;
   920 
   922 
   921     x:= meX;
   923     x:= meX;
   922     dX:= Vx;
   924     dX:= Vx;
   923     y:= meY;
   925     y:= meY;
   924     dY:= -Vy;
   926     dY:= -Vy;
   926     repeat
   928     repeat
   927         x:= x + dX;
   929         x:= x + dX;
   928         if (GameFlags and gfMoreWind) <> 0 then
   930         if (GameFlags and gfMoreWind) <> 0 then
   929             dX:= dX + aiWindSpeed / Density;
   931             dX:= dX + aiWindSpeed / Density;
   930         y:= y + dY;
   932         y:= y + dY;
   931         dY:= dY + cGravityf;
   933         dY:= dY + aiGravityf;
   932         EX:= trunc(x);
   934         EX:= trunc(x);
   933         EY:= trunc(y);
   935         EY:= trunc(y);
   934     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or
   936     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or
   935            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine);
   937            ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine);
   936 
   938 
  1406     i, t, valueResult, targetY: LongInt;
  1408     i, t, valueResult, targetY: LongInt;
  1407 begin
  1409 begin
  1408 Flags:= Flags; // avoid compiler hint
  1410 Flags:= Flags; // avoid compiler hint
  1409 ap.ExplR:= 0;
  1411 ap.ExplR:= 0;
  1410 ap.Time:= 0;
  1412 ap.Time:= 0;
  1411 if (Level > 3) or (cGravityf = 0) then
  1413 if (Level > 3) or (aiGravityf = 0) then
  1412     exit(BadTurn);
  1414     exit(BadTurn);
  1413 
  1415 
  1414 ap.Angle:= 0;
  1416 ap.Angle:= 0;
  1415 ap.AttackPutX:= Targ.Point.X;
  1417 ap.AttackPutX:= Targ.Point.X;
  1416 ap.AttackPutY:= Targ.Point.Y;
  1418 ap.AttackPutY:= Targ.Point.Y;
  1417 
  1419 
  1418 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1420 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1419 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1421 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1420 X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / cGravityf);
  1422 X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / aiGravityf);
  1421 Y:= topY - 300;
  1423 Y:= topY - 300;
  1422 
  1424 
  1423 dX:= bombsSpeed;
  1425 dX:= bombsSpeed;
  1424 dY:= 0;
  1426 dY:= 0;
  1425 
  1427 
  1434 repeat
  1436 repeat
  1435     X:= X + dX;
  1437     X:= X + dX;
  1436     if (GameFlags and gfMoreWind) <> 0 then
  1438     if (GameFlags and gfMoreWind) <> 0 then
  1437         dX:= dX + aiWindSpeed / Density;
  1439         dX:= dX + aiWindSpeed / Density;
  1438     Y:= Y + dY;
  1440     Y:= Y + dY;
  1439     dY:= dY + cGravityf;
  1441     dY:= dY + aiGravityf;
  1440     fexit:= true;
  1442     fexit:= true;
  1441 
  1443 
  1442     for i:= 0 to 9 do
  1444     for i:= 0 to 9 do
  1443         if b[i] then
  1445         if b[i] then
  1444             begin
  1446             begin
  1536     collided, drilling, timerRuns, firstHit: boolean;
  1538     collided, drilling, timerRuns, firstHit: boolean;
  1537     i, t, value, valueResult, attackTime, drillTimer, targetX, targetY: LongInt;
  1539     i, t, value, valueResult, attackTime, drillTimer, targetX, targetY: LongInt;
  1538 begin
  1540 begin
  1539 Flags:= Flags; // avoid compiler hint
  1541 Flags:= Flags; // avoid compiler hint
  1540 ap.ExplR:= 0;
  1542 ap.ExplR:= 0;
  1541 if (Level > 3) or (cGravityf = 0) then
  1543 if (Level > 3) or (aiGravityf = 0) then
  1542     exit(BadTurn);
  1544     exit(BadTurn);
  1543 
  1545 
  1544 ap.Angle:= 0;
  1546 ap.Angle:= 0;
  1545 targetX:= Targ.Point.X;
  1547 targetX:= Targ.Point.X;
  1546 ap.AttackPutY:= Targ.Point.Y;
  1548 ap.AttackPutY:= Targ.Point.Y;
  1547 
  1549 
  1548 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1550 bombsSpeed:= hwFloat2Float(cBombsSpeed);
  1549 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1551 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1550 X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / cGravityf);
  1552 X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / aiGravityf);
  1551 Y:= topY - 300;
  1553 Y:= topY - 300;
  1552 
  1554 
  1553 valueResult:= 0;
  1555 valueResult:= 0;
  1554 
  1556 
  1555 attackTime:= 6000;
  1557 attackTime:= 6000;
  1574             // Simulate in-air movement
  1576             // Simulate in-air movement
  1575             drillX:= drillX + dX;
  1577             drillX:= drillX + dX;
  1576             drillY:= drillY + dY;
  1578             drillY:= drillY + dY;
  1577             if (GameFlags and gfMoreWind) <> 0 then
  1579             if (GameFlags and gfMoreWind) <> 0 then
  1578                 dX:= dX + aiWindSpeed / Density;
  1580                 dX:= dX + aiWindSpeed / Density;
  1579             dY:= dY + cGravityf;
  1581             dY:= dY + aiGravityf;
  1580 
  1582 
  1581             if timerRuns then
  1583             if timerRuns then
  1582                 dec(drillTimer);
  1584                 dec(drillTimer);
  1583 
  1585 
  1584             // Collided with land ... simulate drilling
  1586             // Collided with land ... simulate drilling
  1697 // predictable.
  1699 // predictable.
  1698 // Other cMinesTime values are risky because of bouncy mines;
  1700 // Other cMinesTime values are risky because of bouncy mines;
  1699 // so they are unsupported.
  1701 // so they are unsupported.
  1700 // TODO: Implement mine strike for other values of MineTime
  1702 // TODO: Implement mine strike for other values of MineTime
  1701 // TODO: Teach AI to avoid hitting their own with mines
  1703 // TODO: Teach AI to avoid hitting their own with mines
  1702 if (Level > 3) or (cGravityf = 0) or (cMinesTime <> 0) then
  1704 if (Level > 3) or (aiGravityf = 0) or (cMinesTime <> 0) then
  1703     exit(BadTurn);
  1705     exit(BadTurn);
  1704 
  1706 
  1705 ap.Angle:= 0;
  1707 ap.Angle:= 0;
  1706 ap.AttackPutX:= Targ.Point.X;
  1708 ap.AttackPutX:= Targ.Point.X;
  1707 ap.AttackPutY:= Targ.Point.Y;
  1709 ap.AttackPutY:= Targ.Point.Y;
  1708 
  1710 
  1709 minesSpeed:= hwFloat2Float(cBombsSpeed);
  1711 minesSpeed:= hwFloat2Float(cBombsSpeed);
  1710 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1712 X:= Targ.Point.X - 135 - cShift; // hh center - cShift
  1711 X:= X - minesSpeed * sqrt(((Targ.Point.Y + 128) * 2) / cGravityf);
  1713 X:= X - minesSpeed * sqrt(((Targ.Point.Y + 128) * 2) / aiGravityf);
  1712 Y:= topY - 300;
  1714 Y:= topY - 300;
  1713 dX:= minesSpeed;
  1715 dX:= minesSpeed;
  1714 dY:= 0;
  1716 dY:= 0;
  1715 
  1717 
  1716 for i:= 0 to 9 do
  1718 for i:= 0 to 9 do
  1724 repeat
  1726 repeat
  1725     X:= X + dX;
  1727     X:= X + dX;
  1726     if (GameFlags and (gfMoreWind or gfInfAttack)) <> 0 then
  1728     if (GameFlags and (gfMoreWind or gfInfAttack)) <> 0 then
  1727         dX:= dX + aiWindSpeed / Density;
  1729         dX:= dX + aiWindSpeed / Density;
  1728     Y:= Y + dY;
  1730     Y:= Y + dY;
  1729     dY:= dY + cGravityf;
  1731     dY:= dY + aiGravityf;
  1730     fexit:= true;
  1732     fexit:= true;
  1731 
  1733 
  1732     for i:= 0 to 9 do
  1734     for i:= 0 to 9 do
  1733         if b[i] then
  1735         if b[i] then
  1734             begin
  1736             begin
  1803          Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime
  1805          Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime
  1804     else
  1806     else
  1805          Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime;
  1807          Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime;
  1806     if (GameFlags and gfMoreWind) <> 0 then
  1808     if (GameFlags and gfMoreWind) <> 0 then
  1807          Vx:= -(aiWindSpeed / Density) * rTime * 0.5 + Vx;
  1809          Vx:= -(aiWindSpeed / Density) * rTime * 0.5 + Vx;
  1808     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
  1810     Vy:= aiGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
  1809     r:= sqr(Vx) + sqr(Vy);
  1811     r:= sqr(Vx) + sqr(Vy);
  1810 
  1812 
  1811     if not (r > 1) then
  1813     if not (r > 1) then
  1812         begin
  1814         begin
  1813         x:= meX;
  1815         x:= meX;
  1820             x:= x + dX;
  1822             x:= x + dX;
  1821             if (GameFlags and gfMoreWind) <> 0 then
  1823             if (GameFlags and gfMoreWind) <> 0 then
  1822                 dX:= dX + aiWindSpeed / Density;
  1824                 dX:= dX + aiWindSpeed / Density;
  1823 
  1825 
  1824             y:= y + dY;
  1826             y:= y + dY;
  1825             dY:= dY + cGravityf;
  1827             dY:= dY + aiGravityf;
  1826             dec(t)
  1828             dec(t)
  1827         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 2)) or
  1829         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 2)) or
  1828                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 2))) or (t < -timeLimit);
  1830                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 2))) or (t < -timeLimit);
  1829 
  1831 
  1830         EX:= trunc(x);
  1832         EX:= trunc(x);
  1861     firstHit, solidBounce: boolean;
  1863     firstHit, solidBounce: boolean;
  1862 begin
  1864 begin
  1863 Flags:= Flags; // avoid compiler hint
  1865 Flags:= Flags; // avoid compiler hint
  1864 ap.ExplR:= 0;
  1866 ap.ExplR:= 0;
  1865 ap.Time:= 0;
  1867 ap.Time:= 0;
  1866 if (cGravityf <= 0) then
  1868 if (aiGravityf <= 0) then
  1867     exit(BadTurn);
  1869     exit(BadTurn);
  1868 
  1870 
  1869 if (Level > 2) then
  1871 if (Level > 2) then
  1870     exit(BadTurn);
  1872     exit(BadTurn);
  1871 
  1873 
  2096 repeat
  2098 repeat
  2097     dec(t);
  2099     dec(t);
  2098     if (GameFlags and gfMoreWind) <> 0 then
  2100     if (GameFlags and gfMoreWind) <> 0 then
  2099         dx:= dx + aiWindSpeed / Density;
  2101         dx:= dx + aiWindSpeed / Density;
  2100     x:= x + dx;
  2102     x:= x + dx;
  2101     dy:= dy + cGravityf;
  2103     dy:= dy + aiGravityf;
  2102     y:= y + dy;
  2104     y:= y + dy;
  2103 
  2105 
  2104     if TestColl(trunc(x), trunc(y), 3) then
  2106     if TestColl(trunc(x), trunc(y), 3) then
  2105         t:= 0;
  2107         t:= 0;
  2106 until t = 0;
  2108 until t = 0;
  2146 repeat
  2148 repeat
  2147     dec(t);
  2149     dec(t);
  2148     if (GameFlags and gfMoreWind) <> 0 then
  2150     if (GameFlags and gfMoreWind) <> 0 then
  2149          dx:= dx + aiWindSpeed / Density;
  2151          dx:= dx + aiWindSpeed / Density;
  2150     x:= x + dx;
  2152     x:= x + dx;
  2151     dy:= dy + cGravityf;
  2153     dy:= dy + aiGravityf;
  2152     y:= y + dy;
  2154     y:= y + dy;
  2153     if ((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 2)) or
  2155     if ((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 2)) or
  2154         ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 2)) then
  2156         ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 2)) then
  2155         t:= 0;
  2157         t:= 0;
  2156 until t = 0;
  2158 until t = 0;
  2211          Vx:= (targXWrap - meX) / rTime
  2213          Vx:= (targXWrap - meX) / rTime
  2212     else
  2214     else
  2213          Vx:= (Targ.Point.X - meX) / rTime;
  2215          Vx:= (Targ.Point.X - meX) / rTime;
  2214     if (GameFlags and gfMoreWind) <> 0 then
  2216     if (GameFlags and gfMoreWind) <> 0 then
  2215          Vx:= -(aiWindSpeed / Density) * rTime * 0.5 + Vx;
  2217          Vx:= -(aiWindSpeed / Density) * rTime * 0.5 + Vx;
  2216     Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
  2218     Vy:= aiGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
  2217     r:= sqr(Vx) + sqr(Vy);
  2219     r:= sqr(Vx) + sqr(Vy);
  2218 
  2220 
  2219     if not (r > 1) then
  2221     if not (r > 1) then
  2220         begin
  2222         begin
  2221         x:= meX;
  2223         x:= meX;
  2228             x:= x + dX;
  2230             x:= x + dX;
  2229             if (GameFlags and gfMoreWind) <> 0 then
  2231             if (GameFlags and gfMoreWind) <> 0 then
  2230                 dX:= dX + aiWindSpeed / Density;
  2232                 dX:= dX + aiWindSpeed / Density;
  2231 
  2233 
  2232             y:= y + dY;
  2234             y:= y + dY;
  2233             dY:= dY + cGravityf;
  2235             dY:= dY + aiGravityf;
  2234             dec(t)
  2236             dec(t)
  2235         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 7)) or
  2237         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 7)) or
  2236                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 7))) or (t < -timeLimit);
  2238                ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 7))) or (t < -timeLimit);
  2237 
  2239 
  2238         EX:= trunc(x);
  2240         EX:= trunc(x);