hedgewars/uAIAmmoTests.pas
changeset 6580 6155187bf599
parent 6474 42e9773eedfd
child 6700 e04da46ee43c
--- a/hedgewars/uAIAmmoTests.pas	Mon Jan 16 10:22:21 2012 +0100
+++ b/hedgewars/uAIAmmoTests.pas	Tue Jan 17 09:01:31 2012 -0500
@@ -24,11 +24,11 @@
 const amtest_OnTurn = $00000001;
 
 type TAttackParams = record
-            Time: Longword;
-            Angle, Power: LongInt;
-            ExplX, ExplY, ExplR: LongInt;
-            AttackPutX, AttackPutY: LongInt;
-            end;
+        Time: Longword;
+        Angle, Power: LongInt;
+        ExplX, ExplY, ExplR: LongInt;
+        AttackPutX, AttackPutY: LongInt;
+        end;
 
 function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -137,29 +137,31 @@
 ap.ExplR:= 0;
 valueResult:= BadTurn;
 repeat
-  rTime:= rTime + 300 + Level * 50 + random(300);
-  Vx:= - cWindSpeedf * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
-  Vy:= cGravityf * rTime * 0.5 - (Targ.Y - mY) / rTime;
-  r:= sqrt(sqr(Vx) + sqr(Vy));
-  if not (r > 1) then
-     begin
+    rTime:= rTime + 300 + Level * 50 + random(300);
+    Vx:= - cWindSpeedf * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
+    Vy:= cGravityf * rTime * 0.5 - (Targ.Y - mY) / rTime;
+    r:= sqrt(sqr(Vx) + sqr(Vy));
+    if not (r > 1) then
+        begin
         x:= mX;
         y:= mY;
         dX:= Vx;
         dY:= -Vy;
         t:= rTime;
         repeat
-              x:= x + dX;
-              y:= y + dY;
-              dX:= dX + cWindSpeedf;
-              dY:= dY + cGravityf;
-              dec(t)
+            x:= x + dX;
+            y:= y + dY;
+            dX:= dX + cWindSpeedf;
+            dY:= dY + cGravityf;
+            dec(t)
         until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t <= 0);
+        
         EX:= trunc(x);
         EY:= trunc(y);
         value:= RateExplosion(Me, EX, EY, 101);
-        if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
-     if valueResult <= value then
+        if value = 0 then
+            value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
+    if valueResult <= value then
         begin
         ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
         ap.Power:= trunc(r * cMaxPower) - random((Level - 1) * 17 + 1);
@@ -168,7 +170,7 @@
         ap.ExplY:= EY;
         valueResult:= value
         end;
-     end
+    end
 until (rTime > 4250);
 TestBazooka:= valueResult
 end;
@@ -188,28 +190,29 @@
 ap.ExplR:= 0;
 valueResult:= BadTurn;
 repeat
-  rTime:= rTime + 300 + Level * 50 + random(300);
-  Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime);
-  Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime);
-  r:= Distance(Vx, Vy);
-  if not (r > _1) then
-     begin
+    rTime:= rTime + 300 + Level * 50 + random(300);
+    Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime);
+    Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime);
+    r:= Distance(Vx, Vy);
+    if not (r > _1) then
+        begin
         x:= Me^.X;
         y:= Me^.Y;
         dX:= Vx;
         dY:= -Vy;
         t:= rTime;
         repeat
-          x:= x + dX;
-          y:= y + dY;
-          dX:= dX + cWindSpeed;
-          dY:= dY + cGravity;
-          dec(t)
+            x:= x + dX;
+            y:= y + dY;
+            dX:= dX + cWindSpeed;
+            dY:= dY + cGravity;
+            dec(t)
         until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t <= 0);
         EX:= hwRound(x);
         EY:= hwRound(y);
         value:= RateExplosion(Me, EX, EY, 5);
-        if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
+        if value = 0 then
+            value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
 
         if valueResult <= value then
             begin
@@ -236,26 +239,28 @@
 TestTime:= 0;
 ap.ExplR:= 0;
 repeat
-  inc(TestTime, 300);
-  Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
-  Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
-  r:= Distance(Vx, Vy);
-  if not (r > _1) then
-     begin
+    inc(TestTime, 300);
+    Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
+    Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
+    r:= Distance(Vx, Vy);
+    if not (r > _1) then
+        begin
         x:= Me^.X;
         y:= Me^.Y;
         dY:= -Vy;
         t:= TestTime;
         repeat
-          x:= x + Vx;
-          y:= y + dY;
-          dY:= dY + cGravity;
-          dec(t)
+            x:= x + Vx;
+            y:= y + dY;
+            dY:= dY + cGravity;
+            dec(t)
         until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 7) or (t = 0);
         EX:= hwRound(x);
         EY:= hwRound(y);
-        if t < 50 then Score:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
-                  else Score:= BadTurn;
+        if t < 50 then
+            Score:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
+        else
+            Score:= BadTurn;
                   
         if valueResult < Score then
             begin
@@ -267,7 +272,7 @@
             ap.ExplY:= EY;
             valueResult:= Score
             end;
-     end
+        end
 until (TestTime > 4250);
 TestMolotov:= valueResult
 end;
@@ -284,22 +289,22 @@
 TestTime:= 0;
 ap.ExplR:= 0;
 repeat
-  inc(TestTime, 1000);
-  Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
-  Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta);
-  r:= Distance(Vx, Vy);
-  if not (r > _1) then
-    begin
-    x:= Me^.X;
-    y:= Me^.Y;
-    dY:= -Vy;
-    t:= TestTime;
-    repeat
-        x:= x + Vx;
-        y:= y + dY;
-        dY:= dY + cGravity;
-        dec(t)
-    until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
+    inc(TestTime, 1000);
+    Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
+    Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta);
+    r:= Distance(Vx, Vy);
+    if not (r > _1) then
+        begin
+        x:= Me^.X;
+        y:= Me^.Y;
+        dY:= -Vy;
+        t:= TestTime;
+        repeat
+            x:= x + Vx;
+            y:= y + dY;
+            dY:= dY + cGravity;
+            dec(t)
+        until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0);
     EX:= hwRound(x);
     EY:= hwRound(y);
     if t < 50 then 
@@ -334,20 +339,20 @@
 TestTime:= 0;
 ap.ExplR:= 0;
 repeat
-  inc(TestTime, 1000);
-  // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
-  if Me^.X<int2hwFloat(Targ.X) then
-      Vx:= (int2hwFloat(Targ.X+10) - Me^.X) / int2hwFloat(TestTime + tDelta)
-  else
-      Vx:= (int2hwFloat(Targ.X-10) - Me^.X) / int2hwFloat(TestTime + tDelta);
-  Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-150) - Me^.Y) / int2hwFloat(TestTime + tDelta);
-  r:= Distance(Vx, Vy);
-  if not (r > _1) then
-     begin
-    x:= Me^.X;
-    y:= Me^.Y;
-    dY:= -Vy;
-    t:= TestTime;
+    inc(TestTime, 1000);
+    // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
+    if Me^.X<int2hwFloat(Targ.X) then
+        Vx:= (int2hwFloat(Targ.X+10) - Me^.X) / int2hwFloat(TestTime + tDelta)
+    else
+        Vx:= (int2hwFloat(Targ.X-10) - Me^.X) / int2hwFloat(TestTime + tDelta);
+    Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-150) - Me^.Y) / int2hwFloat(TestTime + tDelta);
+    r:= Distance(Vx, Vy);
+    if not (r > _1) then
+        begin
+        x:= Me^.X;
+        y:= Me^.Y;
+        dY:= -Vy;
+        t:= TestTime;
     repeat
         x:= x + Vx;
         y:= y + dY;
@@ -388,16 +393,16 @@
 TestTime:= 0;
 ap.ExplR:= 0;
 repeat
-  inc(TestTime, 1000);
-  Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
-  Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-200) - Me^.Y) / int2hwFloat(TestTime + tDelta);
-  r:= Distance(Vx, Vy);
-  if not (r > _1) then
-    begin
-    x:= Me^.X;
-    y:= Me^.Y;
-    dY:= -Vy;
-    t:= TestTime;
+    inc(TestTime, 1000);
+    Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta);
+    Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-200) - Me^.Y) / int2hwFloat(TestTime + tDelta);
+    r:= Distance(Vx, Vy);
+    if not (r > _1) then
+        begin
+        x:= Me^.X;
+        y:= Me^.Y;
+        dY:= -Vy;
+        t:= TestTime;
     repeat
         x:= x + Vx;
         y:= y + dY;
@@ -443,7 +448,9 @@
             else
                 T:= _0;
             Solve:= hwRound(T)
-            end else Solve:= 0
+            end
+            else
+                Solve:= 0
     end;
     
 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -456,11 +463,13 @@
 valueResult:= BadTurn;
 ap.ExplR:= 0;
 
-if (Level > 2) then exit(BadTurn);
+if (Level > 2) then
+    exit(BadTurn);
 
 TestTime:= Solve(Targ.X, Targ.Y, hwRound(Me^.X), hwRound(Me^.Y));
 
-if TestTime = 0 then exit(BadTurn);
+if TestTime = 0 then
+    exit(BadTurn);
 
     Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime);
     Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime);
@@ -485,7 +494,8 @@
                 Score:= - abs(Targ.Y - EY) div 32
             else
                 Score:= BadTurn
-        else if (Score < 0) then Score:= BadTurn
+        else if (Score < 0) then
+            Score:= BadTurn
         end
     else
         Score:= BadTurn;
@@ -505,8 +515,8 @@
 
 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 const
-  MIN_RANGE =  80;
-  MAX_RANGE = 400;
+    MIN_RANGE =  80;
+    MAX_RANGE = 400;
 var Vx, Vy, x, y: hwFloat;
     rx, ry, valueResult: LongInt;
     range: integer;
@@ -517,27 +527,28 @@
 x:= Me^.X;
 y:= Me^.Y;
 range:= Metric(hwRound(x), hwRound(y), Targ.X, Targ.Y);
-if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then exit(BadTurn);
+if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
+    exit(BadTurn);
 Vx:= (int2hwFloat(Targ.X) - x) * _1div1024;
 Vy:= (int2hwFloat(Targ.Y) - y) * _1div1024;
 ap.Angle:= DxDy2AttackAngle(Vx, -Vy);
 repeat
-  x:= x + vX;
-  y:= y + vY;
-  rx:= hwRound(x);
-  ry:= hwRound(y);
-  if TestCollExcludingMe(Me, rx, ry, 2) then
-     begin
-     x:= x + vX * 8;
-     y:= y + vY * 8;
-     valueResult:= RateShotgun(Me, rx, ry);
+    x:= x + vX;
+    y:= y + vY;
+    rx:= hwRound(x);
+    ry:= hwRound(y);
+    if TestCollExcludingMe(Me, rx, ry, 2) then
+        begin
+        x:= x + vX * 8;
+        y:= y + vY * 8;
+        valueResult:= RateShotgun(Me, rx, ry);
      
-     if valueResult = 0 then 
+    if valueResult = 0 then 
         valueResult:= - Metric(Targ.X, Targ.Y, rx, ry) div 64
-        else 
+    else 
         dec(valueResult, Level * 4000);
-     exit(valueResult * 27 div 20) // 27/20 is reuse bonus
-     end
+    exit(valueResult * 27 div 20) // 27/20 is reuse bonus
+    end
 until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4)
     or (x.isNegative)
     or (y.isNegative)
@@ -567,10 +578,11 @@
 d:= 0;
 
 repeat
-  x:= x + vX;
-  y:= y + vY;
-  if ((hwRound(x) and LAND_WIDTH_MASK) = 0)and((hwRound(y) and LAND_HEIGHT_MASK) = 0)
-     and (Land[hwRound(y), hwRound(x)] <> 0) then inc(d);
+    x:= x + vX;
+    y:= y + vY;
+    if ((hwRound(x) and LAND_WIDTH_MASK) = 0)and((hwRound(y) and LAND_HEIGHT_MASK) = 0)
+    and (Land[hwRound(y), hwRound(x)] <> 0) then
+        inc(d);
 until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4)
     or (x.isNegative)
     or (y.isNegative)
@@ -578,8 +590,10 @@
     or (y.Round > LongWord(LAND_HEIGHT))
     or (d > 200);
 
-if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then valueResult:= Max(0, (4 - d div 50) * 7 * 1024)
-                                                           else valueResult:= BadTurn;
+if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then
+    valueResult:= Max(0, (4 - d div 50) * 7 * 1024)
+else
+    valueResult:= BadTurn;
 TestDesertEagle:= valueResult
 end;
 
@@ -590,16 +604,21 @@
 Level:= Level; // avoid compiler hint
 ap.ExplR:= 0;
 if (Level > 2) or (Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 25) then
-   exit(BadTurn);
+    exit(BadTurn);
 
 ap.Time:= 0;
 ap.Power:= 1;
 x:= Me^.X;
 y:= Me^.Y;
-if (Targ.X) - hwRound(x) >= 0 then ap.Angle:=   cMaxAngle div 4
-                              else ap.Angle:= - cMaxAngle div 4;
+if (Targ.X) - hwRound(x) >= 0 then
+    ap.Angle:=   cMaxAngle div 4
+else
+    ap.Angle:= - cMaxAngle div 4;
 valueResult:= RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), hwRound(y), 15, 30);
-if valueResult <= 0 then valueResult:= BadTurn else inc(valueResult);
+if valueResult <= 0 then
+    valueResult:= BadTurn
+else
+    inc(valueResult);
 TestBaseballBat:= valueResult;
 end;
 
@@ -648,9 +667,10 @@
          
 if (Abs(hwRound(Me^.X) + hwSign(Me^.dX) * 10 - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 20) then
     rate:= 0
-    else
+else
     rate:= RateHammer(Me);
-if rate = 0 then rate:= BadTurn;
+if rate = 0 then
+    rate:= BadTurn;
 TestHammer:= rate;
 end;
 
@@ -664,7 +684,8 @@
 begin
 ap.ExplR:= 0;
 ap.Time:= 0;
-if (Level > 3) then exit(BadTurn);
+if (Level > 3) then
+    exit(BadTurn);
 
 ap.AttackPutX:= Targ.X;
 ap.AttackPutY:= Targ.Y;
@@ -682,22 +703,22 @@
 valueResult:= 0;
 
 repeat
-  X:= X + cBombsSpeed;
-  Y:= Y + dY;
-  dY:= dY + cGravity;
-  fexit:= true;
+    X:= X + cBombsSpeed;
+    Y:= Y + dY;
+    dY:= dY + cGravity;
+    fexit:= true;
 
-  for i:= 0 to 9 do
-    if b[i] then
-       begin
-       fexit:= false;
-       if TestColl(hwRound(X) + i * 30, hwRound(Y), 4) then
-          begin
-          b[i]:= false;
-          dmg[i]:= RateExplosion(Me, hwRound(X) + i * 30, hwRound(Y), 58)
-          // 58 (instead of 60) for better prediction (hh moves after explosion of one of the rockets)
-          end
-       end;
+    for i:= 0 to 9 do
+        if b[i] then
+            begin
+            fexit:= false;
+            if TestColl(hwRound(X) + i * 30, hwRound(Y), 4) then
+                begin
+                b[i]:= false;
+                dmg[i]:= RateExplosion(Me, hwRound(X) + i * 30, hwRound(Y), 58)
+                // 58 (instead of 60) for better prediction (hh moves after explosion of one of the rockets)
+                end
+            end;
 until fexit or (Y.Round > cWaterLine);
 
 for i:= 0 to 5 do inc(valueResult, dmg[i]);
@@ -709,13 +730,14 @@
     dec(t, dmg[i]);
     inc(t, dmg[i + 6]);
     if t > valueResult then
-       begin
-       valueResult:= t;
-       ap.AttackPutX:= Targ.X - 30 - cShift + i * 30
-       end
+        begin
+        valueResult:= t;
+        ap.AttackPutX:= Targ.X - 30 - cShift + i * 30
+        end
     end;
 
-if valueResult <= 0 then valueResult:= BadTurn;
+if valueResult <= 0 then
+    valueResult:= BadTurn;
 TestAirAttack:= valueResult;
 end;
 
@@ -728,30 +750,38 @@
     TestTeleport := BadTurn;
     Level:= Level; // avoid compiler hint
     FillBonuses(true, [gtCase]);
-    if bonuses.Count = 0 then begin
-        if Me^.Health <= 100  then begin
+    if bonuses.Count = 0 then
+        begin
+        if Me^.Health <= 100  then
+            begin
             maxTop := Targ.Y - cHHRadius * 2;
+            
             while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
-            dec(maxTop, cHHRadius*2);
-            if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then begin
+                dec(maxTop, cHHRadius*2);
+            if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then
+                begin
                 ap.AttackPutX := Targ.X;
                 ap.AttackPutY := maxTop + cHHRadius;
                 TestTeleport := Targ.Y - maxTop;
+                end;
             end;
-        end;
-    end
-    else begin
+        end
+    else
+        begin
         failNum := 0;
         repeat
             i := random(bonuses.Count);
             inc(failNum);
-        until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius) or (failNum = bonuses.Count*2);
-        if failNum < bonuses.Count*2 then begin
+        until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius)
+        or (failNum = bonuses.Count*2);
+        
+        if failNum < bonuses.Count*2 then
+            begin
             ap.AttackPutX := bonuses.ar[i].X;
             ap.AttackPutY := bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius;
             TestTeleport := 0;
+            end;
         end;
-    end;
 end;
 
 end.