# HG changeset patch # User unc0rr # Date 1183287767 0 # Node ID 465e2ec8f05fc0b977e0ae1077d856a0523c2a37 # Parent ec26095f1bedbd3efc5ac20f4d91b2f58493b49d - Better randomness of placing hedgehogs on the land - Bots can use AirAttack - Fix division by "zero" - Small optimizations diff -r ec26095f1bed -r 465e2ec8f05f QTfrontend/hedgewars.pro --- a/QTfrontend/hedgewars.pro Sun Jun 17 14:48:15 2007 +0000 +++ b/QTfrontend/hedgewars.pro Sun Jul 01 11:02:47 2007 +0000 @@ -41,7 +41,7 @@ chatwidget.h -SOURCES += binds.cpp +SOURCES += binds.cpp \ game.cpp \ main.cpp \ hwform.cpp \ diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/CCHandlers.inc --- a/hedgewars/CCHandlers.inc Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/CCHandlers.inc Sun Jul 01 11:02:47 2007 +0000 @@ -329,7 +329,7 @@ end end; -procedure chPut(var s: shortstring); +procedure doPut(putX, putY: LongInt; fromAI: boolean); begin if CheckNoTeamOrHH then exit; if bShowAmmoMenu then @@ -337,6 +337,7 @@ bSelected:= true; exit end; + with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^, CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do if (State and gstHHChooseTarget) <> 0 then @@ -344,15 +345,28 @@ isCursorVisible:= false; if not CurrentTeam^.ExtDriven then begin - SDL_GetMouseState(@TargetPoint.X, @TargetPoint.Y); - dec(TargetPoint.X, WorldDx); - dec(TargetPoint.Y, WorldDy); + if fromAI then + begin + TargetPoint.X:= putX; + TargetPoint.Y:= putY + end else + begin + SDL_GetMouseState(@TargetPoint.X, @TargetPoint.Y); + dec(TargetPoint.X, WorldDx); + dec(TargetPoint.Y, WorldDy) + end; SendIPCXY('p', TargetPoint.X, TargetPoint.Y); end; - State:= State and not gstHHChooseTarget; + State:= State and not gstHHChooseTarget; if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackingPut) <> 0 then Message:= Message or gm_Attack; end else if CurrentTeam^.ExtDriven then OutError('got /put while not being in choose target mode', false) + +end; + +procedure chPut(var s: shortstring); +begin +doPut(0, 0, false) end; procedure chCapture(var s: shortstring); diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/GSHandlers.inc Sun Jul 01 11:02:47 2007 +0000 @@ -1047,22 +1047,18 @@ end; //////////////////////////////////////////////////////////////////////////////// -const cAirPlaneSpeed: hwFloat = (isNegative: false; QWordValue: 6012954214); // 1.4 - cBombsDistance: hwFloat = (isNegative: false; QWordValue: 128849018880); // 30 - cBombsSpeed : hwFloat = (isNegative: false; QWordValue: 429496729); - procedure doStepAirAttackWork(Gear: PGear); begin AllInactive:= false; Gear^.X:= Gear^.X + cAirPlaneSpeed * Gear^.Tag; -if (Gear^.Health > 0)and( not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then +if (Gear^.Health > 0)and(not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then begin dec(Gear^.Health); case Gear^.State of 0: FollowGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0); 1: FollowGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine, 0, cBombsSpeed * Gear^.Tag, _0, 0); end; - Gear^.dX:= Gear^.dX + cBombsDistance * Gear^.Tag + Gear^.dX:= Gear^.dX + int2hwFloat(30 * Gear^.Tag) end; if (hwRound(Gear^.X) > 3072) or (hwRound(Gear^.X) < -1024) then DeleteGear(Gear) end; @@ -1070,15 +1066,17 @@ procedure doStepAirAttack(Gear: PGear); begin AllInactive:= false; + if Gear^.X.QWordValue = 0 then Gear^.Tag:= 1 else Gear^.Tag:= -1; Gear^.X:= _1024 - _2048 * Gear^.Tag; Gear^.Y:= -_128; -Gear^.dX:= int2hwFloat(TargetPoint.X) - - cBombsDistance * _5 * Gear^.Tag / _2; +Gear^.dX:= int2hwFloat(TargetPoint.X - 5 * Gear^.Tag * 15); -if TargetPoint.Y - hwRound(Gear^.Y) > 0 then +if int2hwFloat(TargetPoint.Y) - Gear^.Y > _0 then Gear^.dX:= Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(TargetPoint.Y) - Gear^.Y) * 2 / cGravity) * Gear^.Tag; +addfilelog('attack: x = '+floattostr(gear^.dx)); + Gear^.Health:= 6; Gear^.doStep:= @doStepAirAttackWork end; diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/HHHandlers.inc --- a/hedgewars/HHHandlers.inc Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/HHHandlers.inc Sun Jul 01 11:02:47 2007 +0000 @@ -47,7 +47,7 @@ PlaySound(sndThrowRelease, false); end; xx:= SignAs(AngleSin(Angle), dX); - yy:= -AngleCos(Angle); + yy:= -AngleCos(Angle); case Ammo^[CurSlot, CurAmmo].AmmoType of amGrenade: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtAmmo_Bomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer); amClusterBomb: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtClusterBomb, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer); diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uAI.pas --- a/hedgewars/uAI.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uAI.pas Sun Jul 01 11:02:47 2007 +0000 @@ -57,10 +57,10 @@ BestActions.Pos:= 0 end; -procedure TestAmmos(var Actions: TActions; Me: PGear); +procedure TestAmmos(var Actions: TActions; Me: PGear; isMoved: boolean); var Time, BotLevel: Longword; - Angle, Power, Score, ExplX, ExplY, ExplR: LongInt; - i: LongInt; + ap: TAttackParams; + Score, i: LongInt; a, aa: TAmmoType; begin BotLevel:= PHedgehog(Me^.Hedgehog)^.BotLevel; @@ -72,35 +72,44 @@ a:= Ammo^[CurSlot, CurAmmo].AmmoType; aa:= a; repeat - if CanUseAmmo[a] then + if (CanUseAmmo[a]) and + ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) then begin - Score:= AmmoTests[a](Me, Targets.ar[i].Point, BotLevel, Time, Angle, Power, ExplX, ExplY, ExplR); + Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap); if Actions.Score + Score > BestActions.Score then + if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + LongInt(BotLevel) * 2048) then begin BestActions:= Actions; inc(BestActions.Score, Score); - AddAction(BestActions, aia_Weapon, Longword(a), 500, 0, 0); - if Time <> 0 then AddAction(BestActions, aia_Timer, Time div 1000, 400, 0, 0); - if (Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) - else if (Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); + AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0); + if (ap.Time <> 0) then AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0); + if (ap.Angle > 0) then AddAction(BestActions, aia_LookRight, 0, 200, 0, 0) + else if (ap.Angle < 0) then AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0); if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then begin - Angle:= LongInt(Me^.Angle) - Abs(Angle); - if Angle > 0 then + ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle); + if ap.Angle > 0 then begin - AddAction(BestActions, aia_Up, aim_push, 500, 0, 0); - AddAction(BestActions, aia_Up, aim_release, Angle, 0, 0) - end else if Angle < 0 then + AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0); + AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0) + end else if ap.Angle < 0 then begin - AddAction(BestActions, aia_Down, aim_push, 500, 0, 0); - AddAction(BestActions, aia_Down, aim_release, -Angle, 0, 0) + AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0); + AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0) end end; - AddAction(BestActions, aia_attack, aim_push, 800, 0, 0); - AddAction(BestActions, aia_attack, aim_release, Power, 0, 0); - if ExplR > 0 then - AddAction(BestActions, aia_AwareExpl, ExplR, 10, ExplX, ExplY); + if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then + begin + AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY) + end; + if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then + begin + AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0); + AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); + end; + if ap.ExplR > 0 then + AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY); end end; if a = High(TAmmoType) then a:= Low(TAmmoType) @@ -188,7 +197,7 @@ if (Me^.State and gstAttacked) = 0 then maxticks:= max(0, TurnTimeLeft - 5000 - 4000 * BotLevel) else maxticks:= TurnTimeLeft; -if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me); +if (Me^.State and gstAttacked) = 0 then TestAmmos(Actions, Me, false); BestRate:= RatePlace(Me); BaseRate:= max(BestRate, 0); @@ -232,7 +241,7 @@ end else if Rate < BestRate then break; if ((Me^.State and gstAttacked) = 0) - and ((steps mod 4) = 0) then TestAmmos(Actions, Me); + and ((steps mod 4) = 0) then TestAmmos(Actions, Me, true); if GoInfo.FallPix >= FallPixForBranching then Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right end; @@ -300,7 +309,7 @@ end; FillBonuses((Me^.State and gstAttacked) <> 0); for a:= Low(TAmmoType) to High(TAmmoType) do - CanUseAmmo[a]:= Assigned(AmmoTests[a]) and HHHasAmmo(PHedgehog(Me^.Hedgehog), a); + CanUseAmmo[a]:= Assigned(AmmoTests[a].proc) and HHHasAmmo(PHedgehog(Me^.Hedgehog), a); {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF} BeginThread(@Think, Me, ThinkThread) end; diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uAIActions.pas --- a/hedgewars/uAIActions.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uAIActions.pas Sun Jul 01 11:02:47 2007 +0000 @@ -39,6 +39,7 @@ aia_LJump = $8007; aia_Skip = $8008; aia_Wait = $8009; + aia_Put = $800A; aim_push = $8000; aim_release = $8001; @@ -176,6 +177,7 @@ aia_HJump: ParseCommand('hjump', true); aia_LJump: ParseCommand('ljump', true); aia_Skip: ParseCommand('skip', true); + aia_Put: doPut(X, Y, true); end else begin s:= ActionIdToStr[Action]; 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. diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uConsole.pas --- a/hedgewars/uConsole.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uConsole.pas Sun Jul 01 11:02:47 2007 +0000 @@ -31,6 +31,8 @@ procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean); function GetLastConsoleLine: shortstring; +procedure doPut(putX, putY: LongInt; fromAI: boolean); + implementation {$J+} uses uMisc, uStore, Types, uConsts, uGears, uTeams, uIO, uKeys, uWorld, uLand, diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uFloat.pas --- a/hedgewars/uFloat.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uFloat.pas Sun Jul 01 11:02:47 2007 +0000 @@ -214,7 +214,8 @@ t.QWordValue:= t.QWordValue shl 1; z2.QWordValue:= z2.QWordValue shl 1 end; - z.Frac:= (t.QWordValue) div (z2.Round) + if z2.Round > 0 then z.Frac:= (t.QWordValue) div (z2.Round) + else z.Frac:= 0 end end; diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uGears.pas --- a/hedgewars/uGears.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uGears.pas Sun Jul 01 11:02:47 2007 +0000 @@ -278,7 +278,7 @@ Result^.Tag:= Y end; gtAirBomb: begin - Result^.Radius:= 10; + Result^.Radius:= 5; end; gtBlowTorch: begin Result^.Radius:= cHHRadius + cBlowTorchC; @@ -776,19 +776,45 @@ procedure AssignHHCoords; var Team: PTeam; i, t: LongInt; + ar: array[0..Pred(cMaxHHs)] of PGear; + Count: Longword; begin Team:= TeamsList; -t:= 0; -while Team <> nil do + +if (GameFlags and gfForts) <> 0 then + begin + t:= 0; + while Team <> nil do + begin + for i:= 0 to cMaxHHIndex do + with Team^.Hedgehogs[i] do + if Gear <> nil then FindPlace(Gear, false, t, t + 1024); + inc(t, 1024); + Team:= Team^.Next + end + end else // mix hedgehogs + begin + Count:= 0; + while Team <> nil do begin for i:= 0 to cMaxHHIndex do with Team^.Hedgehogs[i] do if Gear <> nil then - if (GameFlags and gfForts) = 0 then FindPlace(Gear, false, 0, 2048) - else FindPlace(Gear, false, t, t + 1024); - inc(t, 1024); + begin + ar[Count]:= Gear; + inc(Count) + end; Team:= Team^.Next + end; + + while (Count > 0) do + begin + i:= GetRandom(Count); + FindPlace(ar[i], false, 0, 2048); + ar[i]:= ar[Count - 1]; + dec(Count) end + end end; function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear; diff -r ec26095f1bed -r 465e2ec8f05f hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Sun Jun 17 14:48:15 2007 +0000 +++ b/hedgewars/uMisc.pas Sun Jul 01 11:02:47 2007 +0000 @@ -70,6 +70,9 @@ cTimerInterval : Longword = 5; cHasFocus : boolean = true; + cAirPlaneSpeed: hwFloat = (isNegative: false; QWordValue: 6012954214); // 1.4 + cBombsSpeed : hwFloat = (isNegative: false; QWordValue: 429496729); + var cSendEmptyPacketTime : LongWord = 2000; cSendCursorPosTime : LongWord = 50;