diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uAIAmmoTests.pas Sun Jul 01 11:02:47 2007 +0000 @@ -19,42 +19,55 @@ unit uAIAmmoTests; interface uses SDLh, uGears, uConsts, uFloat; +const amtest_OnTurn = $00000001; -function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +type TAttackParams = record + Time: Longword; + Angle, Power: LongInt; + ExplX, ExplY, ExplR: LongInt; + AttackPutX, AttackPutY: LongInt; + end; -type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; -const AmmoTests: array[TAmmoType] of TAmmoTestProc = +function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; + +type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; + TAmmoTest = record + proc: TAmmoTestProc; + flags: Longword; + end; + +const AmmoTests: array[TAmmoType] of TAmmoTest = ( -{amGrenade} @TestGrenade, -{amClusterBomb} nil, -{amBazooka} @TestBazooka, -{amUFO} nil, -{amShotgun} @TestShotgun, -{amPickHammer} nil, -{amSkip} nil, -{amRope} nil, -{amMine} nil, -{amDEagle} @TestDesertEagle, -{amDynamite} nil, -{amFirePunch} @TestFirePunch, -{amBaseballBat} @TestBaseballBat, -{amParachute} nil, -{amAirAttack} nil, -{amMineStrike} nil, -{amBlowTorch} nil, -{amGirder} nil, -{amTeleport} nil, -{amSwitch} nil + (proc: @TestGrenade; flags: 0), // amGrenade + (proc: nil; flags: 0), // amClusterBomb + (proc: @TestBazooka; flags: 0), // amBazooka + (proc: nil; flags: 0), // amUFO + (proc: @TestShotgun; flags: 0), // amShotgun + (proc: nil; flags: 0), // amPickHammer + (proc: nil; flags: 0), // amSkip + (proc: nil; flags: 0), // amRope + (proc: nil; flags: 0), // amMine + (proc: @TestDesertEagle; flags: 0), // amDEagle + (proc: nil; flags: 0), // amDynamite + (proc: @TestFirePunch; flags: 0), // amFirePunch + (proc: @TestBaseballBat; flags: 0), // amBaseballBat + (proc: nil; flags: 0), // amParachute + (proc: @TestAirAttack; flags: amtest_OnTurn), // amAirAttack + (proc: nil; flags: 0), // amMineStrike + (proc: nil; flags: 0), // amBlowTorch + (proc: nil; flags: 0), // amGirder + (proc: nil; flags: amtest_OnTurn), // amTeleport + (proc: nil; flags: 0) // amSwitch ); const BadTurn = Low(LongInt) div 4; - implementation uses uMisc, uAIMisc, uLand; @@ -63,7 +76,7 @@ Metric:= abs(x1 - x2) + abs(y1 - y2) end; -function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var Vx, Vy, r: hwFloat; rTime: LongInt; Score, EX, EY: LongInt; @@ -94,9 +107,9 @@ end; begin -Time:= 0; +ap.Time:= 0; rTime:= 350; -ExplR:= 0; +ap.ExplR:= 0; Result:= BadTurn; repeat rTime:= rTime + 300 + Level * 50 + random(300); @@ -108,11 +121,11 @@ Score:= CheckTrace; if Result <= Score then begin - Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9)); - Power:= hwRound(r * cMaxPower) - random((Level - 1) * 17 + 1); - ExplR:= 100; - ExplX:= EX; - ExplY:= EY; + ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9)); + ap.Power:= hwRound(r * cMaxPower) - random((Level - 1) * 17 + 1); + ap.ExplR:= 100; + ap.ExplX:= EX; + ap.ExplY:= EY; Result:= Score end; end @@ -120,7 +133,7 @@ TestBazooka:= Result end; -function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; const tDelta = 24; var Vx, Vy, r: hwFloat; Score, EX, EY, Result: LongInt; @@ -149,7 +162,7 @@ begin Result:= BadTurn; TestTime:= 0; -ExplR:= 0; +ap.ExplR:= 0; repeat inc(TestTime, 1000); Vx:= (int2hwFloat(Targ.X) - Me^.X) / int2hwFloat(TestTime + tDelta); @@ -160,12 +173,12 @@ Score:= CheckTrace; if Result < Score then begin - Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level)); - Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15); - Time:= TestTime; - ExplR:= 100; - ExplX:= EX; - ExplY:= EY; + ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level)); + ap.Power:= hwRound(r * cMaxPower) + AIrndSign(random(Level) * 15); + ap.Time:= TestTime; + ap.ExplR:= 100; + ap.ExplX:= EX; + ap.ExplY:= EY; Result:= Score end; end @@ -173,20 +186,20 @@ TestGrenade:= Result end; -function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var Vx, Vy, x, y: hwFloat; rx, ry, Result: LongInt; begin -ExplR:= 0; -Time:= 0; -Power:= 1; +ap.ExplR:= 0; +ap.Time:= 0; +ap.Power:= 1; if Metric(hwRound(Me^.X), hwRound(Me^.Y), Targ.X, Targ.Y) < 80 then exit(BadTurn); Vx:= (int2hwFloat(Targ.X) - Me^.X) * _1div1024; Vy:= (int2hwFloat(Targ.Y) - Me^.Y) * _1div1024; x:= Me^.X; y:= Me^.Y; -Angle:= DxDy2AttackAngle(Vx, -Vy); +ap.Angle:= DxDy2AttackAngle(Vx, -Vy); repeat x:= x + vX; y:= y + vY; @@ -205,14 +218,14 @@ TestShotgun:= BadTurn end; -function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var Vx, Vy, x, y, t: hwFloat; d: Longword; Result: LongInt; begin -ExplR:= 0; -Time:= 0; -Power:= 1; +ap.ExplR:= 0; +ap.Time:= 0; +ap.Power:= 1; if Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) < 80 then exit(BadTurn); t:= _0_5 / Distance(int2hwFloat(Targ.X) - Me^.X, int2hwFloat(Targ.Y) - Me^.Y); @@ -220,7 +233,7 @@ Vy:= (int2hwFloat(Targ.Y) - Me^.Y) * t; x:= Me^.X; y:= Me^.Y; -Angle:= DxDy2AttackAngle(Vx, -Vy); +ap.Angle:= DxDy2AttackAngle(Vx, -Vy); d:= 0; repeat x:= x + vX; @@ -229,33 +242,33 @@ and (Land[hwRound(y), hwRound(x)] <> 0) then inc(d); until (Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 4) or (x < _0) or (y < _0) or (x > _2048) or (y > _1024) or (d > 200); if Abs(Targ.X - hwRound(x)) + Abs(Targ.Y - hwRound(y)) < 3 then Result:= max(0, (4 - d div 50) * 7 * 1024) - else Result:= Low(LongInt); + else Result:= BadTurn; TestDesertEagle:= Result end; -function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var Result: LongInt; begin -ExplR:= 0; -if (Level > 2) and not (Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) < 25) then +ap.ExplR:= 0; +if (Level > 2) or (Abs(hwRound(Me^.X) - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 25) then exit(BadTurn); -Time:= 0; -Power:= 1; -if (Targ.X) - hwRound(Me^.X) >= 0 then Angle:= cMaxAngle div 4 - else Angle:= - cMaxAngle div 4; +ap.Time:= 0; +ap.Power:= 1; +if (Targ.X) - hwRound(Me^.X) >= 0 then ap.Angle:= cMaxAngle div 4 + else ap.Angle:= - cMaxAngle div 4; Result:= RateShove(Me, hwRound(Me^.X) + 10 * hwSign(int2hwFloat(Targ.X) - Me^.X), hwRound(Me^.Y), 15, 30); if Result <= 0 then Result:= BadTurn else inc(Result); TestBaseballBat:= Result end; -function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var Time: Longword; var Angle, Power: LongInt; var ExplX, ExplY, ExplR: LongInt): LongInt; +function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var i, Result: LongInt; begin -ExplR:= 0; -Time:= 0; -Power:= 1; -Angle:= 0; +ap.ExplR:= 0; +ap.Time:= 0; +ap.Power:= 1; +ap.Angle:= 0; if (Abs(hwRound(Me^.X) - Targ.X) > 25) or (Abs(hwRound(Me^.Y) - 50 - Targ.Y) > 50) then exit(BadTurn); @@ -267,4 +280,66 @@ TestFirePunch:= Result end; +function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +var X, Y, dY: hwFloat; + b: array[0..9] of boolean; + dmg: array[0..9] of LongInt; + fexit: boolean; + i, t, Result: LongInt; +begin +ap.ExplR:= 0; +ap.Time:= 0; +ap.AttackPutX:= Targ.X; +ap.AttackPutY:= Targ.Y; + +X:= int2hwFloat(Targ.X - 135); +X:= X - cBombsSpeed * hwSqrt(int2hwFloat((Targ.Y + 128) * 2) / cGravity); +Y:= -_128; +dY:= _0; + +for i:= 0 to 9 do + begin + b[i]:= true; + dmg[i]:= 0 + end; +Result:= 0; + +repeat + 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; +until fexit or (Y > _1024); + +for i:= 0 to 5 do inc(Result, dmg[i]); +t:= Result; +ap.AttackPutX:= Targ.X - 60; + +for i:= 0 to 3 do + begin + dec(t, dmg[i]); + inc(t, dmg[i + 6]); + if t > Result then + begin + Result:= t; + ap.AttackPutX:= Targ.X - 30 + i * 30 + end + end; + +if Result <= 0 then Result:= BadTurn; +TestAirAttack:= Result +end; + end.