# HG changeset patch # User Wuzzy # Date 1591646025 -7200 # Node ID 39a353e8ef3df6422231f1f794e1b155623e2cb3 # Parent be8fe5e0789ea2708e110ece31da9a11995837c9 AI: Rewrite TestMolotov The old function was broken, the AI just refused to use the molotov, ever diff -r be8fe5e0789e -r 39a353e8ef3d hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Mon Jun 08 21:13:31 2020 +0200 +++ b/hedgewars/uAIAmmoTests.pas Mon Jun 08 21:53:45 2020 +0200 @@ -561,61 +561,85 @@ end; function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams; Flags: LongWord): LongInt; -var Vx, Vy, r: real; - Score, EX, EY, valueResult: LongInt; - TestTime: LongInt; - targXWrap, x, y, dY, meX, meY: real; +const timeLimit = 50; +var Vx, Vy, r, meX, meY: real; + rTime: LongInt; + EX, EY: LongInt; + valueResult: LongInt; + targXWrap, x, y, dX, dY: real; t: LongInt; + value, range: LongInt; begin Flags:= Flags; // avoid compiler hint meX:= hwFloat2Float(Me^.X); meY:= hwFloat2Float(Me^.Y); -valueResult:= BadTurn; -TestTime:= 0; +ap.Time:= 0; +rTime:= 350; ap.ExplR:= 0; if (WorldEdge = weWrap) then if (Targ.Point.X < meX) then targXWrap:= Targ.Point.X + (RightX-LeftX) else targXWrap:= Targ.Point.X - (RightX-LeftX); +valueResult:= BadTurn; repeat - inc(TestTime, 300); + rTime:= rTime + 300 + Level * 50 + random(300); if (WorldEdge = weWrap) and (random(2)=0) then - Vx:= (targXWrap - meX) / TestTime - else Vx:= (Targ.Point.X - meX) / TestTime; - Vy:= cGravityf * (TestTime div 2) - Targ.Point.Y - meY / TestTime; + Vx:= (targXWrap + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime + else + Vx:= (Targ.Point.X + AIrndSign(2) + AIrndOffset(Targ, Level) - meX) / rTime; + Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - meY) / rTime; r:= sqr(Vx) + sqr(Vy); + if not (r > 1) then begin x:= meX; y:= meY; + dX:= Vx; dY:= -Vy; - t:= TestTime; + t:= rTime; repeat x:= CheckWrap(x); - x:= x + Vx; + x:= x + dX; + 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^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) 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 < -timeLimit); + 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; + + // Sanity check 1: Make sure we're not too close to impact location + range:= Metric(trunc(meX), trunc(meY), EX, EY); + if (range < 150) and (Level < 5) then + exit(BadTurn); + + // Sanity check 2: If impact location is close, above us and wind blows + // towards us, there's a risk of fire flying towards us, so fail in this case. + if (Level < 3) and (range <= 600) and (trunc(meY) >= EX) and + (((ap.Angle < 0) and (windSpeed > 0)) or ((ap.Angle > 0) and (windSpeed < 0))) then + exit(BadTurn); - if valueResult < Score then + if t >= -timeLimit then + value:= RateExplosion(Me, EX, EY, 97) // average of 17 attempts, most good, but some failing spectacularly + else + value:= BadTurn; + + if (value = 0) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then + value := BadTurn; + + if (valueResult < value) or ((valueResult = value) and (Level < 3)) 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 - 1) * 9)); + ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1); ap.ExplR:= 100; ap.ExplX:= EX; ap.ExplY:= EY; - valueResult:= Score + valueResult:= value end; end -until (TestTime > 5050 - Level * 800); +until rTime > 5050 - Level * 800; TestMolotov:= valueResult end;