Start on adding drowning bonus to bat/firepunch/whip. AI still is not smart enough to change direction when firepunching to face the water, or change the angle of the bat.
authornemo
Sun, 11 Mar 2012 20:12:31 -0400
changeset 6770 7d2c6cdb816a
parent 6769 44ad49a3a126
child 6771 87a947097d00
Start on adding drowning bonus to bat/firepunch/whip. AI still is not smart enough to change direction when firepunching to face the water, or change the angle of the bat. Also try to weight cost of switches based on how many switches were available.
hedgewars/uAI.pas
hedgewars/uAIAmmoTests.pas
hedgewars/uAIMisc.pas
hedgewars/uAmmos.pas
--- a/hedgewars/uAI.pas	Sun Mar 11 18:28:32 2012 -0400
+++ b/hedgewars/uAI.pas	Sun Mar 11 20:12:31 2012 -0400
@@ -199,7 +199,7 @@
 Stack.Count:= 0;
 
 for a:= Low(TAmmoType) to High(TAmmoType) do
-    CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(Me^.Hedgehog^, a);
+    CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and (HHHasAmmo(Me^.Hedgehog^, a) > 0);
 
 BotLevel:= Me^.Hedgehog^.BotLevel;
 
@@ -291,8 +291,8 @@
 
 function Think(Me: Pointer): ptrint;
 var BackMe, WalkMe: TGear;
-    StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword;
-    switchImmediatelyAvailable, switchAvailable: boolean;
+    StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i, switchCount: Longword;
+    switchImmediatelyAvailable: boolean;
     Actions: TActions;
 begin
 InterlockedIncrement(hasThread);
@@ -302,7 +302,7 @@
 switchesNum:= 0;
 
 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher);
-switchAvailable:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch);
+switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch);
 
 if (PGear(Me)^.State and gstAttacked) = 0 then
     if Targets.Count > 0 then
@@ -316,10 +316,10 @@
             Actions.Score:= 0;
             if switchesNum > 0 then
                 begin
-                if not switchImmediatelyAvailable then
+                if not switchImmediatelyAvailable  then
                     begin
-                    // when AI has to use switcher, make it cost smth
-                    Actions.Score:= -20000;
+                    // when AI has to use switcher, make it cost smth unless they have a lot of switches
+                    if (SwitchCount < 10) then Actions.Score:= (-27+SwitchCount*3)*4000;
                     AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);                    
                     AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0);
                     AddAction(Actions, aia_attack, aim_release, 1, 0, 0);
@@ -336,7 +336,7 @@
 
 
             inc(switchesNum);
-        until (not (switchImmediatelyAvailable or switchAvailable))
+        until (not (switchImmediatelyAvailable or (switchCount > 0)))
             or StopThinking 
             or (itHedgehog = currHedgehogIndex)
             or BestActions.isWalkingToABetterPlace;
--- a/hedgewars/uAIAmmoTests.pas	Sun Mar 11 18:28:32 2012 -0400
+++ b/hedgewars/uAIAmmoTests.pas	Sun Mar 11 20:12:31 2012 -0400
@@ -41,6 +41,7 @@
 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -66,7 +67,7 @@
             (proc: @TestDesertEagle; flags: 0), // amDEagle
             (proc: nil;              flags: 0), // amDynamite
             (proc: @TestFirePunch;   flags: 0), // amFirePunch
-            (proc: @TestFirePunch;   flags: 0), // amWhip
+            (proc: @TestWhip;        flags: 0), // amWhip
             (proc: @TestBaseballBat; flags: 0), // amBaseballBat
             (proc: nil;              flags: 0), // amParachute
             (proc: @TestAirAttack;   flags: amtest_OnTurn), // amAirAttack
@@ -618,7 +619,8 @@
     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);
+
+valueResult:= RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x), hwRound(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, 1);
 if valueResult <= 0 then
     valueResult:= BadTurn
 else
@@ -641,7 +643,7 @@
 or (Abs(hwRound(y) - 50 - Targ.Y) > 50) then
     begin
     if TestColl(hwRound(x), hwRound(y) - 16, 6)
-    and (RateShove(Me, hwRound(x) + 10 * hwSign(Me^.dX), hwRound(y) - 40, 30, 30) = 0) then
+    and (RateShove(Me, hwRound(x) + 10 * hwSign(Me^.dX), hwRound(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9,  1) = 0) then
         valueResult:= Succ(BadTurn)
     else
         valueResult:= BadTurn;
@@ -651,7 +653,7 @@
 valueResult:= 0;
 for i:= 0 to 4 do
     valueResult:= valueResult + RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x),
-                                    hwRound(y) - 20 * i - 5, 10, 30);
+                                    hwRound(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX)*0.45, -0.9, 1);
 if valueResult <= 0 then
     valueResult:= BadTurn
 else
@@ -660,6 +662,40 @@
 TestFirePunch:= valueResult;
 end;
 
+function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+var i, valueResult: LongInt;
+    x, y: hwFloat;
+begin
+Level:= Level; // avoid compiler hint
+ap.ExplR:= 0;
+ap.Time:= 0;
+ap.Power:= 1;
+ap.Angle:= 0;
+x:= Me^.X;
+y:= Me^.Y;
+if (Abs(hwRound(x) - Targ.X) > 25)
+or (Abs(hwRound(y) - 50 - Targ.Y) > 50) then
+    begin
+    if TestColl(hwRound(x), hwRound(y) - 16, 6)
+    and (RateShove(Me, hwRound(x) + 10 * hwSign(Me^.dX), hwRound(y) - 40, 30, 30, 40, hwSign(Me^.dX), -0.8,  1) = 0) then
+        valueResult:= Succ(BadTurn)
+    else
+        valueResult:= BadTurn;
+    exit(valueResult)
+    end;
+
+valueResult:= 0;
+for i:= 0 to 4 do
+    valueResult:= valueResult + RateShove(Me, hwRound(x) + 10 * hwSign(int2hwFloat(Targ.X) - x),
+                                    hwRound(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX), -0.8, 1);
+if valueResult <= 0 then
+    valueResult:= BadTurn
+else
+    inc(valueResult);
+
+TestWhip:= valueResult;
+end;
+
 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 var rate: LongInt;
 begin
--- a/hedgewars/uAIMisc.pas	Sun Mar 11 18:28:32 2012 -0400
+++ b/hedgewars/uAIMisc.pas	Sun Mar 11 20:12:31 2012 -0400
@@ -54,7 +54,7 @@
 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
 function TestColl(x, y, r: LongInt): boolean; inline;
 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
-function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt;
+function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
 function RateShotgun(Me: PGear; x, y: LongInt): LongInt;
 function RateHammer(Me: PGear): LongInt;
 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
@@ -267,11 +267,25 @@
         y:= y + dY;
         dY:= dY + cGravityf;
         skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner));
+        // consider adding dX/dY calc here for fall damage
         if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then exit(false);
         if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(true);
         end;
 end;
 
+function TraceShoveDrown(Me: PGear; x, y, dX, dY: Real): boolean;
+begin
+    while true do
+        begin
+        x:= x + dX;
+        y:= y + dY;
+        dY:= dY + cGravityf;
+        // consider adding dX/dY calc here for fall damage
+        if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then exit(false);
+        if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(true);
+        end;
+end;
+
 // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
 function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
 var i, dmg, dmgBase, rate, erasure: LongInt;
@@ -305,9 +319,7 @@
                 end;
             if (Flags and 1 <> 0) and TraceDrown(x, y, Point.x, Point.y, dX, dY, erasure) then
                 if Score > 0 then
-                    begin
                     inc(rate, KillScore)
-                    end
                 else
                     dec(rate, KillScore * friendlyfactor div 100)
             else if dmg >= abs(Score) then
@@ -325,19 +337,32 @@
 RateExplosion:= rate * 1024;
 end;
 
-function RateShove(Me: PGear; x, y, r, power: LongInt): LongInt;
+function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
 var i, dmg, rate: LongInt;
+    dX, dY: real;
 begin
 Me:= Me; // avoid compiler hint
 rate:= 0;
 for i:= 0 to Pred(Targets.Count) do
     with Targets.ar[i] do
         begin
-        dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y));
+        dmg:= 0;
+        if abs(Point.x - x) + abs(Point.y - y) < r then
+            dmg:= r - hwRound(DistanceI(Point.x - x, Point.y - y));
         dmg:= hwRound(_0_01 * cDamageModifier * dmg * cDamagePercent);
         if dmg > 0 then
             begin
-            if power >= abs(Score) then
+            if Flags and 1 <> 0 then
+                begin
+                dX:= gdX * 0.005 * kick;
+                dY:= gdY * 0.005 * kick;
+                end;
+            if (Flags and 1 <> 0) and TraceShoveDrown(Me, Point.x, Point.y, dX, dY) then
+                if Score > 0 then
+                    inc(rate, KillScore)
+                else
+                    dec(rate, KillScore * friendlyfactor div 100)
+            else if power >= abs(Score) then
                 if Score > 0 then
                     inc(rate, KillScore)
                 else
--- a/hedgewars/uAmmos.pas	Sun Mar 11 18:28:32 2012 -0400
+++ b/hedgewars/uAmmos.pas	Sun Mar 11 20:12:31 2012 -0400
@@ -33,7 +33,7 @@
 procedure AssignStores;
 procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType);
 procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
-function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): boolean;
+function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): LongWord;
 procedure PackAmmo(Ammo: PHHAmmo; Slot: LongInt);
 procedure OnUsedAmmo(var Hedgehog: THedgehog);
 procedure ApplyAngleBounds(var Hedgehog: THedgehog; AmmoType: TAmmoType);
@@ -277,7 +277,7 @@
     end;
 end;
 
-function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): boolean;
+function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): LongWord;
 var slot, ami: LongInt;
 begin
 Slot:= Ammoz[Ammo].Slot;
@@ -286,10 +286,12 @@
         begin
         with Hedgehog.Ammo^[Slot, ami] do
             if (AmmoType = Ammo) then
-                exit((Count > 0) and (Hedgehog.Team^.Clan^.TurnNumber > Ammoz[AmmoType].SkipTurns));
+                if Hedgehog.Team^.Clan^.TurnNumber > Ammoz[AmmoType].SkipTurns then
+                    exit(Count)
+                else exit(0);
       inc(ami)
       end;
-HHHasAmmo:= false
+HHHasAmmo:= 0
 end;
 
 procedure ApplyAngleBounds(var Hedgehog: THedgehog; AmmoType: TAmmoType);