hedgewars/uAIMisc.pas
changeset 8962 9780e79619ed
parent 8961 b157302674cf
child 8963 1a8335f0d968
--- a/hedgewars/uAIMisc.pas	Sat May 04 21:58:42 2013 -0400
+++ b/hedgewars/uAIMisc.pas	Sun May 05 22:50:17 2013 -0400
@@ -30,9 +30,10 @@
 
       BadTurn = Low(LongInt) div 4;
 
-type TTarget = record
+type TTarget = record // starting to look more and more like a gear
     Point: TPoint;
-    Score: LongInt;
+    Score, Radius: LongInt;
+    Flags: LongWord;
     Density: real;
     skip, matters, dead: boolean;
     Kind: TGearType;
@@ -123,7 +124,7 @@
 Gear:= GearsList;
 while Gear <> nil do
     begin
-    if  ((Gear^.Kind = gtHedgehog) and
+    if  (((Gear^.Kind = gtHedgehog) and
             (Gear <> ThinkingHH) and
             (Gear^.Health > Gear^.Damage) and
             not(Gear^.Hedgehog^.Team^.hasgone)) or
@@ -135,7 +136,7 @@
             ((Gear^.Health > 0) and 
              (cMineDudPercent > 95) and
              (cMinesTime < 3000)) 
-             ) and
+             ))  and 
         (Targets.Count < 256) then
         begin
         with Targets.ar[Targets.Count] do
@@ -143,6 +144,8 @@
             skip:= false;
             dead:= false;
             Kind:= Gear^.Kind;
+            Radius:= Gear^.Radius;
+            Flags:= Gear^.State;
             matters:= (Gear^.AIHints and aihDoesntMatter) = 0;
 
             Point.X:= hwRound(Gear^.X);
@@ -366,21 +369,17 @@
 
 
 
-function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Kind: TGearType): LongInt;
+function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Target: TTarget): LongInt;
 var skipLandCheck: boolean;
-    rCorner, dxdy: real;
-    dmg, radius: LongInt;
+    rCorner, dxdy, odX, odY: real;
+    dmg: LongInt;
 begin
+    odX:= dX;
+    odY:= dY;
     skipLandCheck:= true;
     if x - eX < 0 then dX:= -dX;
     if y - eY < 0 then dY:= -dY;
     // ok. attempt approximate search for an unbroken trajectory into water.  if it continues far enough, assume out of map
-    if Kind = gtHedgehog then 
-        radius:= cHHRadius
-    else if Kind = gtExplosives then
-        radius:= 16
-    else if Kind = gtMine then
-        radius:= 2;
     rCorner:= r * 0.75;
     while true do
         begin
@@ -388,41 +387,46 @@
         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));
-        if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), radius) then
-            begin
-            if (Kind = gtHedgehog) and (0.4 < dY) then
-                begin
-                dmg := 1 + trunc((abs(dY) - 0.4) * 70);
-                if dmg >= 1 then exit(dmg)
-                end
-            else 
+        if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then
+            with Target do
                 begin
-                dxdy:= abs(dX)+abs(dY);
-// so we don't know at present if a barrel is already rolling.  Would need to add that to target info I guess
-// a barrel oriented vertically only considers dY. however, AI doesn't know to use hammer, and could only bat vertically w/ bat, so probably shouldn't matter
-                if (dxdy > 0.3) then
+                if (Kind = gtHedgehog) and (0.4 < dY) then
+                    begin
+                    dmg := 1 + trunc((abs(dY) - 0.4) * 70);
+                    if dmg >= 1 then exit(dmg)
+                    end
+                else 
                     begin
-                    dmg := 1 + trunc(dxdy * 25);
-                    exit(dmg)
-                    end
-                end;
+                    dxdy:= abs(dX)+abs(dY);
+                    if ((Kind = gtMine) and (dxdy > 0.35)) or 
+                       ((Kind = gtExplosives) and 
+                            (((Flags and gstTmpFlag <> 0) and (dxdy > 0.35)) or
+                             ((Flags and gstTmpFlag <> 0) and 
+                                ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and 
+                                (abs(odX) > 0.02))) and (dxdy > 0.35)))) then
+                        begin
+                        dmg := 1 + trunc(dxdy * 25);
+                        exit(dmg)
+                        end
+                    else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then
+                        begin
+                        dmg := 1 + trunc(dy * 70);
+                        exit(dmg)
+                        end
+                    end;
             exit(0)
             end;
         if (y > cWaterLine) or (x > leftX) or (x < rightX) then exit(-1)
         end
 end;
 
-function TraceShoveFall(var x, y: Real; dX, dY: Real; Kind: TGearType): LongInt;
-var dmg, radius: LongInt;
-    dxdy: real;
+function TraceShoveFall(var x, y: Real; dX, dY: Real; Target: TTarget): LongInt;
+var dmg: LongInt;
+    dxdy, odX, odY: real;
 begin
+    odX:= dX;
+    odY:= dY;
 //v:= random($FFFFFFFF);
-    if Kind = gtHedgehog then 
-        radius:= cHHRadius
-    else if Kind = gtExplosives then
-        radius:= 16
-    else if Kind = gtMine then
-        radius:= 2;
     while true do
         begin
         x:= x + dX;
@@ -435,27 +439,34 @@
             UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true);
             end;}
 
-
-        // consider adding dX/dY calc here for fall damage
-        if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then
-            begin
-            if (Kind = gtHedgehog) and (0.4 < dY) then
+        if TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then
+            with Target do
                 begin
-                dmg := 1 + trunc((abs(dY) - 0.4) * 70);
-                if dmg >= 1 then
-                    exit(dmg);
-                end
-            else 
-                begin
-                dxdy:= abs(dX)+abs(dY);
-// so we don't know at present if a barrel is already rolling.  Would need to add that to target info I guess
-// a barrel oriented vertically only considers dY. however, AI doesn't know to use hammer, and could only bat vertically w/ bat, so probably shouldn't matter
-                if (dxdy > 0.3) then
+                if (Kind = gtHedgehog) and (0.4 < dY) then
+                    begin
+                    dmg := 1 + trunc((abs(dY) - 0.4) * 70);
+                    if dmg >= 1 then
+                        exit(dmg);
+                    end
+                else 
                     begin
-                    dmg := 1 + trunc(dxdy * 25);
-                    exit(dmg)
-                    end
-                end;
+                    dxdy:= abs(dX)+abs(dY);
+                    if ((Kind = gtMine) and (dxdy > 0.35)) or 
+                       ((Kind = gtExplosives) and 
+                            (((Flags and gstTmpFlag <> 0) and (dxdy > 0.35)) or
+                             ((Flags and gstTmpFlag <> 0) and 
+                                ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and 
+                                (abs(odX) > 0.02))) and (dxdy > 0.35)))) then
+                        begin
+                        dmg := 1 + trunc(dxdy * 25);
+                        exit(dmg)
+                        end
+                    else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then
+                        begin
+                        dmg := 1 + trunc(dy * 70);
+                        exit(dmg)
+                        end
+                    end;
             exit(0)
         end;
         if (y > cWaterLine) or (x > leftX) or (x < rightX) then
@@ -515,6 +526,7 @@
                 begin
                 pX:= Point.x;
                 pY:= Point.y;
+                fallDmg:= 0;
                 if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then
                     begin
                     dX:= (0.005 * dmg + 0.01) / Density;
@@ -525,8 +537,8 @@
                         dX:= 0;
                     if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
                        (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
-                         fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Kind) * dmgMod)
-                    else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Kind) * dmgMod)
+                         fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
+                    else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
                     end;
                 if Kind = gtHedgehog then
                     begin
@@ -557,8 +569,7 @@
                         else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024)
                         end
                     end
-// FIXME - need to make TraceFall calculate damage for barrels/mines correctly
-                else if (Kind <> gtHedgehog) and (FallDmg >= 0) and ((dmg+fallDmg) >= Score) then
+                else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
                     begin
                     dead:= true;
                     Targets.reset:= true;
@@ -598,9 +609,10 @@
             begin
             pX:= Point.x;
             pY:= Point.y-2;
+            fallDmg:= 0;
             if (Flags and afSetSkip <> 0) then skip:= true;
             if (Flags and afTrackFall <> 0) and (Score > 0) then
-                fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Kind) * dmgMod);
+                fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Targets.ar[i]) * dmgMod);
             if Kind = gtHedgehog then
                 begin
                 if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
@@ -632,8 +644,7 @@
                         dec(rate, (power+fallDmg) * friendlyfactor div 100)
                     end
                 end
-// FIXME - need to make TraceFall calculate damage for barrels/mines correctly
-            else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((power+fallDmg) >= Score) then
+            else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
                 begin
                 dead:= true;
                 Targets.reset:= true;
@@ -696,8 +707,8 @@
                 else dX:= dX + 0.01;
                 if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
                    (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
-                     fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Kind) * dmgMod)
-                else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Kind) * dmgMod);
+                     fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
+                else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod);
                 if Kind = gtHedgehog then
                     begin
                     if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
@@ -725,8 +736,7 @@
                          inc(rate, dmg+fallDmg)
                     else dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
                     end
-// FIXME - need to make TraceFall calculate damage for barrels/mines correctly
-                else if (Kind <> gtHedgehog) and (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
+                else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
                     begin
                     dead:= true;
                     Targets.reset:= true;