- Fixed bug with hedgehog under water using rope
authorunc0rr
Thu, 20 Jul 2006 20:11:32 +0000
changeset 80 3c3dc6a148ca
parent 79 29b477319854
child 81 d74e0e914b50
- Fixed bug with hedgehog under water using rope - Add locale support in engine - Bots use ljump and hjump - Fix shotgun rating - Support for theme-dependent sprites - Horizon and sky can have any image size - Many small fixes
QTfrontend/frameTeam.cpp
QTfrontend/game.cpp
QTfrontend/teamselhelper.cpp
QTfrontend/teamselhelper.h
QTfrontend/translations/hedgewars_ru.qm
QTfrontend/translations/hedgewars_ru.ts
hedgewars/CCHandlers.inc
hedgewars/Data/Locale/en.txt
hedgewars/Data/Locale/ru.txt
hedgewars/Data/Themes/steel/Clouds.16.png
hedgewars/Data/Themes/steel/Clouds.32.png
hedgewars/GSHandlers.inc
hedgewars/HHHandlers.inc
hedgewars/hwengine.dpr
hedgewars/options.inc
hedgewars/uAI.pas
hedgewars/uAIActions.pas
hedgewars/uAIAmmoTests.pas
hedgewars/uAIMisc.pas
hedgewars/uConsts.pas
hedgewars/uGears.pas
hedgewars/uLand.pas
hedgewars/uLandObjects.pas
hedgewars/uLocale.pas
hedgewars/uMisc.pas
hedgewars/uStore.pas
hedgewars/uTeams.pas
hedgewars/uWorld.pas
--- a/QTfrontend/frameTeam.cpp	Sun Jul 16 08:13:51 2006 +0000
+++ b/QTfrontend/frameTeam.cpp	Thu Jul 20 20:11:32 2006 +0000
@@ -1,39 +1,38 @@
-#include "frameTeam.h"
-#include "teamselhelper.h"
-
-#include <QResizeEvent>
-#include <QCoreApplication>
-
-#include <iostream>
-using namespace std;
-
-FrameTeams::FrameTeams(QWidget* parent) :
-  QWidget(parent), mainLayout(this)
-{
-}
-
-void FrameTeams::addTeam(tmprop team)
-{
-  TeamShowWidget* pTeamShowWidget =new TeamShowWidget(team, this);
-  int hght=teamToWidget.empty() ? 0 : teamToWidget.begin()->second->size().height();
-  teamToWidget.insert(make_pair(team, pTeamShowWidget));
-  mainLayout.addWidget(pTeamShowWidget);
-  QResizeEvent* pevent=new QResizeEvent(parentWidget()->size(), parentWidget()->size());
-  QCoreApplication::postEvent(parentWidget(), pevent);
-}
-
-void FrameTeams::removeTeam(tmprop team)
-{
-  tmapTeamToWidget::iterator it=teamToWidget.find(team);
-  mainLayout.removeWidget(it->second);
-  delete it->second;
-  teamToWidget.erase(team);
-}
-
-QWidget* FrameTeams::getTeamWidget(tmprop team)
-{
-  tmapTeamToWidget::iterator it=teamToWidget.find(team);
-  QWidget* ret = it!=teamToWidget.end() ? it->second : 0;
-  if(!ret) throw; // FIXME: this is debug exception
-  return ret;
-}
+#include "frameTeam.h"
+#include "teamselhelper.h"
+
+#include <QResizeEvent>
+#include <QCoreApplication>
+
+using namespace std;
+
+FrameTeams::FrameTeams(QWidget* parent) :
+  QWidget(parent), mainLayout(this)
+{
+}
+
+void FrameTeams::addTeam(tmprop team)
+{
+  TeamShowWidget* pTeamShowWidget =new TeamShowWidget(team, this);
+  int hght=teamToWidget.empty() ? 0 : teamToWidget.begin()->second->size().height();
+  teamToWidget.insert(make_pair(team, pTeamShowWidget));
+  mainLayout.addWidget(pTeamShowWidget);
+  QResizeEvent* pevent=new QResizeEvent(parentWidget()->size(), parentWidget()->size());
+  QCoreApplication::postEvent(parentWidget(), pevent);
+}
+
+void FrameTeams::removeTeam(tmprop team)
+{
+  tmapTeamToWidget::iterator it=teamToWidget.find(team);
+  mainLayout.removeWidget(it->second);
+  delete it->second;
+  teamToWidget.erase(team);
+}
+
+QWidget* FrameTeams::getTeamWidget(tmprop team)
+{
+  tmapTeamToWidget::iterator it=teamToWidget.find(team);
+  QWidget* ret = it!=teamToWidget.end() ? it->second : 0;
+  if(!ret) throw; // FIXME: this is debug exception
+  return ret;
+}
--- a/QTfrontend/game.cpp	Sun Jul 16 08:13:51 2006 +0000
+++ b/QTfrontend/game.cpp	Thu Jul 20 20:11:32 2006 +0000
@@ -239,6 +239,7 @@
 	arguments << "46631";
 	arguments << (vid_Fullscreen ? "1" : "0");
 	arguments << "1";
+	arguments << tr("en.txt");
 	process->start("./hwengine", arguments);
 }
 
@@ -289,7 +290,7 @@
 	{
 		QMessageBox::critical(0,
 				tr("Error"),
-				tr("Cannot save demo to file %s").arg(filename),
+				tr("Cannot save demo to file %1").arg(filename),
 				tr("Quit"));
 		return ;
 	}
@@ -307,7 +308,7 @@
 	{
 		QMessageBox::critical(0,
 				tr("Error"),
-				tr("Cannot open demofile %s").arg(demofilename),
+				tr("Cannot open demofile %1").arg(demofilename),
 				tr("Quit"));
 		return ;
 	}
--- a/QTfrontend/teamselhelper.cpp	Sun Jul 16 08:13:51 2006 +0000
+++ b/QTfrontend/teamselhelper.cpp	Thu Jul 20 20:11:32 2006 +0000
@@ -1,32 +1,30 @@
-#include "teamselhelper.h"
-
-#include <QPixmap>
-#include <QPushButton>
-
-#include <iostream>
-
-void TeamLabel::teamButtonClicked()
-{
-  emit teamActivated(text());
-}
-
-TeamShowWidget::TeamShowWidget(tmprop team, QWidget * parent) :
-  QWidget(parent), mainLayout(this), m_team(team)
-{
-  QLabel* pixlbl=new QLabel();
-  pixlbl->setPixmap(QPixmap("./Data/Graphics/thinking.png"));
-  mainLayout.addWidget(pixlbl);
-
-  TeamLabel* lbl=new TeamLabel(team.teamName);
-  mainLayout.addWidget(lbl);
-
-  QPushButton* butt=new QPushButton("o");
-  mainLayout.addWidget(butt);
-
-  QObject::connect(butt, SIGNAL(clicked()), this, SLOT(activateTeam()));
-}
-
-void TeamShowWidget::activateTeam()
-{
-  emit teamStatusChanged(m_team);
-}
+#include "teamselhelper.h"
+
+#include <QPixmap>
+#include <QPushButton>
+
+void TeamLabel::teamButtonClicked()
+{
+  emit teamActivated(text());
+}
+
+TeamShowWidget::TeamShowWidget(tmprop team, QWidget * parent) :
+  QWidget(parent), mainLayout(this), m_team(team)
+{
+  QLabel* pixlbl=new QLabel();
+  pixlbl->setPixmap(QPixmap("./Data/Graphics/thinking.png"));
+  mainLayout.addWidget(pixlbl);
+
+  TeamLabel* lbl=new TeamLabel(team.teamName);
+  mainLayout.addWidget(lbl);
+
+  QPushButton* butt=new QPushButton("o");
+  mainLayout.addWidget(butt);
+
+  QObject::connect(butt, SIGNAL(clicked()), this, SLOT(activateTeam()));
+}
+
+void TeamShowWidget::activateTeam()
+{
+  emit teamStatusChanged(m_team);
+}
--- a/QTfrontend/teamselhelper.h	Sun Jul 16 08:13:51 2006 +0000
+++ b/QTfrontend/teamselhelper.h	Thu Jul 20 20:11:32 2006 +0000
@@ -1,43 +1,43 @@
-#ifndef _TEAMSEL_HELPER_INCLUDED
-#define _TEAMSEL_HELPER_INCLUDED
-
-#include <QLabel>
-#include <QWidget>
-#include <QString>
-
-#include "teamselect.h"
-
-class TeamLabel : public QLabel
-{
- Q_OBJECT
-
- public:
- TeamLabel(const QString& inp_str) : QLabel(inp_str) {};
-
- signals:
- void teamActivated(QString team_name);
-
- public slots:
- void teamButtonClicked();
-
-};
-
-class TeamShowWidget : public QWidget
-{
- Q_OBJECT
-
- private slots:
- void activateTeam();
-
- public:
- TeamShowWidget(tmprop team, QWidget * parent = 0);
- 
- private:
- QHBoxLayout mainLayout;
- tmprop m_team;
-
- signals:
- void teamStatusChanged(tmprop team);
-};
-
-#endif // _TEAMSEL_HELPER_INCLUDED
+#ifndef _TEAMSEL_HELPER_INCLUDED
+#define _TEAMSEL_HELPER_INCLUDED
+
+#include <QLabel>
+#include <QWidget>
+#include <QString>
+
+#include "teamselect.h"
+
+class TeamLabel : public QLabel
+{
+ Q_OBJECT
+
+ public:
+ TeamLabel(const QString& inp_str) : QLabel(inp_str) {};
+
+ signals:
+ void teamActivated(QString team_name);
+
+ public slots:
+ void teamButtonClicked();
+
+};
+
+class TeamShowWidget : public QWidget
+{
+ Q_OBJECT
+
+ private slots:
+ void activateTeam();
+
+ public:
+ TeamShowWidget(tmprop team, QWidget * parent = 0);
+ 
+ private:
+ QHBoxLayout mainLayout;
+ tmprop m_team;
+
+ signals:
+ void teamStatusChanged(tmprop team);
+};
+
+#endif // _TEAMSEL_HELPER_INCLUDED
Binary file QTfrontend/translations/hedgewars_ru.qm has changed
Binary file QTfrontend/translations/hedgewars_ru.ts has changed
--- a/hedgewars/CCHandlers.inc	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/CCHandlers.inc	Thu Jul 20 20:11:32 2006 +0000
@@ -352,7 +352,7 @@
 begin
 if isDeveloperMode then
    begin
-   Pathz[ptThemeCurrent]:= Pathz[ptThemes] + '/' + s;
+   Pathz[ptCurrTheme]:= Pathz[ptThemes] + '/' + s;
    InitStepsFlags:= InitStepsFlags or cifTheme
    end
 end;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/Data/Locale/en.txt	Thu Jul 20 20:11:32 2006 +0000
@@ -0,0 +1,14 @@
+; English locale
+
+00:00=Grenade
+00:01=ClusterBomb
+00:02=Bazooka
+00:03=UFO
+00:04=Shotgun
+00:05=PickHammer
+00:06=Skip
+00:07=Rope
+00:08=Mine
+00:09=DEagle
+00:10=Dynamite
+00:11=BaseballBat
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/Data/Locale/ru.txt	Thu Jul 20 20:11:32 2006 +0000
@@ -0,0 +1,14 @@
+; Перевод сообщений на русский
+
+00:00=Бомба
+00:01=Кластерная бомба
+00:02=Базука
+00:03=НЛО
+00:04=Ружьё
+00:05=Отбойный молоток
+00:06=Пропустить ход
+00:07=Верёвка
+00:08=Мина
+00:09=Дезерт
+00:10=Динамит
+00:11=Бейсбольная бита
\ No newline at end of file
Binary file hedgewars/Data/Themes/steel/Clouds.16.png has changed
Binary file hedgewars/Data/Themes/steel/Clouds.32.png has changed
--- a/hedgewars/GSHandlers.inc	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/GSHandlers.inc	Thu Jul 20 20:11:32 2006 +0000
@@ -429,7 +429,8 @@
 
 begin
 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
-if (HHGear.State and gstHHDriven) = 0 then
+if ((HHGear.State and gstHHDriven) = 0)
+   or (CheckGearDrowning(HHGear)) then
    begin
    DeleteMe;
    exit
--- a/hedgewars/HHHandlers.inc	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/HHHandlers.inc	Thu Jul 20 20:11:32 2006 +0000
@@ -224,7 +224,7 @@
 
 if ((Gear.State and (gstAttacking or gstMoving or gstFalling)) = 0)and(StepTicks = 0) then
    begin
-   if ((Gear.Message and gm_LJump )<>0) then
+   if ((Gear.Message and gm_LJump ) <> 0) then
       begin
       Gear.Message:= 0;
       if not TestCollisionYwithGear(Gear, -1) then
@@ -239,14 +239,14 @@
          exit
          end;
       end;
-   if ((Gear.Message and gm_HJump )<>0) then
+   if ((Gear.Message and gm_HJump ) <> 0) then
       begin
       Gear.Message:= 0;
       if not TestCollisionYwithGear(Gear, -1) then
          begin
          Gear.dY:= -0.20;
          Gear.dX:= 0.0000001 * Sign(Gear.dX);
-         Gear.X:= Gear.X - Sign(Gear.dX)*0.00008; //   %)
+         Gear.X:= Gear.X - Sign(Gear.dX)*0.00008; // shift compensation
          Gear.State:= Gear.State or gstFalling or gstHHJumping;
          exit
          end;
--- a/hedgewars/hwengine.dpr	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/hwengine.dpr	Thu Jul 20 20:11:32 2006 +0000
@@ -55,7 +55,8 @@
   uLand in 'uLand.pas',
   uLandTemplates in 'uLandTemplates.pas',
   uLandObjects in 'uLandObjects.pas',
-  uLandGraphics in 'uLandGraphics.pas';
+  uLandGraphics in 'uLandGraphics.pas',
+  uLocale in 'uLocale.pas';
 
 {$INCLUDE options.inc}
 
@@ -170,7 +171,7 @@
 {$ELSE}
 begin
 {$ENDIF}
-if ParamCount=6 then
+if ParamCount = 7 then
    begin
    val(ParamStr(1), cScreenWidth, c);
    val(ParamStr(2), cScreenHeight, c);
@@ -179,6 +180,7 @@
    val(ParamStr(4), ipcPort, c);
    cFullScreen:= ParamStr(5) = '1';
    isSoundEnabled:= ParamStr(6) = '1';
+   cLocaleFName:= ParamStr(7);
    end else OutError(errmsgShouldntRun, true);
 end;
 
@@ -216,7 +218,10 @@
 InitKbdKeyTable;
 InitIPC;
 WriteLnToConsole(msgGettingConfig);
-SendIPCAndWaitReply('C');        //   
+
+LoadLocale(Pathz[ptLocale] + '/' + cLocaleFName);
+
+SendIPCAndWaitReply('C');        // ask for game config
 InitTeams;
 
 if isSoundEnabled then InitSound;
--- a/hedgewars/options.inc	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/options.inc	Thu Jul 20 20:11:32 2006 +0000
@@ -35,4 +35,5 @@
 {$DEFINE DEBUGFILE}
 { $DEFINE COUNTTICKS}
 { $DEFINE DUMP}
+{ $DEFINE TRACEAIACTIONS}
 
--- a/hedgewars/uAI.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uAI.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -64,7 +64,7 @@
     a, aa: TAmmoType;
 begin
 for i:= 0 to Pred(Targets.Count) do
-    if Targets.ar[i].Score >= 0 then
+    if (Targets.ar[i].Score >= 0) then
        begin
        with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
             a:= Ammo[CurSlot, CurAmmo].AmmoType;
@@ -104,8 +104,8 @@
 end;
 
 procedure Walk(Me: PGear);
-const FallTicksForBranching = cHHRadius * 2 + 8;
-      cBranchStackSize = 8;
+const FallPixForBranching = cHHRadius * 2 + 8;
+      cBranchStackSize = 12;
       
 type TStackEntry = record
                    WastedTicks: Longword;
@@ -118,9 +118,10 @@
            States: array[0..Pred(cBranchStackSize)] of TStackEntry;
            end;
 
-    procedure Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer);
+    function Push(Ticks: Longword; const Actions: TActions; const Me: TGear; Dir: integer): boolean;
     begin
-    if Stack.Count < cBranchStackSize then
+    Result:= (Stack.Count < cBranchStackSize) and (Actions.Count < MAXACTIONS - 5);
+    if Result then
        with Stack.States[Stack.Count] do
             begin
             WastedTicks:= Ticks;
@@ -147,6 +148,8 @@
     ticks, maxticks, steps: Longword;
     BaseRate, BestRate, Rate: integer;
     GoInfo: TGoInfo;
+    CanGo: boolean;
+    AltMe: TGear;
 begin
 Actions.Count:= 0;
 Actions.Pos:= 0;
@@ -156,7 +159,7 @@
 Push(0, Actions, Me^, aia_Left);
 Push(0, Actions, Me^, aia_Right);
 
-if (Me.State and gstAttacked) = 0 then maxticks:= TurnTimeLeft - 5000
+if (Me.State and gstAttacked) = 0 then maxticks:= max(0, integer(TurnTimeLeft) - 10000)
                                   else maxticks:= TurnTimeLeft;
 
 if (Me.State and gstAttacked) = 0 then TestAmmos(Actions, Me);
@@ -171,10 +174,23 @@
     AddAction(Actions, Me.Message, aim_release, 0);
     steps:= 0;
     
-    while HHGo(Me, GoInfo) do
+    while true do
        begin
+       CanGo:= HHGo(Me, @AltMe, GoInfo);
        inc(ticks, GoInfo.Ticks);
        if ticks > maxticks then break;
+       if GoInfo.JumpType = jmpHJump then // hjump support
+          if Push(ticks, Actions, AltMe, Me^.Message) then
+             with Stack.States[Pred(Stack.Count)] do
+                  begin
+                  AddAction(MadeActions, aia_HJump, 0, 305);
+                  AddAction(MadeActions, aia_HJump, 0, 350);
+                  end;
+       if GoInfo.JumpType = jmpLJump then // ljump support
+          if Push(ticks, Actions, AltMe, Me^.Message) then
+             with Stack.States[Pred(Stack.Count)] do
+                  AddAction(MadeActions, aia_LJump, 0, 305);
+       if not CanGo then break;
        inc(steps);
        Actions.actions[Actions.Count - 2].Param:= round(Me.X);
        Rate:= RatePlace(Me);
@@ -187,7 +203,7 @@
        else if Rate < BestRate then break;
        if ((Me.State and gstAttacked) = 0)
            and ((steps mod 4) = 0) then TestAmmos(Actions, Me);
-       if GoInfo.FallTicks >= FallTicksForBranching then
+       if GoInfo.FallPix >= FallPixForBranching then
           Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
        if StopThinking then exit
        end;
@@ -211,7 +227,7 @@
       begin
       Walk(@WalkMe);
       if (StartTicks > GameTicks - 1500) then SDL_Delay(2000);
-      end else OutError('AI: no targets!?')
+      end else
 else begin
       Walk(@WalkMe);
       while (not StopThinking) and (BestActions.Count = 0) do
@@ -235,6 +251,11 @@
 StopThinking:= false;
 ThinkingHH:= Me;
 FillTargets;
+if Targets.Count = 0 then
+   begin
+   OutError('AI: no targets!?');
+   exit
+   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);
--- a/hedgewars/uAIActions.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uAIActions.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -34,6 +34,7 @@
 unit uAIActions;
 interface
 uses uGears;
+{$INCLUDE options.inc}
 const MAXACTIONS = 96;
       aia_none       = 0;
       aia_Left       = 1;
@@ -49,6 +50,8 @@
       aia_LookLeft   = $80000003;
       aia_LookRight  = $80000004;
       aia_AwareExpl  = $80000005;
+      aia_HJump      = $80000006;
+      aia_LJump      = $80000007;
 
       aim_push       = $80000000;
       aim_release    = $80000001;
@@ -81,6 +84,30 @@
 {aia_Down}           'down'
                      );
 
+{$IFDEF TRACEAIACTIONS}
+const SpecActionIdToStr: array[$80000000..$80000006] of string[16] = (
+{aia_Weapon}             'aia_Weapon',
+{aia_WaitX}              'aia_WaitX',
+{aia_WaitY}              'aia_WaitY',
+{aia_LookLeft}           'aia_LookLeft',
+{aia_LookRight}          'aia_LookRight',
+{aia_AwareExpl}          'aia_AwareExpl',
+{aia_HJump}              'aia_HJump',
+{aia_LJump}              'aia_LJump'
+);
+
+procedure DumpAction(Action: TAction; Me: PGear);
+begin
+if (Action.Action and ai_specmask) = 0 then
+   WriteLnToConsole('AI action: '+ActionIdToStr[Action.Action])
+else begin
+   WriteLnToConsole('AI action: '+SpecActionIdToStr[Action.Action]);
+   if Action.Action = aia_WaitX then
+      WriteLnToConsole('AI action Wait X = '+inttostr(Action.Param)+', current X = '+inttostr(round(Me.X)));
+   end
+end;
+{$ENDIF}
+
 procedure AddAction(var Actions: TActions; Action, Param, TimeDelta: Longword; const X: integer = 0; Y: integer = 0);
 begin
 with Actions do
@@ -111,6 +138,9 @@
 with Actions.actions[Actions.Pos] do
      begin
      if Time > GameTicks then exit;
+     {$IFDEF TRACEAIACTIONS}
+     DumpAction(Actions.actions[Actions.Pos], Me);
+     {$ENDIF}
      if (Action and ai_specmask) <> 0 then
         case Action of
            aia_Weapon: SetWeapon(Param);
@@ -129,6 +159,8 @@
                           exit
                           end else ParseCommand('-right');
         aia_AwareExpl: AwareOfExplosion(X, Y, Param);
+            aia_HJump: ParseCommand('hjump');
+            aia_LJump: ParseCommand('ljump');
              end else
         begin
         s:= ActionIdToStr[Action];
--- a/hedgewars/uAIAmmoTests.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uAIAmmoTests.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -195,7 +195,7 @@
   y:= y + vY;
   if TestColl(round(x), round(y), 2) then
      begin
-     Result:= RateShove(Me, round(x), round(y), 25, 25) * 1024;
+     Result:= RateShove(Me, round(x), round(y), 25, 25);
      if Result = 0 then Result:= - Metric(Targ.X, Targ.Y, round(x), round(y)) div 64;
      exit
      end
--- a/hedgewars/uAIMisc.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uAIMisc.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -34,6 +34,7 @@
 unit uAIMisc;
 interface
 uses SDLh, uConsts, uGears;
+{$INCLUDE options.inc}
 
 type TTarget = record
                Point: TPoint;
@@ -43,9 +44,11 @@
                 Count: Longword;
                 ar: array[0..cMaxHHIndex*5] of TTarget;
                 end;
+     TJumpType = (jmpNone, jmpHJump, jmpLJump);
      TGoInfo = record
                Ticks: Longword;
-               FallTicks: Longword;
+               FallPix: Longword;
+               JumpType: TJumpType;
                end;
 
 procedure FillTargets;
@@ -56,7 +59,7 @@
 function TestColl(x, y, r: integer): boolean;
 function RateExplosion(Me: PGear; x, y, r: integer): integer;
 function RateShove(Me: PGear; x, y, r, power: integer): integer;
-function HHGo(Gear: PGear; out GoInfo: TGoInfo): boolean;
+function HHGo(Gear, AltGear: PGear; out GoInfo: TGoInfo): boolean;
 
 var ThinkingHH: PGear;
     Targets: TTargets;
@@ -238,12 +241,88 @@
 Result:= Result * 1024
 end;
 
-function HHGo(Gear: PGear; out GoInfo: TGoInfo): boolean;
+function HHJump(Gear: PGear; JumpType: TJumpType; out GoInfo: TGoInfo): boolean;
+var bX, bY: integer;
+begin
+Result:= false;
+GoInfo.Ticks:= 0;
+GoInfo.FallPix:= 0;
+GoInfo.JumpType:= jmpNone;
+bX:= round(Gear.X);
+bY:= round(Gear.Y);
+case JumpType of
+     jmpNone: exit;
+    jmpHJump: if not TestCollisionYwithGear(Gear, -1) then
+                 begin
+                 Gear.dY:= -0.20;
+                 Gear.dX:= 0.0000001 * Sign(Gear.dX);
+                 Gear.X:= Gear.X - Sign(Gear.dX)*0.00008; // shift compensation
+                 Gear.State:= Gear.State or gstFalling or gstHHJumping;
+                 end else exit;
+    jmpLJump: begin
+              if not TestCollisionYwithGear(Gear, -1) then
+                 if not TestCollisionXwithXYShift(Gear, 0, -2, Sign(Gear.dX)) then Gear.Y:= Gear.Y - 2 else
+                 if not TestCollisionXwithXYShift(Gear, 0, -1, Sign(Gear.dX)) then Gear.Y:= Gear.Y - 1;
+              if not (TestCollisionXwithGear(Gear, Sign(Gear.dX))
+                 or   TestCollisionYwithGear(Gear, -1)) then
+                 begin
+                 Gear.dY:= -0.15;
+                 Gear.dX:= Sign(Gear.dX) * 0.15;
+                 Gear.State:= Gear.State or gstFalling or gstHHJumping
+                 end
+              end
+    end;
+    
+repeat
+if Gear.Y + cHHRadius >= cWaterLine then exit;
+if (Gear.State and gstFalling) <> 0 then
+   begin
+   if (GoInfo.Ticks = 350) then
+      if (abs(Gear.dX) < 0.0000002) and (Gear.dY < -0.02) then
+         begin
+         Gear.dY:= -0.25;
+         Gear.dX:= Sign(Gear.dX) * 0.02
+         end;
+   if TestCollisionXwithGear(Gear, Sign(Gear.dX)) then Gear.dX:= 0.0000001 * Sign(Gear.dX);
+   Gear.X:= Gear.X + Gear.dX;
+   inc(GoInfo.Ticks);
+   Gear.dY:= Gear.dY + cGravity;
+   if Gear.dY > 0.40 then exit;
+   if (Gear.dY < 0)and TestCollisionYwithGear(Gear, -1) then Gear.dY:= 0; 
+   Gear.Y:= Gear.Y + Gear.dY;
+   if (Gear.dY >= 0)and TestCollisionYwithGear(Gear, 1) then
+      begin
+      Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
+      Gear.dY:= 0;
+      case JumpType of
+           jmpHJump: if (bY - Gear.Y > 5) then
+                        begin
+                        Result:= true;
+                        GoInfo.JumpType:= jmpHJump;
+                        inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
+                        end;
+           jmpLJump: if abs(bX - Gear.X) > 30 then
+                        begin
+                        Result:= true;
+                        GoInfo.JumpType:= jmpLJump;
+                        inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
+                        end;
+           end;
+      exit
+      end;
+   end;
+until false;
+end;
+
+function HHGo(Gear, AltGear: PGear; out GoInfo: TGoInfo): boolean;
 var pX, pY: integer;
 begin
 Result:= false;
+AltGear^:= Gear^;
+
 GoInfo.Ticks:= 0;
-GoInfo.FallTicks:= 0;
+GoInfo.FallPix:= 0;
+GoInfo.JumpType:= jmpNone;
 repeat
 pX:= round(Gear.X);
 pY:= round(Gear.Y);
@@ -254,36 +333,23 @@
    Gear.dY:= Gear.dY + cGravity;
    if Gear.dY > 0.40 then
       begin
-      Goinfo.FallTicks:= 0;
+      Goinfo.FallPix:= 0;
+      HHJump(AltGear, jmpLJump, GoInfo);
       exit
       end;
    Gear.Y:= Gear.Y + Gear.dY;
-   if round(Gear.Y) > pY then inc(GoInfo.FallTicks);
+   if round(Gear.Y) > pY then inc(GoInfo.FallPix);
    if TestCollisionYwithGear(Gear, 1) then
       begin
       inc(GoInfo.Ticks, 300);
       Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
       Gear.dY:= 0;
       Result:= true;
+      HHJump(AltGear, jmpLJump, GoInfo);
       exit
       end;
    continue
    end;
-   {if ((Gear.Message and gm_LJump )<>0) then
-      begin
-      Gear.Message:= 0;
-      if not HHTestCollisionYwithGear(Gear, -1) then
-         if not TestCollisionXwithXYShift(Gear, 0, -2, Sign(Gear.dX)) then Gear.Y:= Gear.Y - 2 else
-         if not TestCollisionXwithXYShift(Gear, 0, -1, Sign(Gear.dX)) then Gear.Y:= Gear.Y - 1;
-      if not (TestCollisionXwithGear(Gear, Sign(Gear.dX))
-         or   HHTestCollisionYwithGear(Gear, -1)) then
-         begin
-         Gear.dY:= -0.15;
-         Gear.dX:= Sign(Gear.dX) * 0.15;
-         Gear.State:= Gear.State or gstFalling or gstHHJumping;
-         exit
-         end;
-      end;}
    if (Gear.Message and gm_Left  )<>0 then Gear.dX:= -1.0 else
    if (Gear.Message and gm_Right )<>0 then Gear.dX:=  1.0 else exit;
    if TestCollisionXwithGear(Gear, Sign(Gear.dX)) then
@@ -344,6 +410,7 @@
    exit
    end
 until (pX = round(Gear.X)) and (pY = round(Gear.Y)) and ((Gear.State and gstFalling) = 0);
+HHJump(AltGear, jmpHJump, GoInfo)
 end;
 
 end.
--- a/hedgewars/uConsts.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uConsts.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -33,19 +33,21 @@
 
 unit uConsts;
 interface
-uses SDLh;
+uses SDLh, uLocale;
 {$INCLUDE options.inc}
-type TStuff     = (sHorizont, sSky, sConsoleBG, sPowerBar, sQuestion, sWindBar,
+type TStuff     = (sConsoleBG, sPowerBar, sQuestion, sWindBar,
                    sWindL, sWindR, sRopeNode);
      TGameState = (gsLandGen, gsStart, gsGame, gsConsole, gsExit);
      TGameType  = (gmtLocal, gmtDemo, gmtNet, gmtSave);
-     TPathType  = (ptData, ptGraphics, ptThemes, ptThemeCurrent, ptTeams, ptMaps,
-                   ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts);
+     TPathType  = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps,
+                   ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts,
+                   ptLocale);
      TSprite    = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
                    sprLag, sprArrow, sprGrenade, sprTargetP, sprUFO,
                    sprSmokeTrace, sprRopeHook, sprExplosion50, sprMineOff,
                    sprMineOn, sprCase, sprFAid, sprDynamite, sprPower,
-                   sprClusterBomb, sprClusterParticle, sprFlame);
+                   sprClusterBomb, sprClusterParticle, sprFlame, sprHorizont,
+                   sprSky);
      TGearType  = (gtCloud, gtAmmo_Bomb, gtHedgehog, gtAmmo_Grenade, gtHealthTag,
                    gtGrave, gtUFO, gtShotgunShot, gtActionTimer, gtPickHammer, gtRope,
                    gtSmokeTrace, gtExplosion, gtMine, gtCase, gtDEagleShot, gtDynamite,
@@ -184,10 +186,11 @@
                                          );
 
       Pathz: array[TPathType] of string[ 64] = (
+                                               '',                              // ptNone      
                                                'Data',                          // ptData
                                                'Data/Graphics',                 // ptGraphics
                                                'Data/Themes',                   // ptThemes
-                                               'Data/Themes/avematan',          // ptThemeCurrent
+                                               'Data/Themes/avematan',          // ptCurrTheme
                                                'Data/Teams',                    // ptTeams
                                                'Data/Maps',                     // ptMaps
                                                '',                              // ptMapCurrent
@@ -195,15 +198,14 @@
                                                'Data/Sounds',                   // ptSounds
                                                'Data/Graphics/Graves',          // ptGraves
                                                'Data/Fonts',                    // ptFonts
-                                               'Data/Forts'                     // ptForts
+                                               'Data/Forts',                    // ptForts
+                                               'Data/Locale'                    // ptLocale
                                                );
 
       StuffLoadData: array[TStuff] of record
                                      FileName: String[31];
                                      Path    : TPathType;
                                      end = (
-                                     (FileName: 'horizont'; Path: ptThemeCurrent ),    // sHorizont
-                                     (FileName:      'Sky'; Path: ptThemeCurrent ),    // sSky
                                      (FileName:  'Console'; Path: ptGraphics     ),    // sConsoleBG
                                      (FileName: 'PowerBar'; Path: ptGraphics     ),    // sPowerBar
                                      (FileName: 'thinking'; Path: ptGraphics     ),    // sQuestion
@@ -213,8 +215,6 @@
                                      (FileName: 'RopeNode'; Path: ptGraphics     )     // sRopeNode
                                      );
       StuffPoz: array[TStuff] of TSDL_Rect = (
-                                      (x:   0; y:   0; w: 512; h: 256), // sHorizont
-                                      (x: 512; y:   0; w:  64; h:1024), // sSky
                                       (x: 256; y: 256; w: 256; h: 256), // sConsoleBG
                                       (x: 256; y: 768; w: 256; h:  32), // sPowerBar
                                       (x: 256; y: 512; w:  32; h:  32), // sQuestion
@@ -225,13 +225,14 @@
                                       );
       SpritesData: array[TSprite] of record
                      FileName: String[31];
-                     Path    : TPathType;
+                     Path, AltPath: TPathType;
                      Surface : PSDL_Surface;
                      Width, Height: integer;
                      hasAlpha: boolean;
                      end = (
                      (FileName: 'BlueWater'; Path: ptGraphics; Width: 256; Height: 48; hasAlpha: false),// sprWater
-                     (FileName:    'Clouds'; Path: ptGraphics; Width: 256; Height:128; hasAlpha: false),// sprCloud
+                     (FileName:    'Clouds'; Path: ptCurrTheme;
+                                          AltPath: ptGraphics; Width: 256; Height:128; hasAlpha: false),// sprCloud
                      (FileName:      'Bomb'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false),// sprBomb
                      (FileName: 'BigDigits'; Path: ptGraphics; Width:  32; Height: 32; hasAlpha:  true),// sprBigDigit
                      (FileName:     'Frame'; Path: ptGraphics; Width:   4; Height: 32; hasAlpha:  true),// sprFrame
@@ -251,7 +252,9 @@
                      (FileName:     'Power'; Path: ptGraphics; Width:  32; Height: 32; hasAlpha:  true),// sprPower
                      (FileName:    'ClBomb'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false),// sprClusterBomb
                      (FileName:'ClParticle'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false),// sprClusterParticle
-                     (FileName:     'Flame'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false) // sprFlame
+                     (FileName:     'Flame'; Path: ptGraphics; Width:  16; Height: 16; hasAlpha: false),// sprFlame
+                     (FileName:  'horizont'; Path: ptCurrTheme;Width:   0; Height:  0; hasAlpha: false),// sprHorizont
+                     (FileName:       'Sky'; Path: ptCurrTheme;Width:   0; Height:  0; hasAlpha: false) // sprSky
                      );
       Soundz: array[TSound] of record
                                        FileName: String[31];
@@ -270,12 +273,12 @@
                                        );
 
       Ammoz: array [TAmmoType] of record
-                                  Name: string[32];
+                                  NameId: TAmmoStrId;
                                   Ammo: TAmmo;
                                   Slot: Longword;
                                   TimeAfterTurn: Longword;
                                   end = (
-                                  (Name: 'Grenade';
+                                  (NameId: sidGrenade;
                                    Ammo: (Propz: ammoprop_Timerable or ammoprop_Power;
                                           Count: AMMO_INFINITE;
                                           NumPerTurn: 0;
@@ -283,7 +286,7 @@
                                           AmmoType: amGrenade);
                                    Slot: 1;
                                    TimeAfterTurn: 3000),
-                                  (Name: 'Cluster Bomb';
+                                  (NameId: sidClusterBomb;
                                    Ammo: (Propz: ammoprop_Timerable or ammoprop_Power;
                                           Count: 5;
                                           NumPerTurn: 0;
@@ -291,7 +294,7 @@
                                           AmmoType: amClusterBomb);
                                    Slot: 1;
                                    TimeAfterTurn: 3000),
-                                  (Name: 'Bazooka';
+                                  (NameId: sidBazooka;
                                    Ammo: (Propz: ammoprop_Power;
                                           Count: AMMO_INFINITE;
                                           NumPerTurn: 0;
@@ -299,7 +302,7 @@
                                           AmmoType: amBazooka);
                                    Slot: 0;
                                    TimeAfterTurn: 3000),
-                                  (Name: 'UFO';
+                                  (NameId: sidUFO;
                                    Ammo: (Propz: ammoprop_Power or ammoprop_NeedTarget;
                                           Count: 2;
                                           NumPerTurn: 0;
@@ -307,7 +310,7 @@
                                           AmmoType: amUFO);
                                    Slot: 0;
                                    TimeAfterTurn: 3000),
-                                  (Name: 'Shotgun';
+                                  (NameId: sidShotgun;
                                    Ammo: (Propz: 0;
                                           Count: AMMO_INFINITE;
                                           NumPerTurn: 1;
@@ -315,7 +318,7 @@
                                           AmmoType: amShotgun);
                                    Slot: 2;
                                    TimeAfterTurn: 3000),
-                                  (Name: 'Pneumatic pick';
+                                  (NameId: sidPickHammer;
                                    Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_AttackInFall or ammoprop_AttackInJump;
                                           Count: 2;
                                           NumPerTurn: 0;
@@ -323,7 +326,7 @@
                                           AmmoType: amPickHammer);
                                    Slot: 5;
                                    TimeAfterTurn: 0),
-                                  (Name: 'Skip turn';
+                                  (NameId: sidSkip;
                                    Ammo: (Propz: 0;
                                           Count: AMMO_INFINITE;
                                           NumPerTurn: 0;
@@ -331,7 +334,7 @@
                                           AmmoType: amSkip);
                                    Slot: 7;
                                    TimeAfterTurn: 0),
-                                  (Name: 'Rope';
+                                  (NameId: sidRope;
                                    Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_AttackInFall or ammoprop_AttackInJump;
                                           Count: 5;
                                           NumPerTurn: 0;
@@ -339,7 +342,7 @@
                                           AmmoType: amRope);
                                    Slot: 6;
                                    TimeAfterTurn: 0),
-                                  (Name: 'Mine';
+                                  (NameId: sidMine;
                                    Ammo: (Propz: ammoprop_NoCrosshair;
                                           Count: 2;
                                           NumPerTurn: 0;
@@ -347,7 +350,7 @@
                                           AmmoType: amMine);
                                    Slot: 4;
                                    TimeAfterTurn: 5000),
-                                  (Name: 'Desert Eagle';
+                                  (NameId: sidDEagle;
                                    Ammo: (Propz: 0;
                                           Count: 3;
                                           NumPerTurn: 3;
@@ -355,7 +358,7 @@
                                           AmmoType: amDEagle);
                                    Slot: 2;
                                    TimeAfterTurn: 3000),
-                                   (Name: 'Dynamite';
+                                   (NameId: sidDynamite;
                                     Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInJump or ammoprop_AttackInFall;
                                            Count: 1;
                                            NumPerTurn: 0;
@@ -363,7 +366,7 @@
                                            AmmoType: amDynamite);
                                     Slot: 4;
                                     TimeAfterTurn: 5000),
-                                   (Name: 'Baseball Bat';
+                                   (NameId: sidBaseballBat;
                                     Ammo: (Propz: 0;
                                            Count: 1;
                                            NumPerTurn: 0;
--- a/hedgewars/uGears.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uGears.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -590,7 +590,8 @@
               end;
          end;
       Gear:= Gear.NextGear
-      end
+      end;
+uAIMisc.AwareOfExplosion(0, 0, 0)
 end;
 
 procedure AmmoShove(Ammo: PGear; Damage, Power: integer);
--- a/hedgewars/uLand.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uLand.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -262,7 +262,7 @@
 var tmpsurf: PSDL_Surface;
     r: TSDL_Rect;
 begin
-tmpsurf:= LoadImage(Pathz[ptThemeCurrent] + '/LandTex', false);
+tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', false);
 r.y:= 0;
 while r.y < 1024 do
       begin
@@ -288,7 +288,7 @@
     r, rr: TSDL_Rect;
     x, yd, yu: integer;
 begin
-tmpsurf:= LoadImage(Pathz[ptThemeCurrent] + '/Border', false);
+tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', false);
 for x:= 0 to 2047 do
     begin
     yd:= 1023;
--- a/hedgewars/uLandObjects.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uLandObjects.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -364,7 +364,7 @@
     f: textfile;
     i, ii: integer;
 begin
-s:= Pathz[ptThemeCurrent] + '/' + cThemeCFGFilename;
+s:= Pathz[ptCurrTheme] + '/' + cThemeCFGFilename;
 WriteLnToConsole('Reading objects info...');
 AssignFile(f, s);
 {$I-}
@@ -376,7 +376,7 @@
     Readln(f, s); // filename
     with ThemeObjects.objs[i] do
          begin
-         Surf:= LoadImage(Pathz[ptThemeCurrent] + '/' + s, false);
+         Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + s, false);
          Read(f, Width, Height);
          with inland do Read(f, x, y, w, h);
          Read(f, rectcnt);
@@ -393,7 +393,7 @@
     Readln(f, s); // filename
     with SprayObjects.objs[i] do
          begin
-         Surf:= LoadImage(Pathz[ptThemeCurrent] + '/' + s, false);
+         Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + s, false);
          Width:= Surf.w;
          Height:= Surf.h;
          ReadLn(f, Maxcnt)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uLocale.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -0,0 +1,76 @@
+(*
+ * Hedgewars, a worms-like game
+ * Copyright (c) 2006 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * Distributed under the terms of the BSD-modified licence:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * with the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *)
+
+unit uLocale;
+interface
+type TAmmoStrId = (sidGrenade, sidClusterBomb, sidBazooka, sidUFO, sidShotgun,
+                   sidPickHammer, sidSkip, sidRope, sidMine, sidDEagle,
+                   sidDynamite, sidBaseballBat);
+var trammo: array[TAmmoStrId] of shortstring;
+
+procedure LoadLocale(FileName: string);
+
+implementation
+uses uMisc;
+
+procedure LoadLocale(FileName: string);
+var s: shortstring;
+    f: textfile;
+    a, b, c: integer;
+begin
+{$I-}
+assignfile(f, FileName);
+reset(f);
+TryDo(IOResult = 0, 'Cannot load locale "' + FileName + '"', true);
+while not eof(f) do
+      begin
+      readln(f, s);
+      if Length(s) = 0 then continue;
+      if s[1] = ';' then continue;
+      TryDo(Length(s) > 6, 'Load locale: empty string', true);
+      val(s[1]+s[2], a, c);
+      TryDo(c = 0, 'Load locale: numbers should be two-digit', true);
+      TryDo(s[3] = ':', 'Load locale: ":" expected', true);
+      val(s[4]+s[5], b, c);
+      TryDo(c = 0, 'Load locale: numbers should be two-digit', true);
+      TryDo(s[6] = '=', 'Load locale: "=" expected', true);
+      Delete(s, 1, 6);
+      case a of
+           0: if (b >=0) and (b <= ord(High(TAmmoStrId))) then trammo[TAmmoStrId(b)]:= s;
+           end;
+      end;
+closefile(f)
+{$I+}
+end;
+
+end.
--- a/hedgewars/uMisc.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uMisc.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -78,6 +78,7 @@
 
     cShowFPS      : boolean = true;
     cFullScreen   : boolean = true;
+    cLocaleFName  : shortstring = 'en.txt';
 
 const
     cMaxPower     = 1500;
--- a/hedgewars/uStore.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uStore.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -51,7 +51,7 @@
 procedure RenderHealth(var Hedgehog: THedgehog);
 function  RenderString(var s: shortstring; Color, Pos: integer): TSDL_Rect;
 procedure AddProgress;
-function  LoadImage(filename: string; hasAlpha: boolean): PSDL_Surface;
+function  LoadImage(filename: string; hasAlpha: boolean; const critical: boolean = true): PSDL_Surface;
 
 var PixelFormat: PSDL_PixelFormat;
  SDLPrimSurface: PSDL_Surface;
@@ -248,24 +248,24 @@
     procedure GetSkyColor;
     var p: Longword;
     begin
-    if SDL_MustLock(StoreSurface) then
-       SDLTry(SDL_LockSurface(StoreSurface) >= 0, true);
-    p:= Longword(StoreSurface.pixels) + Word(StuffPoz[sSky].x) * StoreSurface.format.BytesPerPixel;
-    case StoreSurface.format.BytesPerPixel of
+    if SDL_MustLock(SpritesData[sprSky].Surface) then
+       SDLTry(SDL_LockSurface(SpritesData[sprSky].Surface) >= 0, true);
+    p:= Longword(SpritesData[sprSky].Surface.pixels);
+    case SpritesData[sprSky].Surface.format.BytesPerPixel of
          1: cSkyColor:= PByte(p)^;
          2: cSkyColor:= PWord(p)^;
          3: cSkyColor:= (PByte(p)^) or (PByte(p + 1)^ shl 8) or (PByte(p + 2)^ shl 16);
          4: cSkyColor:= PLongword(p)^;
          end;
-    if SDL_MustLock(StoreSurface) then
-       SDL_UnlockSurface(StoreSurface)
+    if SDL_MustLock(SpritesData[sprSky].Surface) then
+       SDL_UnlockSurface(SpritesData[sprSky].Surface)
     end;
 
     procedure GetExplosionBorderColor;
     var f: textfile;
         c: integer;
     begin
-    s:= Pathz[ptThemeCurrent] + '/' + cThemeCFGFilename;
+    s:= Pathz[ptCurrTheme] + '/' + cThemeCFGFilename;
     WriteToConsole(msgLoading + s + ' ');
     AssignFile(f, s);
     {$I-}
@@ -319,12 +319,22 @@
 MakeCrossHairs;
 LoadGraves;
 
-GetSkyColor;
-
 AddProgress;
 for ii:= Low(TSprite) to High(TSprite) do
     with SpritesData[ii] do
-         Surface:= LoadImage(Pathz[Path] + '/' + FileName, hasAlpha);
+         begin
+         if AltPath = ptNone then
+            Surface:= LoadImage(Pathz[Path] + '/' + FileName, hasAlpha)
+         else begin
+            Surface:= LoadImage(Pathz[Path] + '/' + FileName, hasAlpha, false);
+            if Surface = nil then
+               Surface:= LoadImage(Pathz[AltPath] + '/' + FileName, hasAlpha)
+            end;
+         if Width = 0 then Width:= Surface.w;
+         if Height = 0 then Height:= Surface.h
+         end;
+
+GetSkyColor;
 
 AddProgress;
 tmpsurf:= LoadImage(Pathz[ptGraphics] + '/' + cHHFileName, false);
@@ -484,21 +494,25 @@
    end;
 end;
 
-function  LoadImage(filename: string; hasAlpha: boolean): PSDL_Surface;
+function  LoadImage(filename: string; hasAlpha: boolean; const critical: boolean = true): PSDL_Surface;
 var tmpsurf: PSDL_Surface;
 begin
 WriteToConsole(msgLoading + filename + '... ');
 tmpsurf:= IMG_Load(PChar(filename + '.' + cBitsStr + '.png'));
 if tmpsurf = nil then
    tmpsurf:= IMG_Load(PChar(filename + '.png'));
-TryDo(tmpsurf <> nil, msgFailed, true);
+
+if tmpsurf = nil then
+   if critical then OutError(msgFailed, true)
+      else begin
+      WriteLnToConsole(msgFailed);
+      Result:= nil;
+      exit
+      end;
+      
 TryDo(SDL_SetColorKey(tmpsurf, SDL_SRCCOLORKEY or SDL_RLEACCEL, 0) = 0, errmsgTransparentSet, true);
-if cFullScreen then
-   begin
-   if hasAlpha then Result:= SDL_DisplayFormatAlpha(tmpsurf)
-               else Result:= SDL_DisplayFormat(tmpsurf);
-   SDL_FreeSurface(tmpsurf);
-   end else Result:= tmpsurf;
+if hasAlpha then Result:= SDL_DisplayFormatAlpha(tmpsurf)
+            else Result:= SDL_DisplayFormat(tmpsurf);
 WriteLnToConsole(msgOK)
 end;
 
--- a/hedgewars/uTeams.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uTeams.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -83,7 +83,7 @@
 procedure RestoreTeamsFromSave;
 
 implementation
-uses uMisc, uStore, uWorld, uIO, uAI;
+uses uMisc, uStore, uWorld, uIO, uAI, uLocale;
 const MaxTeamHealth: integer = 0;
 
 procedure FreeTeamsList; forward;
@@ -148,7 +148,7 @@
 function AddTeam: PTeam;
 begin
 New(Result);
-TryDo(Result <> nil, 'AddTean: Result = nil', true);
+TryDo(Result <> nil, 'AddTeam: Result = nil', true);
 FillChar(Result^, sizeof(TTeam), 0);
 Result.AttackBar:= 2;
 if TeamsList = nil then TeamsList:= Result
@@ -234,7 +234,7 @@
 
 with Ammo[CurSlot, CurAmmo] do
      begin
-     s:= Ammoz[AmmoType].Name;
+     s:= trammo[Ammoz[AmmoType].NameId];
      if Count <> AMMO_INFINITE then
         s:= s + ' (' + IntToStr(Count) + ')';
      if (Propz and ammoprop_Timerable) <> 0 then
--- a/hedgewars/uWorld.pas	Sun Jul 16 08:13:51 2006 +0000
+++ b/hedgewars/uWorld.pas	Thu Jul 20 20:11:32 2006 +0000
@@ -83,6 +83,19 @@
     r: TSDL_Rect;
     team: PTeam;
     tdx, tdy: real;
+
+    procedure DrawRepeated(spr: TSprite);
+    var i, w: integer;
+    begin
+    w:= SpritesData[spr].Width;
+    i:= WorldDx mod w;
+    if i > 0 then dec(i, w);
+    repeat
+      DrawSprite(spr, i, WorldDy + 1024 - SpritesData[spr].Height, 0, Surface);
+      inc(i, w)
+    until i > cScreenWidth
+    end;
+
 begin
 // Sky
 inc(RealTicks, Lag);
@@ -96,11 +109,8 @@
    SDL_FillRect(Surface, @r, cSkyColor)
    end;
 // background
-for i:= 0 to (cScreenWidth shr 6) do
-    DrawGear(sSky, i*64, WorldDy, Surface);
-
-for i:= -1 to 3 do
-    DrawGear(sHorizont, i * 512 + (((WorldDx * 3) div 5) and $1FF), cWaterLine - 256 + WorldDy, Surface);
+DrawRepeated(sprSky);
+DrawRepeated(sprHorizont);
 
 // Waves
 {$WARNINGS OFF}