diff -r fc52f7c22c9b -r 6155187bf599 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Mon Jan 16 10:22:21 2012 +0100 +++ b/hedgewars/uAIAmmoTests.pas Tue Jan 17 09:01:31 2012 -0500 @@ -24,11 +24,11 @@ const amtest_OnTurn = $00000001; type TAttackParams = record - Time: Longword; - Angle, Power: LongInt; - ExplX, ExplY, ExplR: LongInt; - AttackPutX, AttackPutY: LongInt; - end; + Time: Longword; + Angle, Power: LongInt; + ExplX, ExplY, ExplR: LongInt; + AttackPutX, AttackPutY: LongInt; + end; function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -137,29 +137,31 @@ ap.ExplR:= 0; valueResult:= BadTurn; repeat - rTime:= rTime + 300 + Level * 50 + random(300); - Vx:= - cWindSpeedf * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime; - Vy:= cGravityf * rTime * 0.5 - (Targ.Y - mY) / rTime; - r:= sqrt(sqr(Vx) + sqr(Vy)); - if not (r > 1) then - begin + rTime:= rTime + 300 + Level * 50 + random(300); + Vx:= - cWindSpeedf * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime; + Vy:= cGravityf * rTime * 0.5 - (Targ.Y - mY) / rTime; + r:= sqrt(sqr(Vx) + sqr(Vy)); + if not (r > 1) then + begin x:= mX; y:= mY; dX:= Vx; dY:= -Vy; t:= rTime; repeat - x:= x + dX; - y:= y + dY; - dX:= dX + cWindSpeedf; - dY:= dY + cGravityf; - dec(t) + x:= x + dX; + y:= y + dY; + dX:= dX + cWindSpeedf; + dY:= dY + cGravityf; + dec(t) until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t <= 0); + EX:= trunc(x); EY:= trunc(y); value:= RateExplosion(Me, EX, EY, 101); - if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64; - if valueResult <= value then + if value = 0 then + value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64; + if valueResult <= value then begin ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9)); ap.Power:= trunc(r * cMaxPower) - random((Level - 1) * 17 + 1); @@ -168,7 +170,7 @@ ap.ExplY:= EY; valueResult:= value end; - end + end until (rTime > 4250); TestBazooka:= valueResult end; @@ -188,28 +190,29 @@ ap.ExplR:= 0; valueResult:= BadTurn; repeat - rTime:= rTime + 300 + Level * 50 + random(300); - Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime); - Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime); - r:= Distance(Vx, Vy); - if not (r > _1) then - begin + rTime:= rTime + 300 + Level * 50 + random(300); + Vx:= - cWindSpeed * rTime * _0_5 + (int2hwFloat(Targ.X + AIrndSign(2)) - Me^.X) / int2hwFloat(rTime); + Vy:= cGravity * rTime * _0_5 - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(rTime); + r:= Distance(Vx, Vy); + if not (r > _1) then + begin x:= Me^.X; y:= Me^.Y; dX:= Vx; dY:= -Vy; t:= rTime; repeat - x:= x + dX; - y:= y + dY; - dX:= dX + cWindSpeed; - dY:= dY + cGravity; - dec(t) + x:= x + dX; + y:= y + dY; + dX:= dX + cWindSpeed; + dY:= dY + cGravity; + dec(t) until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t <= 0); EX:= hwRound(x); EY:= hwRound(y); value:= RateExplosion(Me, EX, EY, 5); - if value = 0 then value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64; + if value = 0 then + value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64; if valueResult <= value then begin @@ -236,26 +239,28 @@ TestTime:= 0; ap.ExplR:= 0; repeat - inc(TestTime, 300); - Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime); - Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime); - r:= Distance(Vx, Vy); - if not (r > _1) then - begin + inc(TestTime, 300); + Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime); + Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime); + r:= Distance(Vx, Vy); + if not (r > _1) then + begin x:= Me^.X; y:= Me^.Y; dY:= -Vy; t:= TestTime; repeat - x:= x + Vx; - y:= y + dY; - dY:= dY + cGravity; - dec(t) + x:= x + Vx; + y:= y + dY; + dY:= dY + cGravity; + dec(t) until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 7) or (t = 0); EX:= hwRound(x); EY:= hwRound(y); - if t < 50 then Score:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly - else Score:= BadTurn; + if t < 50 then + Score:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly + else + Score:= BadTurn; if valueResult < Score then begin @@ -267,7 +272,7 @@ ap.ExplY:= EY; valueResult:= Score end; - end + end until (TestTime > 4250); TestMolotov:= valueResult end; @@ -284,22 +289,22 @@ TestTime:= 0; ap.ExplR:= 0; repeat - inc(TestTime, 1000); - Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); - Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta); - r:= Distance(Vx, Vy); - if not (r > _1) then - begin - x:= Me^.X; - y:= Me^.Y; - dY:= -Vy; - t:= TestTime; - repeat - x:= x + Vx; - y:= y + dY; - dY:= dY + cGravity; - dec(t) - until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0); + inc(TestTime, 1000); + Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); + Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime + tDelta); + r:= Distance(Vx, Vy); + if not (r > _1) then + begin + x:= Me^.X; + y:= Me^.Y; + dY:= -Vy; + t:= TestTime; + repeat + x:= x + Vx; + y:= y + dY; + dY:= dY + cGravity; + dec(t) + until TestCollExcludingMe(Me, hwRound(x), hwRound(y), 5) or (t = 0); EX:= hwRound(x); EY:= hwRound(y); if t < 50 then @@ -334,20 +339,20 @@ TestTime:= 0; ap.ExplR:= 0; repeat - inc(TestTime, 1000); - // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster - if Me^.X _1) then - begin - x:= Me^.X; - y:= Me^.Y; - dY:= -Vy; - t:= TestTime; + inc(TestTime, 1000); + // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster + if Me^.X _1) then + begin + x:= Me^.X; + y:= Me^.Y; + dY:= -Vy; + t:= TestTime; repeat x:= x + Vx; y:= y + dY; @@ -388,16 +393,16 @@ TestTime:= 0; ap.ExplR:= 0; repeat - inc(TestTime, 1000); - Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); - Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-200) - Me^.Y) / int2hwFloat(TestTime + tDelta); - r:= Distance(Vx, Vy); - if not (r > _1) then - begin - x:= Me^.X; - y:= Me^.Y; - dY:= -Vy; - t:= TestTime; + inc(TestTime, 1000); + Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); + Vy:= cGravity * ((TestTime + tDelta) div 2) - (int2hwFloat(Targ.Y-200) - Me^.Y) / int2hwFloat(TestTime + tDelta); + r:= Distance(Vx, Vy); + if not (r > _1) then + begin + x:= Me^.X; + y:= Me^.Y; + dY:= -Vy; + t:= TestTime; repeat x:= x + Vx; y:= y + dY; @@ -443,7 +448,9 @@ else T:= _0; Solve:= hwRound(T) - end else Solve:= 0 + end + else + Solve:= 0 end; function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -456,11 +463,13 @@ valueResult:= BadTurn; ap.ExplR:= 0; -if (Level > 2) then exit(BadTurn); +if (Level > 2) then + exit(BadTurn); TestTime:= Solve(Targ.X, Targ.Y, hwRound(Me^.X), hwRound(Me^.Y)); -if TestTime = 0 then exit(BadTurn); +if TestTime = 0 then + exit(BadTurn); Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime); Vy:= cGravity * (TestTime div 2) - (int2hwFloat(Targ.Y) - Me^.Y) / int2hwFloat(TestTime); @@ -485,7 +494,8 @@ Score:= - abs(Targ.Y - EY) div 32 else Score:= BadTurn - else if (Score < 0) then Score:= BadTurn + else if (Score < 0) then + Score:= BadTurn end else Score:= BadTurn; @@ -505,8 +515,8 @@ function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; const - MIN_RANGE = 80; - MAX_RANGE = 400; + MIN_RANGE = 80; + MAX_RANGE = 400; var Vx, Vy, x, y: hwFloat; rx, ry, valueResult: LongInt; range: integer; @@ -517,27 +527,28 @@ x:= Me^.X; y:= Me^.Y; range:= Metric(hwRound(x), hwRound(y), Targ.X, Targ.Y); -if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then exit(BadTurn); +if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then + exit(BadTurn); Vx:= (int2hwFloat(Targ.X) - x) * _1div1024; Vy:= (int2hwFloat(Targ.Y) - y) * _1div1024; ap.Angle:= DxDy2AttackAngle(Vx, -Vy); repeat - x:= x + vX; - y:= y + vY; - rx:= hwRound(x); - ry:= hwRound(y); - if TestCollExcludingMe(Me, rx, ry, 2) then - begin - x:= x + vX * 8; - y:= y + vY * 8; - valueResult:= RateShotgun(Me, rx, ry); + x:= x + vX; + y:= y + vY; + rx:= hwRound(x); + ry:= hwRound(y); + if TestCollExcludingMe(Me, rx, ry, 2) then + begin + x:= x + vX * 8; + y:= y + vY * 8; + valueResult:= RateShotgun(Me, rx, ry); - if valueResult = 0 then + if valueResult = 0 then valueResult:= - Metric(Targ.X, Targ.Y, rx, ry) div 64 - else + else dec(valueResult, Level * 4000); - exit(valueResult * 27 div 20) // 27/20 is reuse bonus - end + exit(valueResult * 27 div 20) // 27/20 is reuse bonus + end until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x.isNegative) or (y.isNegative) @@ -567,10 +578,11 @@ d:= 0; repeat - x:= x + vX; - y:= y + vY; - if ((hwRound(x) and LAND_WIDTH_MASK) = 0)and((hwRound(y) and LAND_HEIGHT_MASK) = 0) - and (Land[hwRound(y), hwRound(x)] <> 0) then inc(d); + x:= x + vX; + y:= y + vY; + if ((hwRound(x) and LAND_WIDTH_MASK) = 0)and((hwRound(y) and LAND_HEIGHT_MASK) = 0) + and (Land[hwRound(y), hwRound(x)] <> 0) then + inc(d); until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x.isNegative) or (y.isNegative) @@ -578,8 +590,10 @@ or (y.Round > LongWord(LAND_HEIGHT)) or (d > 200); -if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then valueResult:= Max(0, (4 - d div 50) * 7 * 1024) - else valueResult:= BadTurn; +if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then + valueResult:= Max(0, (4 - d div 50) * 7 * 1024) +else + valueResult:= BadTurn; TestDesertEagle:= valueResult end; @@ -590,16 +604,21 @@ Level:= Level; // avoid compiler hint ap.ExplR:= 0; if (Level > 2) or (Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 25) then - exit(BadTurn); + exit(BadTurn); ap.Time:= 0; ap.Power:= 1; x:= Me^.X; y:= Me^.Y; -if (Targ.X) - hwRound(x) >= 0 then ap.Angle:= cMaxAngle div 4 - else ap.Angle:= - cMaxAngle div 4; +if (Targ.X) - hwRound(x) >= 0 then + 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); -if valueResult <= 0 then valueResult:= BadTurn else inc(valueResult); +if valueResult <= 0 then + valueResult:= BadTurn +else + inc(valueResult); TestBaseballBat:= valueResult; end; @@ -648,9 +667,10 @@ if (Abs(hwRound(Me^.X) + hwSign(Me^.dX) * 10 - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 20) then rate:= 0 - else +else rate:= RateHammer(Me); -if rate = 0 then rate:= BadTurn; +if rate = 0 then + rate:= BadTurn; TestHammer:= rate; end; @@ -664,7 +684,8 @@ begin ap.ExplR:= 0; ap.Time:= 0; -if (Level > 3) then exit(BadTurn); +if (Level > 3) then + exit(BadTurn); ap.AttackPutX:= Targ.X; ap.AttackPutY:= Targ.Y; @@ -682,22 +703,22 @@ valueResult:= 0; repeat - X:= X + cBombsSpeed; - Y:= Y + dY; - dY:= dY + cGravity; - fexit:= true; + X:= X + cBombsSpeed; + Y:= Y + dY; + dY:= dY + cGravity; + fexit:= true; - for i:= 0 to 9 do - if b[i] then - begin - fexit:= false; - if TestColl(hwRound(X) + i * 30, hwRound(Y), 4) then - begin - b[i]:= false; - dmg[i]:= RateExplosion(Me, hwRound(X) + i * 30, hwRound(Y), 58) - // 58 (instead of 60) for better prediction (hh moves after explosion of one of the rockets) - end - end; + for i:= 0 to 9 do + if b[i] then + begin + fexit:= false; + if TestColl(hwRound(X) + i * 30, hwRound(Y), 4) then + begin + b[i]:= false; + dmg[i]:= RateExplosion(Me, hwRound(X) + i * 30, hwRound(Y), 58) + // 58 (instead of 60) for better prediction (hh moves after explosion of one of the rockets) + end + end; until fexit or (Y.Round > cWaterLine); for i:= 0 to 5 do inc(valueResult, dmg[i]); @@ -709,13 +730,14 @@ dec(t, dmg[i]); inc(t, dmg[i + 6]); if t > valueResult then - begin - valueResult:= t; - ap.AttackPutX:= Targ.X - 30 - cShift + i * 30 - end + begin + valueResult:= t; + ap.AttackPutX:= Targ.X - 30 - cShift + i * 30 + end end; -if valueResult <= 0 then valueResult:= BadTurn; +if valueResult <= 0 then + valueResult:= BadTurn; TestAirAttack:= valueResult; end; @@ -728,30 +750,38 @@ TestTeleport := BadTurn; Level:= Level; // avoid compiler hint FillBonuses(true, [gtCase]); - if bonuses.Count = 0 then begin - if Me^.Health <= 100 then begin + if bonuses.Count = 0 then + begin + if Me^.Health <= 100 then + begin maxTop := Targ.Y - cHHRadius * 2; + while not TestColl(Targ.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do - dec(maxTop, cHHRadius*2); - if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then begin + dec(maxTop, cHHRadius*2); + if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then + begin ap.AttackPutX := Targ.X; ap.AttackPutY := maxTop + cHHRadius; TestTeleport := Targ.Y - maxTop; + end; end; - end; - end - else begin + end + else + begin failNum := 0; repeat i := random(bonuses.Count); inc(failNum); - until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius) or (failNum = bonuses.Count*2); - if failNum < bonuses.Count*2 then begin + until not TestColl(bonuses.ar[i].X, bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius, cHHRadius) + or (failNum = bonuses.Count*2); + + if failNum < bonuses.Count*2 then + begin ap.AttackPutX := bonuses.ar[i].X; ap.AttackPutY := bonuses.ar[i].Y - cHHRadius - bonuses.ar[i].Radius; TestTeleport := 0; + end; end; - end; end; end.