diff -r 6ea838b8dcd5 -r 13ac59499066 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Sat Apr 20 02:17:53 2013 +0200 +++ b/hedgewars/uAIAmmoTests.pas Sat Apr 20 02:20:15 2013 +0200 @@ -21,7 +21,7 @@ unit uAIAmmoTests; interface uses SDLh, uConsts, uFloat, uTypes; -const +const amtest_Rare = $00000001; // check only several positions amtest_NoTarget = $00000002; // each pos, but no targetting @@ -163,9 +163,9 @@ dX:= dX + windSpeed; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0); - + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0); + EX:= trunc(x); EY:= trunc(y); if Level = 1 then @@ -184,7 +184,7 @@ end; end //until (value > 204800) or (rTime > 4250); not so useful since adding score to the drowning -until rTime > 4250; +until rTime > 5050 - Level * 800; TestBazooka:= valueResult end; @@ -226,10 +226,10 @@ dX:= dX + windSpeed; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (y > cWaterLine); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine); - if TestCollWithLand(trunc(x), trunc(y), 5) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then + if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then begin timer := 500; t2 := 0.5 / sqrt(sqr(dX) + sqr(dY)); @@ -244,11 +244,13 @@ or (y < 0) or (trunc(x) > LAND_WIDTH) or (trunc(y) > LAND_HEIGHT) - or not TestCollWithLand(trunc(x), trunc(y), 5) + or not TestCollExcludingObjects(trunc(x), trunc(y), 5) or (timer = 0) end; EX:= trunc(x); EY:= trunc(y); + // Try to prevent AI from thinking firing into water will cause a drowning + if (EY < cWaterLine-5) and (Timer > 0) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then exit(BadTurn); if Level = 1 then value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else value:= RateExplosion(Me, EX, EY, 101); @@ -262,7 +264,7 @@ valueResult:= value-2500 // trying to make it slightly less attractive than a bazooka, to prevent waste. AI could use awareness of weapon count end; end - until rTime > 4250; + until rTime > 5050 - Level * 800; TestDrillRocket:= valueResult end; @@ -301,8 +303,8 @@ dX:= dX + windSpeed; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0); EX:= trunc(x); EY:= trunc(y); @@ -321,7 +323,7 @@ valueResult:= value end; end -until (rTime > 4250); +until (rTime > 5050 - Level * 800); TestSnowball:= valueResult end; @@ -353,15 +355,15 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0); EX:= trunc(x); EY:= trunc(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 valueResult < Score then begin ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); @@ -372,7 +374,7 @@ valueResult:= Score end; end -until (TestTime > 4250); +until (TestTime > 5050 - Level * 800); TestMolotov:= valueResult end; @@ -397,7 +399,7 @@ if not (r > 1) then begin x:= meX; - y:= meY; + y:= meY; dY:= -Vy; t:= TestTime; repeat @@ -405,21 +407,21 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0); EX:= trunc(x); EY:= trunc(y); - if t < 50 then + if t < 50 then if Level = 1 then Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else Score:= RateExplosion(Me, EX, EY, 101) - else + else Score:= BadTurn; if (valueResult < Score) and (Score > 0) then begin - ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); - ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); + ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 3)); + ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 20); ap.Time:= TestTime; ap.ExplR:= 100; ap.ExplX:= EX; @@ -428,7 +430,7 @@ end; end //until (Score > 204800) or (TestTime > 4000); -until TestTime > 4000; +until TestTime > 4500 - Level * 512; TestGrenade:= valueResult end; @@ -465,18 +467,18 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0); + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0); EX:= trunc(x); EY:= trunc(y); - if t < 50 then + if t < 50 then Score:= RateExplosion(Me, EX, EY, 41) - else + else Score:= BadTurn; if valueResult < Score then begin - ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); + ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 2)); ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15); ap.Time:= TestTime div 1000 * 1000; ap.ExplR:= 90; @@ -518,16 +520,16 @@ y:= y + dY; dY:= dY + cGravityf; dec(t) - until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0); - + until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0); + EX:= trunc(x); EY:= trunc(y); - if t < 50 then + if t < 50 then Score:= RateExplosion(Me, EX, EY, 200) + RateExplosion(Me, EX, EY + 120, 200) - else + else Score:= BadTurn; - + if valueResult < Score then begin ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level)); @@ -564,7 +566,7 @@ else Solve:= 0 end; - + function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; //const tDelta = 24; var Vx, Vy: real; @@ -599,8 +601,8 @@ dY:= dY + cGravityf; EX:= trunc(x); EY:= trunc(y); - until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, EX, EY, 4))) or (EY > cWaterLine); + until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine); if (EY < cWaterLine) and (dY >= 0) then begin @@ -653,16 +655,16 @@ y:= y + vY; rx:= trunc(x); ry:= trunc(y); - if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or - ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, rx, ry, 2)) then + if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or + ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 2)) then begin x:= x + vX * 8; y:= y + vY * 8; valueResult:= RateShotgun(Me, vX, vY, rx, ry); - - if valueResult = 0 then + + if valueResult = 0 then valueResult:= 1024 - Metric(Targ.X, Targ.Y, rx, ry) div 64 - else + else dec(valueResult, Level * 4000); // 27/20 is reuse bonus exit(valueResult * 27 div 20) @@ -768,7 +770,7 @@ fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg); if fallDmg < 0 then TestSniperRifle:= BadTurn - else + else TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024) end else @@ -807,13 +809,13 @@ , 32, 30, 115 , dx, -dy, trackFall); if (v1 > valueResult) or (v2 > valueResult) then - if (v2 > v1) + if (v2 > v1) or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then begin ap.Angle:= a; valueResult:= v2 end - else + else begin ap.Angle:= -a; valueResult:= v1 @@ -821,7 +823,7 @@ a:= a - 15 - random(cMaxAngle div 16) end; - + if valueResult <= 0 then valueResult:= BadTurn; @@ -867,18 +869,18 @@ , 19, 30, 40 , 0.45, -0.9, trackFall); - if (v2 > v1) + if (v2 > v1) or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then begin ap.Angle:= 1; valueResult:= v2 end - else + else begin ap.Angle:= -1; valueResult:= v1 end; - + if valueResult <= 0 then valueResult:= BadTurn; @@ -902,8 +904,8 @@ y:= hwRound(Me^.Y); // check left direction - {first RateShove checks farthermost of two whip's AmmoShove attacks - to encourage distant attacks (damaged hog is excluded from view of second + {first RateShove checks farthermost of two whip's AmmoShove attacks + to encourage distant attacks (damaged hog is excluded from view of second RateShove call)} v1:= RateShove(x - 13, y , 30, 30, 25 @@ -921,18 +923,18 @@ , 30, 30, 25 , 1, -0.8, trackFall); - if (v2 > v1) + if (v2 > v1) or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then begin ap.Angle:= 1; valueResult:= v2 end - else + else begin ap.Angle:= -1; valueResult:= v1 end; - + if valueResult <= 0 then valueResult:= BadTurn else @@ -951,13 +953,13 @@ ap.Time:= 0; ap.Power:= 1; - if Level = 1 then + if Level = 1 then trackFall:= afTrackFall else if Level = 2 then trackFall:= 0 else exit(BadTurn); - + valueResult:= 0; v:= 0; @@ -978,16 +980,16 @@ ap.Angle:= DxDy2AttackAnglef(dx, -dy) end; - + if dx >= 0 then cx:= 0.45 else cx:= -0.45; for i:= 0 to 512 div step - 2 do begin - valueResult:= valueResult + + valueResult:= valueResult + RateShove(trunc(x), trunc(y) , 30, 30, 25 , cx, -0.9, trackFall or afSetSkip); - + x:= x + dx; y:= y + dy; end; @@ -1002,7 +1004,7 @@ for i:= 1 to 512 div step - 2 do begin y:= y + dy; - v:= v + + v:= v + RateShove(tx, trunc(y) , 30, 30, 25 , -cx, -0.9, trackFall or afSetSkip); @@ -1035,7 +1037,7 @@ ap.Time:= 0; ap.Power:= 1; ap.Angle:= 0; - + rate:= RateHammer(Me); if rate = 0 then rate:= BadTurn; @@ -1126,7 +1128,7 @@ 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 @@ -1145,7 +1147,7 @@ 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 ap.AttackPutX := bonuses.ar[i].X; @@ -1167,7 +1169,7 @@ begin cakeStep(Gear); v:= RateExplosion(Me, hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg * 2, afTrackFall); - if v > ap.Power then + if v > ap.Power then begin ap.ExplX:= hwRound(Gear^.X); ap.ExplY:= hwRound(Gear^.Y);