AI: Rewrite TestMolotov
authorWuzzy <Wuzzy2@mail.ru>
Mon, 08 Jun 2020 21:53:45 +0200
changeset 15612 39a353e8ef3d
parent 15611 be8fe5e0789e
child 15613 d9c62f196fe0
AI: Rewrite TestMolotov The old function was broken, the AI just refused to use the molotov, ever
hedgewars/uAIAmmoTests.pas
--- a/hedgewars/uAIAmmoTests.pas	Mon Jun 08 21:13:31 2020 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Mon Jun 08 21:53:45 2020 +0200
@@ -561,61 +561,85 @@
 end;
 
 function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
-var Vx, Vy, r: real;
-    Score, EX, EY, valueResult: LongInt;
-    TestTime: LongInt;
-    targXWrap, x, y, dY, meX, meY: real;
+const timeLimit = 50;
+var Vx, Vy, r, meX, meY: real;
+    rTime: LongInt;
+    EX, EY: LongInt;
+    valueResult: LongInt;
+    targXWrap, x, y, dX, dY: real;
     t: LongInt;
+    value, range: LongInt;
 begin
 Flags:= Flags; // avoid compiler hint
 meX:= hwFloat2Float(Me^.X);
 meY:= hwFloat2Float(Me^.Y);
-valueResult:= BadTurn;
-TestTime:= 0;
+ap.Time:= 0;
+rTime:= 350;
 ap.ExplR:= 0;
 if (WorldEdge = weWrap) then
     if (Targ.Point.X < meX) then
          targXWrap:= Targ.Point.X + (RightX-LeftX)
     else targXWrap:= Targ.Point.X - (RightX-LeftX);
+valueResult:= BadTurn;
 repeat
-    inc(TestTime, 300);
+    rTime:= rTime + 300 + Level * 50 + random(300);
     if (WorldEdge = weWrap) and (random(2)=0) then
-         Vx:= (targXWrap - meX) / TestTime
-    else Vx:= (Targ.Point.X - meX) / TestTime;
-    Vy:= cGravityf * (TestTime div 2) - Targ.Point.Y - meY / TestTime;
+         Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime
+    else
+         Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime;
+    Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime;
     r:= sqr(Vx) + sqr(Vy);
+
     if not (r > 1) then
         begin
         x:= meX;
         y:= meY;
+        dX:= Vx;
         dY:= -Vy;
-        t:= TestTime;
+        t:= rTime;
         repeat
             x:= CheckWrap(x);
-            x:= x + Vx;
+            x:= x + dX;
+
             y:= y + dY;
             dY:= dY + cGravityf;
             dec(t)
-        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
-               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
+        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t < -timeLimit);
+
         EX:= trunc(x);
         EY:= trunc(y);
-        if t < 50 then
-            Score:= RateExplosion(Me, EX, EY, 97)  // average of 17 attempts, most good, but some failing spectacularly
-        else
-            Score:= BadTurn;
+
+        // Sanity check 1: Make sure we're not too close to impact location
+        range:= Metric(trunc(meX), trunc(meY), EX, EY);
+        if (range < 150) and (Level < 5) then
+            exit(BadTurn);
+
+        // Sanity check 2: If impact location is close, above us and wind blows
+        // towards us, there's a risk of fire flying towards us, so fail in this case.
+        if (Level < 3) and (range <= 600) and (trunc(meY) >= EX) and
+            (((ap.Angle < 0) and (windSpeed > 0)) or ((ap.Angle > 0) and (windSpeed < 0))) then
+            exit(BadTurn);
 
-        if valueResult < Score then
+        if t >= -timeLimit then
+            value:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly
+        else
+            value:= BadTurn;
+
+        if (value = 0) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then
+            value := BadTurn;
+
+        if (valueResult < value) or ((valueResult = value) and (Level < 3)) then
             begin
-            ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
-            ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
+            ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
+            ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
             ap.ExplR:= 100;
             ap.ExplX:= EX;
             ap.ExplY:= EY;
-            valueResult:= Score
+            valueResult:= value
             end;
         end
-until (TestTime > 5050 - Level * 800);
+until rTime > 5050 - Level * 800;
 TestMolotov:= valueResult
 end;