Some brainfucking code which greatly reduces number of TestCollision* calls in hedgehog walk routine. Especially helpful to AI optimization. Also fixes some edge cases.
authorunc0rr
Fri, 01 Jun 2012 12:42:44 +0400
changeset 7164 fad64b97947e
parent 7163 7db1e3a7422a
child 7165 aad1aea05f1e
child 7166 8d1d6adf5f82
Some brainfucking code which greatly reduces number of TestCollision* calls in hedgehog walk routine. Especially helpful to AI optimization. Also fixes some edge cases.
hedgewars/uAI.pas
hedgewars/uAIMisc.pas
hedgewars/uGearsHedgehog.pas
--- a/hedgewars/uAI.pas	Fri Jun 01 00:19:30 2012 +0200
+++ b/hedgewars/uAI.pas	Fri Jun 01 12:42:44 2012 +0400
@@ -266,9 +266,11 @@
                 with Stack.States[Pred(Stack.Count)] do
                     AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
 
+        // 'not CanGO' means we can't go straight, possible jumps are checked above
         if not CanGo then
             break;
-        inc(steps);
+        
+         inc(steps);
          Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
          Rate:= RatePlace(Me);
          if Rate > BestRate then
@@ -284,11 +286,11 @@
             TestAmmos(Actions, Me, true);
         if GoInfo.FallPix >= FallPixForBranching then
             Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
-        end;
+        end {while};
 
     if BestRate > BaseRate then
         exit
-        end
+        end {while}
 end;
 
 function Think(Me: Pointer): ptrint;
--- a/hedgewars/uAIMisc.pas	Fri Jun 01 00:19:30 2012 +0200
+++ b/hedgewars/uAIMisc.pas	Fri Jun 01 12:42:44 2012 +0400
@@ -129,12 +129,14 @@
 
 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline;
 begin
-bonuses.ar[bonuses.Count].x:= x;
-bonuses.ar[bonuses.Count].y:= y;
-bonuses.ar[bonuses.Count].Radius:= r;
-bonuses.ar[bonuses.Count].Score:= s;
-inc(bonuses.Count);
-TryDo(bonuses.Count <= MAXBONUS, 'Bonuses overflow', true)
+if(bonuses.Count < MAXBONUS) then
+    begin
+    bonuses.ar[bonuses.Count].x:= x;
+    bonuses.ar[bonuses.Count].y:= y;
+    bonuses.ar[bonuses.Count].Radius:= r;
+    bonuses.ar[bonuses.Count].Score:= s;
+    inc(bonuses.Count);
+    end;
 end;
 
 procedure FillBonuses(isAfterAttack: boolean);
@@ -162,7 +164,7 @@
                     
             gtExplosives:
             if isAfterAttack then
-                AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60+Gear^.Health);
+                AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health);
                 
             gtSMine:
                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30);
@@ -210,7 +212,7 @@
         r:= Radius;
         if abs(gX-X)+abs(gY-Y) < Radius then
             r:= trunc(sqrt(sqr(gX - X)+sqr(gY - Y)));
-        if r < 15 then
+        if r < 20 then
                 inc(rate, Score * Radius)
         else if r < Radius then
                 inc(rate, Score * (Radius - r))
@@ -612,114 +614,124 @@
 GoInfo.Ticks:= 0;
 GoInfo.FallPix:= 0;
 GoInfo.JumpType:= jmpNone;
+
 repeat
-pX:= hwRound(Gear^.X);
-pY:= hwRound(Gear^.Y);
-if pY + cHHRadius >= cWaterLine then
-    exit(false);
-if (Gear^.State and gstMoving) <> 0 then
-    begin
-    inc(GoInfo.Ticks);
-    Gear^.dY:= Gear^.dY + cGravity;
-    if Gear^.dY > _0_4 then
+    pX:= hwRound(Gear^.X);
+    pY:= hwRound(Gear^.Y);
+    if pY + cHHRadius >= cWaterLine then
+        exit(false);
+        
+    // hog is falling    
+    if (Gear^.State and gstMoving) <> 0 then
         begin
-        Goinfo.FallPix:= 0;
-        HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
-        exit(false)
-        end;
-    Gear^.Y:= Gear^.Y + Gear^.dY;
-    if hwRound(Gear^.Y) > pY then
-        inc(GoInfo.FallPix);
-    if TestCollisionYwithGear(Gear, 1) <> 0 then
-        begin
-        inc(GoInfo.Ticks, 410);
-        Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
-        Gear^.dY:= _0;
-        HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
-        HHGo:= true;
-        exit(false)
+        inc(GoInfo.Ticks);
+        Gear^.dY:= Gear^.dY + cGravity;
+        if Gear^.dY > _0_4 then
+            begin
+            Goinfo.FallPix:= 0;
+            // try ljump instead of fall with damage
+            HHJump(AltGear, jmpLJump, GoInfo); 
+            exit(false)
+            end;
+        Gear^.Y:= Gear^.Y + Gear^.dY;
+        if hwRound(Gear^.Y) > pY then
+            inc(GoInfo.FallPix);
+        if TestCollisionYwithGear(Gear, 1) <> 0 then
+            begin
+            inc(GoInfo.Ticks, 410);
+            Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
+            Gear^.dY:= _0;
+            // try ljump instead of fall
+            HHJump(AltGear, jmpLJump, GoInfo);
+            exit(true)
+            end;
+        continue
         end;
-    continue
-    end;
-    if (Gear^.Message and gmLeft  )<>0 then
-        Gear^.dX:= -cLittle
-    else
-        if (Gear^.Message and gmRight )<>0 then
-            Gear^.dX:=  cLittle
+        
+        // usual walk
+        if (Gear^.Message and gmLeft) <> 0 then
+            Gear^.dX:= -cLittle
         else
-            exit(false);
-    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
-        begin
-        if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            if (Gear^.Message and gmRight) <> 0 then
+                Gear^.dX:=  cLittle
+            else
+                exit(false);
+                
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+            begin
+            Gear^.Y:= Gear^.Y - _1;
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+            begin
+            Gear^.Y:= Gear^.Y - _1;
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+            begin
             Gear^.Y:= Gear^.Y - _1;
-            
-        if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+            begin
             Gear^.Y:= Gear^.Y - _1;
-            
-        if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+            begin
+            Gear^.Y:= Gear^.Y - _1;
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+            begin
             Gear^.Y:= Gear^.Y - _1;
-            
-        if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-            
-        if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
+            if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
+                Gear^.Y:= Gear^.Y + _6
+            end else Gear^.Y:= Gear^.Y + _5 else
+            end else Gear^.Y:= Gear^.Y + _4 else
+            end else Gear^.Y:= Gear^.Y + _3 else
+            end else Gear^.Y:= Gear^.Y + _2 else
+            end else Gear^.Y:= Gear^.Y + _1
+            end;
+
+        if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
+        begin
+            Gear^.X:= Gear^.X + int2hwFloat(hwSign(Gear^.dX));
+            inc(GoInfo.Ticks, cHHStepTicks)
         end;
 
-    if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
-    begin
-        Gear^.X:= Gear^.X + int2hwFloat(hwSign(Gear^.dX));
-        inc(GoInfo.Ticks, cHHStepTicks)
-    end;
+        // too scared to reformat this part
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y + _1;
+            
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y + _1;
+            
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y + _1;
 
-    // too scared to reformat this part
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-        
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-        
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y + _1;
 
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y + _1;
 
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y + _1;
 
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y - _6;
-        Gear^.dY:= _0;
-        Gear^.State:= Gear^.State or gstMoving
+        if TestCollisionYwithGear(Gear, 1) = 0 then
+            begin
+            Gear^.Y:= Gear^.Y - _6;
+            Gear^.dY:= _0;
+            Gear^.State:= Gear^.State or gstMoving
+            end
+        end
+        end
         end
-    end
-    end
-    end
-    end
-    end
-    end;
-if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
-    exit(true)
+        end
+        end
+        end;
+        // we have moved for 1 px
+        if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
+            exit(true)
 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
+
 HHJump(AltGear, jmpHJump, GoInfo);
 end;
 
--- a/hedgewars/uGearsHedgehog.pas	Fri Jun 01 00:19:30 2012 +0200
+++ b/hedgewars/uGearsHedgehog.pas	Fri Jun 01 12:42:44 2012 +0400
@@ -723,26 +723,32 @@
     DeleteCI(Gear); // must be after exit!! (see previous line)
 
     Gear^.Hedgehog^.visStepPos:= (Gear^.Hedgehog^.visStepPos + 1) and 7;
-    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
+
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+        begin
+        Gear^.Y:= Gear^.Y - _1;
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+        begin
+        Gear^.Y:= Gear^.Y - _1;
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+        begin
+        Gear^.Y:= Gear^.Y - _1;
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
         begin
-        if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
+        Gear^.Y:= Gear^.Y - _1;
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+        begin
+        Gear^.Y:= Gear^.Y - _1;
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then if (TestCollisionYwithGear(Gear, -1) = 0) then
+        begin
+        Gear^.Y:= Gear^.Y - _1;
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
+            Gear^.Y:= Gear^.Y + _6
+        end else Gear^.Y:= Gear^.Y + _5 else
+        end else Gear^.Y:= Gear^.Y + _4 else
+        end else Gear^.Y:= Gear^.Y + _3 else
+        end else Gear^.Y:= Gear^.Y + _2 else
+        end else Gear^.Y:= Gear^.Y + _1
         end;
 
     if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then