Some brainfucking code which greatly reduces number of TestCollision* calls in hedgehog walk routine. Especially helpful to AI optimization. Also fixes some edge cases.
--- 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