# HG changeset patch # User nemo # Date 1367096210 14400 # Node ID b26aaf28c92088092c2568c409ceca2d11d0460e # Parent c321264439c6f355fd65f4f297d16294c222ce22 So. First pass. Add secondary explosions to RateExplosion and RateShotgun. Not yet added to shoves. This is of limited utility at present since the dX has to be small since we can't bother tracing all hog motion. But, should be more useful once shove is added, and tracking of explosives and mines. 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;