Teach AI how to use resurrector
authorWuzzy <Wuzzy2@mail.ru>
Mon, 06 Jul 2020 01:46:22 +0200
changeset 15685 78e383fff605
parent 15684 c7fe94d56d6e
child 15686 034955e721a1
Teach AI how to use resurrector
ChangeLog.txt
hedgewars/uAIAmmoTests.pas
hedgewars/uAIMisc.pas
--- a/ChangeLog.txt	Mon Jul 06 00:25:13 2020 +0200
+++ b/ChangeLog.txt	Mon Jul 06 01:46:22 2020 +0200
@@ -6,7 +6,7 @@
  + Easier to push hogs around with blowtorch
  + Backjumps are now a bit easier
  + Teach computer players how to ...
- +   - use drill strike, piano strike, air mine, cleaver, seduction, laser sight
+ +   - use drill strike, piano strike, air mine, cleaver, seduction, resurrector, laser sight
  +   - use mine strike (0 seconds only)
  +   - use RC plane (very basic)
  +   - drop mines from a cliff
--- a/hedgewars/uAIAmmoTests.pas	Mon Jul 06 00:25:13 2020 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Mon Jul 06 01:46:22 2020 +0200
@@ -64,6 +64,7 @@
 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;
 function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
+function TestResurrector(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestSeduction(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 function TestDynamite(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
@@ -130,7 +131,7 @@
             (proc: nil;              flags: 0), // amFlamethrower
             (proc: @TestSMine;       flags: 0), // amSMine
             (proc: @TestHammer;      flags: amtest_NoTarget or amtest_NoInvulnerable), // amHammer
-            (proc: nil;              flags: 0), // amResurrector
+            (proc: @TestResurrector; flags: amtest_NoTarget or amtest_NoInvulnerable or amtest_NoVampiric), // amResurrector
             (proc: @TestDrillStrike; flags: amtest_Rare), // amDrillStrike
             (proc: nil;              flags: 0), // amSnowball
             (proc: nil;              flags: 0), // amTardis
@@ -1487,6 +1488,40 @@
 TestAirAttack:= valueResult;
 end;
 
+function TestResurrector(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
+var rate, heal: LongInt;
+begin
+Flags:= Flags; // avoid compiler hint
+Targ:= Targ;
+
+if (Level = 5) then
+    exit(BadTurn);
+
+if (Me^.Health <= 1) then
+    exit(BadTurn);
+
+if (Level <= 2) and (Me^.Hedgehog^.Effects[hePoisoned] > 0) then
+    // Sacrifice almost all health if poisoned
+    heal:= Me^.Health - 1
+else
+    // Sacrifice up to 10% of own health
+    heal:= (Me^.Health div 10);
+
+ap.ExplR:= 0;
+ap.Time:= 0;
+if (GameFlags and gfInfAttack) = 0 then
+    ap.Power:= max(min(500 * heal - 500, 10000), 10)
+else
+    // Shorter attack duration in inf attack because the clock is ticking!
+    ap.Power:= max(min(500 * heal - 500, 3000), 10);
+ap.Angle:= 0;
+
+rate:= RateResurrector(Me);
+if rate <= 0 then
+    rate:= BadTurn;
+TestResurrector:= rate;
+end;
+
 function TestDrillStrike(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt;
 const cShift = 4;
       Density : real = 1.0;
--- a/hedgewars/uAIMisc.pas	Mon Jul 06 00:25:13 2020 +0200
+++ b/hedgewars/uAIMisc.pas	Mon Jul 06 01:46:22 2020 +0200
@@ -88,6 +88,7 @@
 function  RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
 function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
 function  RateSeduction(Me: PGear): LongInt;
+function  RateResurrector(Me: PGear): LongInt;
 function  RateHammer(Me: PGear): LongInt;
 
 function  HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
@@ -102,6 +103,7 @@
     walkbonuses: Twalkbonuses;
 
 const KillScore = 200;
+      ResurrectScore = 100;
 var friendlyfactor: LongInt = 300;
 var dmgMod: real = 1.0;
 
@@ -137,6 +139,8 @@
             (Gear <> ThinkingHH) and
             (Gear^.Health > Gear^.Damage) and
             (not Gear^.Hedgehog^.Team^.hasgone)) or
+        ((Gear^.Kind = gtGrave) and
+            (Gear^.Health = 0)) or
         ((Gear^.Kind = gtExplosives) and
             (Gear^.Health > Gear^.Damage)) or
         ((Gear^.Kind = gtMine) and
@@ -170,6 +174,17 @@
                     inc(e)
                     end;
                 end
+            else if Gear^.Kind = gtGrave then
+                if (Gear^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then
+                    begin
+                    Score:= ResurrectScore;
+                    inc(f);
+                    end
+                else
+                    begin
+                    Score:= -ResurrectScore;
+                    inc(e);
+                    end
             else if Gear^.Kind = gtExplosives then
                 Score:= Gear^.Health - Gear^.Damage
             else if Gear^.Kind = gtMine then
@@ -923,6 +938,45 @@
     RateSeduction:= rate * 1024;
 end;
 
+function RateResurrector(Me: PGear): LongInt;
+var i, r, rate, pX, pY: LongInt;
+    meX, meY: hwFloat;
+    hadSkips: boolean;
+begin
+meX:= Me^.X;
+meY:= Me^.Y;
+rate:= 0;
+for i:= 0 to Targets.Count do
+    if (Targets.ar[i].Kind = gtGrave) and (not Targets.ar[i].dead) then
+        with Targets.ar[i] do
+            begin
+            pX:= Point.X;
+            pY:= Point.Y;
+
+            if (not matters) then
+                hadSkips:= true
+            else if matters and (abs(pX - hwRound(meX)) + abs(pY - hwRound(meY)) < cResurrectorDist) then
+                begin
+                r:= trunc(sqrt(sqr(abs(pX - hwRound(meX)))+sqr(abs(pY - hwRound(meY)))));
+                if r < cResurrectorDist then
+                    begin
+                    if Score > 0 then
+                        inc(rate, Score * 1024)
+                    else
+                        inc(rate, Score * friendlyFactor div 100 * 1024);
+                    // a "dead" grave is a grave that we have resurrected
+                    dead:= true;
+                    Targets.reset:= true;
+                    end;
+                end;
+            end;
+
+if hadSkips and (rate <= 0) then
+    RateResurrector:= BadTurn
+else
+    RateResurrector:= rate * 1024;
+end;
+
 function RateHammer(Me: PGear): LongInt;
 var x, y, i, r, rate: LongInt;
     hadSkips: boolean;