diff -r c321264439c6 -r b26aaf28c920 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Sat Apr 27 00:09:50 2013 +0400 +++ b/hedgewars/uAIMisc.pas Sat Apr 27 16:56:50 2013 -0400 @@ -33,11 +33,12 @@ type TTarget = record Point: TPoint; Score: LongInt; - skip, matters: boolean; + skip, matters, dead: boolean; end; TTargets = record Count: Longword; ar: array[0..Pred(cMaxHHs)] of TTarget; + reset: boolean; end; TJumpType = (jmpNone, jmpHJump, jmpLJump); TGoInfo = record @@ -55,6 +56,7 @@ procedure freeModule; procedure FillTargets; +procedure ResetTargets; inline; procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline; procedure FillBonuses(isAfterAttack: boolean); procedure AwareOfExplosion(x, y, r: LongInt); inline; @@ -66,9 +68,11 @@ function TraceShoveFall(x, y, dX, dY: Real): LongInt; function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; -function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; +function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; +function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; -function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; +function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; inline; +function RealRateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; function RateHammer(Me: PGear): LongInt; function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean; @@ -99,11 +103,20 @@ X, Y, Radius: LongInt end = (X: 0; Y: 0; Radius: 0); +procedure ResetTargets; inline; +var i: LongWord; +begin +if Targets.reset then + for i:= 0 to Targets.Count do + Targets.ar[i].dead:= false; +Targets.reset:= false; +end; procedure FillTargets; var i, t: Longword; f, e: LongInt; begin Targets.Count:= 0; +Targets.reset:= false; f:= 0; e:= 0; for t:= 0 to Pred(TeamsCount) do @@ -119,6 +132,7 @@ with Targets.ar[Targets.Count], Hedgehogs[i] do begin skip:= false; + dead:= false; matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0; Point.X:= hwRound(Gear^.X); @@ -326,7 +340,7 @@ -function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt; +function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord): LongInt; var skipLandCheck: boolean; rCorner: real; dmg: LongInt; @@ -391,14 +405,20 @@ end; end; -function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; +function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; begin - RateExplosion:= RateExplosion(Me, x, y, r, 0); + RateExplosion:= RealRateExplosion(Me, x, y, r, 0); + ResetTargets; +end; +function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline; +begin + RateExplosion:= RealRateExplosion(Me, x, y, r, Flags); + ResetTargets; end; -function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; +function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt; - dX, dY: real; + pX, pY, dX, dY: real; hadSkips: boolean; begin fallDmg:= 0; @@ -421,46 +441,55 @@ hadSkips:= false; for i:= 0 to Targets.Count do - with Targets.ar[i] do - if not matters then hadSkips:= true - else - begin - dmg:= 0; - if abs(Point.x - x) + abs(Point.y - y) < dmgBase then - dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r)); + if not Targets.ar[i].dead then + with Targets.ar[i] do + if not matters then hadSkips:= true + else + begin + dmg:= 0; + if abs(Point.x - x) + abs(Point.y - y) < dmgBase then + dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r)); - if dmg > 0 then - begin - if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then + if dmg > 0 then begin - dX:= 0.005 * dmg + 0.01; - dY:= dX; - if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and - (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then - fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) - else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod) - end; - if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI - if Score > 0 then - inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings + pX:= Point.x; + pY:= Point.y; + if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then + begin + dX:= 0.005 * dmg + 0.01; + dY:= dX; + if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and + (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then + fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod) + else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod) + end; + if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI + if Score > 0 then + inc(rate, (KillScore + Score div 10) * 1024) // Add a bit of a bonus for bigger hog drownings + else + dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs + else if (dmg+fallDmg) >= abs(Score) then + begin + dead:= true; + Targets.reset:= true; + if dX < 0.035 then + inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall))); + if Score > 0 then + inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill + else + dec(rate, KillScore * friendlyfactor div 100 * 1024) + end else - dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs - else if (dmg+fallDmg) >= abs(Score) then - if Score > 0 then - inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill - else - dec(rate, KillScore * friendlyfactor div 100 * 1024) - else - if Score > 0 then - inc(rate, (dmg + fallDmg) * 1024) - else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) + if Score > 0 then + inc(rate, (dmg + fallDmg) * 1024) + else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024) + end; end; - end; if hadSkips and (rate = 0) then - RateExplosion:= BadTurn + RealRateExplosion:= BadTurn else - RateExplosion:= rate; + RealRateExplosion:= rate; end; function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt; @@ -506,9 +535,14 @@ RateShove:= rate * 1024 end; -function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; +function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; inline; +begin + RateShotgun:= RealRateShotgun(Me, gdX, gdY, x, y); + ResetTargets; +end; +function RealRateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt; var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt; - dX, dY: real; + pX, pY, dX, dY: real; hadSkips: boolean; begin rate:= 0; @@ -532,48 +566,57 @@ hadSkips:= false; for i:= 0 to Targets.Count do - with Targets.ar[i] do - if not matters then hadSkips:= true - else - begin - dmg:= 0; - if abs(Point.x - x) + abs(Point.y - y) < baseDmg then - begin - dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25); - dmg:= trunc(dmg * dmgMod); - end; - if dmg > 0 then + if not Targets.ar[i].dead then + with Targets.ar[i] do + if not matters then hadSkips:= true + else begin - dX:= gdX * dmg; - dY:= gdY * dmg; - if dX < 0 then dX:= dX - 0.01 - else dX:= dX + 0.01; - if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and - (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then - fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod) - else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod); - if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI - if Score > 0 then - inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings + dmg:= 0; + if abs(Point.x - x) + abs(Point.y - y) < baseDmg then + begin + dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25); + dmg:= trunc(dmg * dmgMod); + end; + if dmg > 0 then + begin + pX:= Point.x; + pY:= Point.y; + dX:= gdX * dmg; + dY:= gdY * dmg; + if dX < 0 then dX:= dX - 0.01 + else dX:= dX + 0.01; + if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and + (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then + fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0) * dmgMod) + else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure) * dmgMod); + if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI + if Score > 0 then + inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings + else + dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs + else if (dmg+fallDmg) >= abs(Score) then + begin + dead:= true; + Targets.reset:= true; + if dX < 0.035 then + inc(Rate,RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall) div 1024); + if Score > 0 then + inc(rate, KillScore) + else + dec(rate, KillScore * friendlyfactor div 100) + end else - dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs - else if (dmg+fallDmg) >= abs(Score) then - if Score > 0 then - inc(rate, KillScore) + if Score > 0 then + inc(rate, dmg+fallDmg) else - dec(rate, KillScore * friendlyfactor div 100) - else - if Score > 0 then - inc(rate, dmg+fallDmg) - else - dec(rate, (dmg+fallDmg) * friendlyfactor div 100) + dec(rate, (dmg+fallDmg) * friendlyfactor div 100) + end; end; - end; if hadSkips and (rate = 0) then - RateShotgun:= BadTurn + RealRateShotgun:= BadTurn else - RateShotgun:= rate * 1024; + RealRateShotgun:= rate * 1024; end; function RateHammer(Me: PGear): LongInt;