- Better randomness of placing hedgehogs on the land
- Bots can use AirAttack
- Fix division by "zero"
- Small optimizations
--- 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 \
--- 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);
--- 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;
--- 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);
--- 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;
--- 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];
--- 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.
--- 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,
--- 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;
--- 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;
--- 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;