AI: Add new sine gun test (still WIP)
authorWuzzy <Wuzzy2@mail.ru>
Sun, 19 Jul 2020 22:08:55 +0200
changeset 15730 680dc787408c
parent 15729 34138bf36c5c
child 15731 26247a74d823
AI: Add new sine gun test (still WIP)
hedgewars/uAIAmmoTests.pas
--- a/hedgewars/uAIAmmoTests.pas	Sun Jul 19 11:32:30 2020 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Sun Jul 19 22:08:55 2020 +0200
@@ -63,6 +63,7 @@
 function TestAirAttack(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestDrillStrike(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestMineStrike(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
+function TestSineGun(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestSMine(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestPiano(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
@@ -130,7 +131,7 @@
             (proc: nil;              flags: 0), // amPortalGun
             (proc: @TestPiano;       flags: amtest_Rare or amtest_NoInvulnerable or amtest_NoVampiric), // amPiano
             (proc: @TestGrenade;     flags: amtest_NoTrackFall), // amGasBomb
-            (proc: @TestShotgun;     flags: 0), // amSineGun
+            (proc: @TestSineGun;     flags: amtest_NoVampiric), // amSineGun
             (proc: nil;              flags: 0), // amFlamethrower
             (proc: @TestSMine;       flags: 0), // amSMine
             (proc: @TestHammer;      flags: amtest_NoTarget or amtest_NoInvulnerable), // amHammer
@@ -1806,6 +1807,77 @@
 TestMineStrike:= valueResult;
 end;
 
+function TestSineGun(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
+const
+    MIN_RANGE =  40;
+    MAX_RANGE = 400;
+var Vx, Vy, x, y: real;
+    rx, ry, value, valueResult: LongInt;
+    range: integer;
+    landStop: boolean;
+begin
+// TODO: Also simulate the sine gun's kickback and make sure the attacker
+// doesn't get hurt
+
+Flags:= Flags; // avoid compiler hint
+TestSineGun:= BadTurn;
+valueResult:= 0;
+ap.ExplR:= 0;
+ap.Time:= 0;
+ap.Power:= 1;
+x:= hwFloat2Float(Me^.X);
+y:= hwFloat2Float(Me^.Y);
+range:= Metric(trunc(x), trunc(y), Targ.Point.X, Targ.Point.Y);
+// Range limits
+if (range < MIN_RANGE) or ((range > MAX_RANGE) and (Level >= 4)) then
+    exit(BadTurn);
+
+Vx:= (Targ.Point.X - x) * 1 / 1024;
+Vy:= (Targ.Point.Y - y) * 1 / 1024;
+
+// Never shoot downwards or horizontal because it's dangerous
+// and we don't have a proper check for kickback yet
+if Vy >= 0 then
+    exit(BadTurn);
+
+landStop:= false;
+ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
+// Apply inaccuracy
+if (not aiLaserSighting) then
+    inc(ap.Angle, AIrndSign(random((Level - 1) * 10)));
+repeat
+    x:= x + vX;
+    y:= y + vY;
+    rx:= trunc(x);
+    ry:= trunc(y);
+    if (GameFlags and gfSolidLand) <> 0 then
+        // Stop projectile when colliding with indestructible land
+        landStop:= (Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 5);
+
+    if landStop or
+       ((Me = CurrentHedgehog^.Gear) and TestCollHogsOrObjects(rx, ry, 5)) or
+       ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 5)) then
+    begin
+        x:= x + vX * 8;
+        y:= y + vY * 8;
+        value:= RateShove(Me, rx, ry, 5, 35, 50, vX, vY, afTrackFall);
+
+        if (value > 0) then
+            inc(valueResult, value);
+    end
+until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5)
+    or (landStop)
+    or (Metric(trunc(x), trunc(y), hwRound(Me^.X), hwRound(Me^.Y)) > MAX_RANGE)
+    or (x < 0)
+    or (y < 0)
+    or (trunc(x) > LAND_WIDTH)
+    or (trunc(y) > LAND_HEIGHT);
+
+if valueResult <= 0 then
+    valueResult:= BadTurn;
+TestSineGun:= valueResult;
+end;
+
 function TestSMine(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 const timeLimit = 50;
       Density : real = 1.6;