- New First Aid powerup
authorunc0rr
Tue, 11 Jul 2006 21:04:05 +0000
changeset 75 d2b737858ff7
parent 74 42257fee61ae
child 76 4e50c2bdeefc
- New First Aid powerup - New power progressbar - Less powerful Desert Eagle - Bots can use Desert Eagle - Set TurnTimeLeft to 0 when hh damaged - Bots can handle situation when ammo is over - Bots can go in different directions to reach good position, not just only go left or right - Small fixes for FillLand (use all the array) - Fixes for world geometry, get rid of one variable - Added missed in previous commit files - New test map
Fonts_LICENSE.txt
README.txt
hedgewars/CMakeLists.txt
hedgewars/Data/CMakeLists.txt
hedgewars/Data/Graphics/FirstAid.png
hedgewars/Data/Graphics/Power.png
hedgewars/Data/Maps/test2/map.png
hedgewars/GSHandlers.inc
hedgewars/HHHandlers.inc
hedgewars/uAI.pas
hedgewars/uAIActions.pas
hedgewars/uAIAmmoTests.pas
hedgewars/uAIMisc.pas
hedgewars/uConsts.pas
hedgewars/uGears.pas
hedgewars/uLand.pas
hedgewars/uMisc.pas
hedgewars/uTeams.pas
hedgewars/uWorld.pas
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fonts_LICENSE.txt	Tue Jul 11 21:04:05 2006 +0000
@@ -0,0 +1,48 @@
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org.
--- a/README.txt	Sat Jul 08 21:40:03 2006 +0000
+++ b/README.txt	Tue Jul 11 21:04:05 2006 +0000
@@ -5,12 +5,11 @@
 images in Data/Graphics, 
 sounds in Data/Sounds,
 themes "avematan", "bubbles", "tibet"
-fort "Barrelhouse"
-(c) 2004, 2005 Andrey Korotaev <unC0Rr@gmail.com>
+Copyright 2004, 2005 Andrey Korotaev <unC0Rr@gmail.com>
 
 Fonts  
-(c) 1995 Gavin Helf <ghelf@violet.berkeley.edu>, <gh22@cornell.edu>
+See Fonts_LICENSE.txt
 
 Images in Data/Front, Data/Graphics/Graves, 
 themes "ethereal", "norsk", "wood", "xtheme"
-(c) 2005 Alexey Andreev <grayfox@inbox.ru>
\ No newline at end of file
+Copyright 2005 Alexey Andreev <grayfox@inbox.ru>
\ No newline at end of file
--- a/hedgewars/CMakeLists.txt	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/CMakeLists.txt	Tue Jul 11 21:04:05 2006 +0000
@@ -1,3 +1,5 @@
+add_subdirectory(Data)
+
 set(dcc32_tryexe dcc32.exe)
 set(ppc386_tryexe ppc386)
 set(hwengine_project "hwengine.dpr")
@@ -28,7 +30,7 @@
 			message("Minimum required version of FreePascal is 1.9.2")
 		else (ppc386_ver LESS "010902")
 			set(pascal_compiler ${ppc386_executable})
-			set(pascal_compiler_flags "-B -Sd -Xs -OG -Or -O2 -Cs2000000"${hwengine_project})
+			set(pascal_compiler_flags "-B -Sd -Xs -OG -O3 -Cs2000000"${hwengine_project})
 		endif (ppc386_ver LESS "010902")
 	endif (ppc386_version)
 endif (dcc32version)
Binary file hedgewars/Data/Graphics/FirstAid.png has changed
Binary file hedgewars/Data/Graphics/Power.png has changed
Binary file hedgewars/Data/Maps/test2/map.png has changed
--- a/hedgewars/GSHandlers.inc	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/GSHandlers.inc	Tue Jul 11 21:04:05 2006 +0000
@@ -73,7 +73,7 @@
 begin
 AllInactive:= false;
 Gear.Y:= Gear.Y + cDrownSpeed;
-if round(Gear.Y) > Gear.Radius + cWaterLine + 48 + cVisibleWater then DeleteGear(Gear)
+if round(Gear.Y) > Gear.Radius + cWaterLine + cVisibleWater then DeleteGear(Gear)
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -252,9 +252,10 @@
 CheckCollision(Gear);
 if (Gear.State and gstCollision) <> 0 then
    begin
-   AmmoShove(Gear, 25);
+   AmmoShove(Gear, 25, 25);
    doMakeExplosion(round(Gear.X), round(Gear.Y), 25, EXPLNoDamage or EXPLDoNotTouchHH);
    DeleteGear(Gear);
+   AfterAttack;
    exit
    end;
 dec(i)
@@ -279,7 +280,7 @@
   y:= round(Gear.Y);
   if ((y and $FFFFFC00) = 0) and ((x and $FFFFF800) = 0)
      and (Land[y, x] <> 0) then inc(Gear.Damage);
-  AmmoShove(Gear, 12);
+  AmmoShove(Gear, 7, 20);
   dec(i)
 until (i = 0) or (Gear.Damage > Gear.Health);
 if Gear.Damage > 0 then
@@ -491,9 +492,9 @@
 HHGear.dY:= HHGear.Y - HHGear.dY;
 
 if TestCollisionXwithGear(HHGear, Sign(HHGear.dX)) then
-   HHGear.dX:= -0.9 * HHGear.dX;
+   HHGear.dX:= -0.6 * HHGear.dX;
 if TestCollisionYwithGear(HHGear, Sign(HHGear.dY)) then
-   HHGear.dY:= -0.9 * HHGear.dY;
+   HHGear.dY:= -0.6 * HHGear.dY;
 
 if (Gear.Message and gm_Attack) <> 0 then
    if (Gear.State and gsttmpFlag) <> 0 then DeleteMe else
--- a/hedgewars/HHHandlers.inc	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/HHHandlers.inc	Tue Jul 11 21:04:05 2006 +0000
@@ -63,7 +63,7 @@
                           amUFO: FollowGear:= AddGear(round(X), round(Y), gtUFO,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor);
                       amShotgun: begin
                                  PlaySound(sndShotgunReload);
-                                 FollowGear:= AddGear(round(X), round(Y), gtShotgunShot,  0, xx * 0.5, yy * 0.5);
+                                 CurAmmoGear:= AddGear(round(X), round(Y), gtShotgunShot,  0, xx * 0.5, yy * 0.5);
                                  end;
                        amDEagle: begin
                                  FollowGear:= AddGear(round(X), round(Y), gtDEagleShot,   0, xx * 0.5, yy * 0.5);
@@ -135,6 +135,7 @@
 DeleteCI(Gear);
 if (TurnTimeLeft = 0) or (Gear.Damage > 0) then
    begin
+   TurnTimeLeft:= 0;
    if ((Gear.State and (gstMoving or gstFalling)) = 0)
       and (CurAmmoGear = nil) then Gear.dX:= 0.0000001 * Sign(Gear.dX);
    Gear.State:= Gear.State and not gstHHDriven;
@@ -180,7 +181,7 @@
 if ((Gear.State and gstAttacking) <> 0) and ((Gear.Message and gm_Attack) = 0) then
    begin
    Attack(Gear);
-   StepTicks:= 40
+   StepTicks:= cHHStepTicks
    end;
 
 if (Gear.State and gstFalling) <> 0 then
--- a/hedgewars/uAI.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uAI.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -43,6 +43,7 @@
 var BestActions: TActions;
     ThinkThread: PSDL_Thread = nil;
     StopThinking: boolean;
+    CanUseAmmo: array [TAmmoType] of boolean;
 
 procedure FreeActionsList;
 begin
@@ -65,13 +66,11 @@
 for i:= 0 to Pred(Targets.Count) do
     if Targets.ar[i].Score >= 0 then
        begin
-       if (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].AttacksNum > 0)
-          then with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
-                    a:= Ammo[CurSlot, CurAmmo].AmmoType
-          else a:= Low(TAmmoType);
+       with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
+            a:= Ammo[CurSlot, CurAmmo].AmmoType;
        aa:= a;
        repeat
-        if Assigned(AmmoTests[a]) then
+        if CanUseAmmo[a] then
            begin
            Score:= AmmoTests[a](Me, Targets.ar[i].Point, Time, Angle, Power, ExplX, ExplY, ExplR);
            if Actions.Score + Score + Targets.ar[i].Score > BestActions.Score then
@@ -105,31 +104,79 @@
 end;
 
 procedure Walk(Me: PGear);
+const FallTicksForBranching = cHHRadius * 2 + 8;
+      cBranchStackSize = 8;
+      
+type TStackEntry = record
+                   WastedTicks: Longword;
+                   MadeActions: TActions;
+                   Hedgehog: TGear;
+                   end;
+                   
+var Stack: record
+           Count: Longword;
+           States: array[0..Pred(cBranchStackSize)] of TStackEntry;
+           end;
+
+    procedure Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer);
+    begin
+    if Stack.Count < cBranchStackSize then
+       with Stack.States[Stack.Count] do
+            begin
+            WastedTicks:= Ticks;
+            MadeActions:= Actions;
+            Hedgehog:= Me;
+            Hedgehog.Message:= Dir;
+            inc(Stack.Count)
+            end
+    end;
+
+    procedure Pop(out Ticks: Longword; out Actions: TActions; out Me: TGear);
+    begin
+    dec(Stack.Count);
+    with Stack.States[Stack.Count] do
+         begin
+         Ticks:= WastedTicks;
+         Actions:= MadeActions;
+         Me:= Hedgehog
+         end
+    end;
+
+
 var Actions: TActions;
-    BackMe: TGear;
-    Dir, steps, maxsteps: integer;
-    BestRate, Rate: integer;
+    ticks, maxticks, steps: Longword;
+    BaseRate, BestRate, Rate: integer;
+    GoInfo: TGoInfo;
 begin
-Actions.Score:= 0;
 Actions.Count:= 0;
 Actions.Pos:= 0;
-BestActions.Count:= 0;
-if (Me.State and gstAttacked) = 0 then maxsteps:= (TurnTimeLeft - 4000) div cHHStepTicks
-                                  else maxsteps:= TurnTimeLeft div cHHStepTicks;
-BackMe:= Me^;
+Actions.Score:= 0;
+Stack.Count:= 0;
+
+Push(0, Actions, Me^, aia_Left);
+Push(0, Actions, Me^, aia_Right);
+
+if (Me.State and gstAttacked) = 0 then maxticks:= TurnTimeLeft - 5000
+                                  else maxticks:= TurnTimeLeft;
+
 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
 BestRate:= RatePlace(Me);
-for Dir:= aia_Left to aia_Right do
+BaseRate:= max(BestRate, 0);
+
+while (Stack.Count > 0) and not StopThinking do
     begin
-    Me.Message:= Dir;
+    Pop(ticks, Actions, Me^);
+    AddAction(Actions, Me.Message, aim_push, 250);
+    AddAction(Actions, aia_WaitX, round(Me.X), 0);
+    AddAction(Actions, Me.Message, aim_release, 0);
     steps:= 0;
-    while HHGo(Me) and (steps < maxsteps) do
+    
+    while HHGo(Me, GoInfo) do
        begin
+       inc(ticks, GoInfo.Ticks);
+       if ticks > maxticks then break;
        inc(steps);
-       Actions.Count:= 0;
-       AddAction(Actions, Dir, aim_push, 250);
-       AddAction(Actions, aia_WaitX, round(Me.X), 0);
-       AddAction(Actions, Dir, aim_release, 0);
+       Actions.actions[Actions.Count - 2].Param:= round(Me.X);
        Rate:= RatePlace(Me);
        if Rate > BestRate then
           begin
@@ -137,14 +184,15 @@
           BestRate:= Rate;
           Me.State:= Me.State or gstAttacked // we have better place, go there and don't use ammo
           end
-       else if Rate < BestRate then
-               if BestRate > 0 then exit
-                               else break;
+       else if Rate < BestRate then break;
        if ((Me.State and gstAttacked) = 0)
            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
-       if StopThinking then exit;
+       if GoInfo.FallTicks >= FallTicksForBranching then
+          Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
+       if StopThinking then exit
        end;
-    Me^:= BackMe
+
+    if BestRate > BaseRate then exit
     end
 end;
 
@@ -172,8 +220,7 @@
             FillBonuses(true);
             WalkMe:= BackMe;
             Walk(@WalkMe)
-            end;
-      AwareOfExplosion(0, 0, 0)
+            end
       end;
 
 Me.State:= Me.State and not gstHHThinking;
@@ -181,6 +228,7 @@
 end;
 
 procedure StartThink(Me: PGear);
+var a: TAmmoType;
 begin
 if ((Me.State and gstAttacking) <> 0) or isInMultiShoot then exit;
 Me.State:= Me.State or gstHHThinking;
@@ -188,6 +236,8 @@
 ThinkingHH:= Me;
 FillTargets;
 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);
 {$IFDEF DEBUGFILE}AddFileLog('Enter Think Thread');{$ENDIF}
 ThinkThread:= SDL_CreateThread(@Think, Me)
 end;
@@ -199,8 +249,8 @@
         and ((Gear.State and gstHHDriven) <> 0)
         and (TurnTimeLeft < 29990)
         and ((Gear.State and gstHHThinking) = 0) then
-           if (BestActions.Pos = BestActions.Count) then StartThink(Gear)
-                                                    else ProcessAction(BestActions, Gear)
+           if (BestActions.Pos >= BestActions.Count) then StartThink(Gear)
+                                                     else ProcessAction(BestActions, Gear)
 end;
 
 end.
--- a/hedgewars/uAIActions.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uAIActions.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -34,7 +34,7 @@
 unit uAIActions;
 interface
 uses uGears;
-const MAXACTIONS = 32;
+const MAXACTIONS = 96;
       aia_none       = 0;
       aia_Left       = 1;
       aia_Right      = 2;
--- a/hedgewars/uAIAmmoTests.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uAIAmmoTests.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -38,6 +38,7 @@
 function TestBazooka(Me: PGear; Targ: TPoint; out Time: Longword; out Angle, Power: integer; out ExplX, ExplY, ExplR: integer): integer;
 function TestGrenade(Me: PGear; Targ: TPoint; out Time: Longword; out Angle, Power: integer; out ExplX, ExplY, ExplR: integer): integer;
 function TestShotgun(Me: PGear; Targ: TPoint; out Time: Longword; out Angle, Power: integer; out ExplX, ExplY, ExplR: integer): integer;
+function TestDesertEagle(Me: PGear; Targ: TPoint; out Time: Longword; out Angle, Power: integer; out ExplX, ExplY, ExplR: integer): integer;
 
 type TAmmoTestProc = function (Me: PGear; Targ: TPoint; out Time: Longword; out Angle, Power: integer; out ExplX, ExplY, ExplR: integer): integer;
 const AmmoTests: array[TAmmoType] of TAmmoTestProc =
@@ -50,12 +51,12 @@
 {amSkip}          nil,
 {amRope}          nil,
 {amMine}          nil,
-{amDEagle}        nil,
+{amDEagle}        TestDesertEagle,
 {amDynamite}      nil
                   );
 
 implementation
-uses uMisc, uAIMisc;
+uses uMisc, uAIMisc, uLand;
 const BadTurn = Low(integer);
 
 function Metric(x1, y1, x2, y2: integer): integer;
@@ -199,4 +200,33 @@
 Result:= BadTurn
 end;
 
+function TestDesertEagle(Me: PGear; Targ: TPoint; out Time: Longword; out Angle, Power: integer; out ExplX, ExplY, ExplR: integer): integer;
+var Vx, Vy, x, y, t: real;
+    d: Longword;
+begin
+if abs(Me.X - Targ.X) + abs(Me.Y - Targ.Y) < 80 then
+   begin
+   Result:= BadTurn;
+   exit
+   end;
+Time:= 0;
+Power:= 1;
+ExplR:= 0;
+t:= sqrt(sqr(Targ.X - Me.X) + sqr(Targ.Y - Me.Y)) * 2;
+Vx:= (Targ.X - Me.X) / t;
+Vy:= (Targ.Y - Me.Y) / t;
+x:= Me.X;
+y:= Me.Y;
+Angle:= DxDy2AttackAngle(Vx, -Vy);
+d:= 0;
+repeat
+  x:= x + vX;
+  y:= y + vY;
+  if ((round(x) and $FFFFF800) = 0)and((round(y) and $FFFFFC00) = 0)
+     and (Land[round(y), round(x)] <> 0) then inc(d);
+until (abs(Targ.X - x) + abs(Targ.Y - y) < 2) or (x < 0) or (y < 0) or (x > 2048) or (y > 1024) or (d > 200);
+if abs(Targ.X - x) + abs(Targ.Y - y) < 2 then Result:= max(0, (4 - d div 50) * 7 * 1024)
+                                         else Result:= Low(integer)
+end;
+
 end.
--- a/hedgewars/uAIMisc.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uAIMisc.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -43,6 +43,10 @@
                 Count: Longword;
                 ar: array[0..cMaxHHIndex*5] of TTarget;
                 end;
+     TGoInfo = record
+               Ticks: Longword;
+               FallTicks: Longword;
+               end;
 
 procedure FillTargets;
 procedure FillBonuses(isAfterAttack: boolean);
@@ -51,7 +55,7 @@
 function DxDy2AttackAngle(const _dY, _dX: Extended): integer;
 function TestColl(x, y, r: integer): boolean;
 function RateExplosion(Me: PGear; x, y, r: integer): integer;
-function HHGo(Gear: PGear): boolean;
+function HHGo(Gear: PGear; out GoInfo: TGoInfo): boolean;
 
 var ThinkingHH: PGear;
     Targets: TTargets;
@@ -212,23 +216,34 @@
 Result:= Result * 1024
 end;
 
-function HHGo(Gear: PGear): boolean;
+function HHGo(Gear: PGear; out GoInfo: TGoInfo): boolean;
 var pX, pY: integer;
 begin
 Result:= false;
+GoInfo.Ticks:= 0;
+GoInfo.FallTicks:= 0;
 repeat
 pX:= round(Gear.X);
 pY:= round(Gear.Y);
 if pY + cHHRadius >= cWaterLine then exit;
 if (Gear.State and gstFalling) <> 0 then
    begin
+   inc(GoInfo.Ticks);
    Gear.dY:= Gear.dY + cGravity;
-   if Gear.dY > 0.40 then exit;
+   if Gear.dY > 0.40 then
+      begin
+      Goinfo.FallTicks:= 0;
+      exit
+      end;
    Gear.Y:= Gear.Y + Gear.dY;
+   if round(Gear.Y) > pY then inc(GoInfo.FallTicks);
    if TestCollisionYwithGear(Gear, 1) then
       begin
+      inc(GoInfo.Ticks, 300);
       Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
-      Gear.dY:= 0
+      Gear.dY:= 0;
+      Result:= true;
+      exit
       end;
    continue
    end;
@@ -265,7 +280,11 @@
          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
       end;
 
-   if not TestCollisionXwithGear(Gear, Sign(Gear.dX)) then Gear.X:= Gear.X + Gear.dX;
+   if not TestCollisionXwithGear(Gear, Sign(Gear.dX)) then
+      begin
+      Gear.X:= Gear.X + Gear.dX;
+      inc(GoInfo.Ticks, cHHStepTicks)
+      end;
    if not TestCollisionYwithGear(Gear, 1) then
    begin
    Gear.Y:= Gear.Y + 1;
@@ -297,11 +316,11 @@
    end
    end
    end;
-if (pX <> round(Gear.X))and ((Gear.State and gstFalling) = 0) then
+if (pX <> round(Gear.X)) and ((Gear.State and gstFalling) = 0) then
    begin
    Result:= true;
    exit
-   end;
+   end
 until (pX = round(Gear.X)) and (pY = round(Gear.Y)) and ((Gear.State and gstFalling) = 0);
 end;
 
--- a/hedgewars/uConsts.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uConsts.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -244,7 +244,7 @@
                      (FileName:   'MineOff'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false),// sprMineOff
                      (FileName:    'MineOn'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false),// sprMineOn
                      (FileName:      'Case'; Path: ptGraphics; Width:  32; Height: 32; hasAlpha: false),// sprCase
-                     (FileName:  'FirstAid'; Path: ptGraphics; Width:  32; Height: 32; hasAlpha: false),// sprFAid
+                     (FileName:  'FirstAid'; Path: ptGraphics; Width:  48; Height: 48; hasAlpha: false),// sprFAid
                      (FileName:  'dynamite'; Path: ptGraphics; Width:  32; Height: 32; hasAlpha: false),// sprDynamite
                      (FileName:     'Power'; Path: ptGraphics; Width:  32; Height: 32; hasAlpha:  true) // sprPower
                      );
@@ -336,7 +336,7 @@
                                    TimeAfterTurn: 3000),
                                   (Name: 'Desert Eagle';
                                    Ammo: (Propz: 0;
-                                          Count: AMMO_INFINITE;
+                                          Count: 3;
                                           NumPerTurn: 3;
                                           Timer: 0;
                                           AmmoType: amDEagle);
--- a/hedgewars/uGears.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uGears.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -89,7 +89,7 @@
 
 procedure DeleteGear(Gear: PGear); forward;
 procedure doMakeExplosion(X, Y, Radius: integer; Mask: LongWord); forward;
-procedure AmmoShove(Ammo: PGear; Power: integer); forward;
+procedure AmmoShove(Ammo: PGear; Damage, Power: integer); forward;
 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: integer): PGear; forward;
 procedure SpawnBoxOfSmth; forward;
 procedure AfterAttack; forward;
@@ -196,7 +196,7 @@
                 Result.Timer:= 3000;
                 end;
         gtCase: begin
-                Result.Radius:= 14;
+                Result.Radius:= 16;
                 Result.Elasticity:= 0.6
                 end;
   gtDEagleShot: begin
@@ -497,7 +497,7 @@
         gtDynamite: DrawSprite2(sprDynamite, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 25 + WorldDy, Gear.Tag and 1, Gear.Tag shr 1, Surface);
             gtCase: case Gear.Pos of
                          posCaseAmmo  : DrawSprite(sprCase, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, 0, Surface);
-                         posCaseHealth: DrawSprite(sprFAid, Round(Gear.X) - 16 + WorldDx, Round(Gear.Y) - 16 + WorldDy, (GameTicks shr 6) and $F, Surface);
+                         posCaseHealth: DrawSprite(sprFAid, Round(Gear.X) - 24 + WorldDx, Round(Gear.Y) - 24 + WorldDy, (GameTicks shr 6) mod 13, Surface);
                          end;
               end;
       Gear:= Gear.NextGear
@@ -569,7 +569,7 @@
       end
 end;
 
-procedure AmmoShove(Ammo: PGear; Power: integer);
+procedure AmmoShove(Ammo: PGear; Damage, Power: integer);
 var t: PGearArray;
     i: integer;
     Gear: PGear;
@@ -583,7 +583,7 @@
            gtHedgehog,
                gtMine,
                gtCase: begin
-                       inc(t.ar[i].Damage, Power);
+                       inc(t.ar[i].Damage, Damage);
                        t.ar[i].dX:= Ammo.dX * Power * 0.01;
                        t.ar[i].dY:= Ammo.dY * Power * 0.01;
                        t.ar[i].Active:= true;
--- a/hedgewars/uLand.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uLand.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -203,6 +203,7 @@
 
     procedure Push(_xl, _xr, _y, _dir: integer);
     begin
+    TryDo(Stack.Count <= 8192, 'FillLand: stack overflow', true);
     _y:= _y + _dir;
     if (_y < 0) or (_y > 1023) then exit;
     with Stack.points[Stack.Count] do
@@ -212,8 +213,7 @@
          y:= _y;
          dir:= _dir
          end;
-    inc(Stack.Count);
-    TryDo(Stack.Count < 8192, 'stack overflow', true)
+    inc(Stack.Count)
     end;
 
     procedure Pop(out _xl, _xr, _y, _dir: integer);
--- a/hedgewars/uMisc.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uMisc.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -48,7 +48,6 @@
     TurnTimeLeft  : Longword = 0;
     cHedgehogTurnTime: Longword = 30000;
 
-    cLandYShift      : integer = 1088;
     cCloudsNumber    : integer = 9;
     cConsoleHeight   : integer = 320;
     cConsoleYAdd     : integer = 0; 
@@ -59,7 +58,7 @@
     cBitsStr         : string[2] = '16';
 
     cWaterLine       : integer = 1024;
-    cVisibleWater    : integer = 64;
+    cVisibleWater    : integer = 128;
     cScreenEdgesDist : integer = 240;
     cTeamHealthWidth : integer = 128;
 
--- a/hedgewars/uTeams.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uTeams.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -77,6 +77,7 @@
 procedure SwitchHedgehog;
 procedure InitTeams;
 procedure OnUsedAmmo(Ammo: PHHAmmo);
+function  HHHasAmmo(Hedgehog: PHedgehog; Ammo: TAmmoType): boolean;
 function  TeamSize(p: PTeam): Longword;
 procedure RecountTeamHealth(team: PTeam);
 procedure RestoreTeamsFromSave;
@@ -286,6 +287,20 @@
      end
 end;
 
+function  HHHasAmmo(Hedgehog: PHedgehog; Ammo: TAmmoType): boolean;
+var slot, ami: integer;
+begin
+Slot:= Ammoz[Ammo].Slot;
+ami:= 0;
+Result:= false;
+while (not Result) and (ami <= cMaxSlotAmmoIndex) do
+      begin
+      with  Hedgehog.Ammo[Slot, ami] do
+            if (AmmoType = Ammo) and (Count > 0) then Result:= true;
+      inc(ami)
+      end
+end;
+
 function  TeamSize(p: PTeam): Longword;
 var i: Longword;
 begin
--- a/hedgewars/uWorld.pas	Sat Jul 08 21:40:03 2006 +0000
+++ b/hedgewars/uWorld.pas	Tue Jul 11 21:04:05 2006 +0000
@@ -69,7 +69,6 @@
 
 procedure InitWorld;
 begin
-cLandYShift:= cWaterLine + 64;
 cWaterSprCount:= 1 + cScreenWidth div (SpritesData[sprWater].Width);
 cScreenEdgesDist:= Min(cScreenWidth div 4, cScreenHeight div 4);
 SDL_WarpMouse(cScreenWidth div 2, cScreenHeight div 2);
@@ -190,8 +189,8 @@
                 tdx:= Sign(Gear.dX) * Sin(Gear.Angle*pi/cMaxAngle);
                 tdy:= - Cos(Gear.Angle*pi/cMaxAngle);
                 for i:= (Gear.Power * 24) div cPowerDivisor downto 0 do
-                    DrawSprite(sprPower, round(Gear.X + WorldDx + tdx * (32 + i * 2)) - 16,
-                                         round(Gear.Y + WorldDy + tdy * (32 + i * 2)) - 12,
+                    DrawSprite(sprPower, round(Gear.X + WorldDx + tdx * (24 + i * 2)) - 16,
+                                         round(Gear.Y + WorldDy + tdy * (24 + i * 2)) - 12,
                                          i, Surface)
                 end
         end;
@@ -383,7 +382,7 @@
    end;
 SDL_WarpMouse(CursorPoint.X, CursorPoint.Y);
 prevPoint:= CursorPoint;
-if WorldDy < cScreenHeight - cLandYShift - cVisibleWater then WorldDy:= cScreenHeight - cLandYShift - cVisibleWater;
+if WorldDy < cScreenHeight - cWaterLine - cVisibleWater then WorldDy:= cScreenHeight - cWaterLine - cVisibleWater;
 if WorldDy >  2048 then WorldDy:=  2048;
 if WorldDx < -2048 then WorldDx:= -2048;
 if WorldDx > cScreenWidth then WorldDx:=  cScreenWidth;