merge
authorStepan777 <stepik-777@mail.ru>
Mon, 06 Aug 2012 00:40:26 +0400
changeset 7503 deaeac102355
parent 7447 01111960a48d (current diff)
parent 7498 86984f6fa1b9 (diff)
child 7507 3032a5739fe1
merge
hedgewars/hwengine.pas
hedgewars/uCommandHandlers.pas
hedgewars/uConsts.pas
hedgewars/uGearsHedgehog.pas
hedgewars/uStore.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
hedgewars/uWorld.pas
--- a/QTfrontend/ui/page/pageeditteam.cpp	Thu Jul 26 21:58:25 2012 +0400
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Mon Aug 06 00:40:26 2012 +0400
@@ -289,6 +289,9 @@
     int idx = list.indexOf("cpu.png");
     if (idx >= 0)
         list.removeAt(idx);
+    idx = list.indexOf("cpu_plain.png");
+    if (idx >= 0)
+        list.removeAt(idx);
     idx = list.indexOf("hedgewars.png");
     if (idx >= 0)
         list.removeAt(idx);
--- a/gameServer/Actions.hs	Thu Jul 26 21:58:25 2012 +0400
+++ b/gameServer/Actions.hs	Mon Aug 06 00:40:26 2012 +0400
@@ -146,9 +146,14 @@
     io $
         infoM "Clients" (show ci ++ " quits: " ++ B.unpack msg)
 
-    processAction $ AnswerClients [chan] ["BYE", msg]
     when loggedIn $ processAction $ AnswerClients clientsChans ["LOBBY:LEFT", clNick, msg]
 
+    mapM processAction
+        [
+        AnswerClients [chan] ["BYE", msg]
+        , ModifyClient (\c -> c{logonPassed = False}) -- this will effectively hide client from others while he isn't deleted from list
+        ]
+
     s <- get
     put $! s{removedClients = ci `Set.insert` removedClients s}
 
@@ -418,11 +423,22 @@
 processAction JoinLobby = do
     chan <- client's sendChan
     clientNick <- client's nick
-    (lobbyNicks, clientsChans) <- liftM (unzip . Prelude.map (nick &&& sendChan) . Prelude.filter logonPassed) $! allClientsS
-    mapM_ processAction $
-        AnswerClients clientsChans ["LOBBY:JOINED", clientNick]
-        : AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks)
-        : [ModifyClient (\cl -> cl{logonPassed = True}), SendServerMessage]
+    isAuthenticated <- liftM (not . B.null) $ client's webPassword
+    isAdmin <- client's isAdministrator
+    loggedInClients <- liftM (Prelude.filter logonPassed) $! allClientsS
+    let (lobbyNicks, clientsChans) = unzip . L.map (nick &&& sendChan) $ loggedInClients
+    let authenticatedNicks = L.map nick . L.filter (not . B.null . webPassword) $ loggedInClients
+    let adminsNicks = L.map nick . L.filter isAdministrator $ loggedInClients
+    let clFlags = B.concat . L.concat $ [["u" | isAuthenticated], ["a" | isAdmin]]
+    mapM_ processAction . concat $ [
+        [AnswerClients clientsChans ["LOBBY:JOINED", clientNick]]
+        , [AnswerClients [chan] ("LOBBY:JOINED" : clientNick : lobbyNicks)]
+        , [AnswerClients [chan] ("CLIENT_FLAGS" : "+u" : authenticatedNicks) | not $ null authenticatedNicks]
+        , [AnswerClients [chan] ("CLIENT_FLAGS" : "+a" : adminsNicks) | not $ null adminsNicks]
+        , [AnswerClients (chan : clientsChans) ["CLIENT_FLAGS",  B.concat["+" , clFlags], clientNick] | not $ B.null clFlags]
+        , [ModifyClient (\cl -> cl{logonPassed = True})]
+        , [SendServerMessage]
+        ]
 
 
 processAction (KickClient kickId) = do
@@ -522,9 +538,11 @@
     where
         kickTimeouted rnc ci = do
             pq <- io $ client'sM rnc pingsQueue ci
-            when (pq > 0) $
+            when (pq > 0) $ do
                 withStateT (\as -> as{clientIndex = Just ci}) $
                     processAction (ByeClient "Ping timeout")
+                when (pq > 1) $
+                    processAction $ DeleteClient ci -- smth went wrong with client io threads, issue DeleteClient here
 
 
 processAction StatsAction = do
--- a/hedgewars/GSHandlers.inc	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/GSHandlers.inc	Mon Aug 06 00:40:26 2012 +0400
@@ -610,11 +610,10 @@
     // move back to cloud layer
         if yy > cWaterLine then
             move:= true
-        else if ((yy and LAND_HEIGHT_MASK) <> 0)
-        or (xx > LAND_WIDTH + 512) or (xx < -512) then
+        else if (xx > snowRight) or (xx < snowLeft) then
             move:=true
         // Solid pixel encountered
-        else if ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then
+        else if ((yy and LAND_HEIGHT_MASK) = 0) and ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then
             begin
             lf:= Land[yy, xx] and (lfObject or lfBasic or lfIndestructible);
             // If there's room below keep falling
@@ -724,8 +723,8 @@
         exit
         end;
     Gear^.Pos:= 0;
-    Gear^.X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512);
-    Gear^.Y:= int2hwFloat(750+(GetRandom(50)-25));
+    Gear^.X:= int2hwFloat(GetRandom(snowRight-snowLeft)+snowLeft);
+    Gear^.Y:= int2hwFloat(LAND_HEIGHT-1300+(GetRandom(50)-25));
     Gear^.State:= Gear^.State or gstInvisible;
     end
 end;
@@ -3685,10 +3684,6 @@
 
     Gear^.X := HHGear^.X;
     Gear^.Y := HHGear^.Y;
-    // For some reason I need to reapply followgear here, something else grabs it otherwise.
-    // This is probably not needed anymore
-    if not CurrentTeam^.ExtDriven then
-        FollowGear := HHGear;
 
     if not isUnderWater and hasBorder and ((HHGear^.X < _0)
     or (hwRound(HHGear^.X) > LAND_WIDTH)) then
--- a/hedgewars/hwengine.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/hwengine.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -59,6 +59,9 @@
         gsLandGen:
             begin
             GenMap;
+            uLandTexture.initModule;
+            UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); 
+            uAILandMarks.initModule;
             ParseCommand('sendlanddigest', true);
             GameState:= gsStart;
             end;
@@ -462,7 +465,6 @@
         uAI.initModule;
         //uAIActions does not need initialization
         //uAIAmmoTests does not need initialization
-        uAILandMarks.initModule;
         uAIMisc.initModule;
         uAmmos.initModule;
         uChat.initModule;
@@ -474,7 +476,6 @@
         //uLandGraphics does not need initialization
         //uLandObjects does not need initialization
         //uLandTemplates does not need initialization
-        uLandTexture.initModule;
         //uLocale does not need initialization
         uRandom.initModule;
         uScript.initModule;
--- a/hedgewars/uAI.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uAI.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -178,9 +178,12 @@
                         begin
                         AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0);
                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
-                                                
-                        AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
-                        AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
+                         
+                        if abs(ap.Angle) > 32 then
+                           begin
+                           AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
+                           AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
+                           end;
                         
                         AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0);
                         AddAction(BestActions, aia_attack, aim_push, 1, 0, 0);
@@ -274,7 +277,8 @@
                 break;
 
             if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
-                if Push(ticks, Actions, AltMe, Me^.Message) then
+                // check if we could go backwards and maybe ljump over a gap after this hjump
+                if Push(ticks, Actions, AltMe, Me^.Message xor 3) then
                     begin
                     with Stack.States[Pred(Stack.Count)] do
                         begin
@@ -291,9 +295,8 @@
                         else
                             AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
                         end;
-                    
-                    // check if we could go backwards and maybe ljump over a gap after this hjump
-                    Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message xor 3)
+                    // but first check walking forward
+                    Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message)
                     end;
             if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
                 begin
--- a/hedgewars/uAIAmmoTests.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uAIAmmoTests.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -47,6 +47,7 @@
 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 TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -84,7 +85,7 @@
             //(proc: @TestTeleport;    flags: amtest_OnTurn), // amTeleport
             (proc: nil;              flags: 0), // amSwitch
             (proc: @TestMortar;      flags: 0), // amMortar
-            (proc: nil;              flags: 0), // amKamikaze
+            (proc: @TestKamikaze;    flags: 0), // amKamikaze
             (proc: @TestCake;        flags: amtest_OnTurn or amtest_NoTarget), // amCake
             (proc: nil;              flags: 0), // amSeduction
             (proc: @TestWatermelon;  flags: 0), // amWatermelon
@@ -167,7 +168,7 @@
         
         EX:= trunc(x);
         EY:= trunc(y);
-        if Me^.Hedgehog^.BotLevel = 1 then
+        if Level = 1 then
             value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
         else value:= RateExplosion(Me, EX, EY, 101);
         if value = 0 then
@@ -330,7 +331,7 @@
     EX:= trunc(x);
     EY:= trunc(y);
     if t < 50 then 
-        if Me^.Hedgehog^.BotLevel = 1 then
+        if Level = 1 then
             Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
         else Score:= RateExplosion(Me, EX, EY, 101)
     else 
@@ -361,12 +362,12 @@
     t: LongInt;
 begin
 valueResult:= BadTurn;
-TestTime:= 0;
+TestTime:= 500;
 ap.ExplR:= 0;
 meX:= hwFloat2Float(Me^.X);
 meY:= hwFloat2Float(Me^.Y);
 repeat
-    inc(TestTime, 1000);
+    inc(TestTime, 900);
     // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
     if meX<Targ.X then
         Vx:= ((Targ.X+10) - meX) / (TestTime + tDelta)
@@ -398,14 +399,14 @@
         begin
         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
-        ap.Time:= TestTime;
+        ap.Time:= TestTime div 1000 * 1000;
         ap.ExplR:= 90;
         ap.ExplX:= EX;
         ap.ExplY:= EY;
         valueResult:= Score
         end;
      end
-until (TestTime = 4000);
+until (TestTime = 4100);
 TestClusterBomb:= valueResult
 end;
 
@@ -418,12 +419,12 @@
     t: LongInt;
 begin
 valueResult:= BadTurn;
-TestTime:= 0;
+TestTime:= 500;
 ap.ExplR:= 0;
 meX:= hwFloat2Float(Me^.X);
 meY:= hwFloat2Float(Me^.Y);
 repeat
-    inc(TestTime, 1000);
+    inc(TestTime, 900);
     Vx:= (Targ.X - meX) / (TestTime + tDelta);
     Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Y-50) - meY) / (TestTime + tDelta);
     r:= sqr(Vx)+sqr(Vy);
@@ -452,14 +453,14 @@
             begin
             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
             ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
-            ap.Time:= TestTime;
+            ap.Time:= TestTime div 1000 * 1000;
             ap.ExplR:= 300;
             ap.ExplX:= EX;
             ap.ExplY:= EY;
             valueResult:= Score
             end;
         end
-until (TestTime = 4000);
+until (TestTime = 4100);
 TestWatermelon:= valueResult
 end;
 
@@ -600,19 +601,22 @@
     d: Longword;
     fallDmg, valueResult: LongInt;
 begin
-if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn);
+if Level > 3 then exit(BadTurn);
 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 Level:= Level; // avoid compiler hint
 ap.ExplR:= 0;
 ap.Time:= 0;
 ap.Power:= 1;
+
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
+
 if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then
     begin
     TestDesertEagle:= BadTurn;
     exit(BadTurn);
     end;
+
 t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
 Vx:= (Targ.X - x) * t;
 Vy:= (Targ.Y - y) * t;
@@ -650,7 +654,7 @@
     d: Longword;
     fallDmg, valueResult: LongInt;
 begin
-if Me^.Hedgehog^.BotLevel > 3 then exit(BadTurn);
+if Level > 3 then exit(BadTurn);
 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 Level:= Level; // avoid compiler hint
 ap.ExplR:= 0;
@@ -700,9 +704,9 @@
     x, y, trackFall: LongInt;
     dx, dy: real;
 begin
-    if Me^.Hedgehog^.BotLevel < 3 then trackFall:= afTrackFall
+    if Level < 3 then trackFall:= afTrackFall
     else trackFall:= 0;
-    Level:= Level; // avoid compiler hint
+
     ap.ExplR:= 0;
     ap.Time:= 0;
     ap.Power:= 1;
@@ -749,9 +753,9 @@
 var valueResult, v1, v2, i: LongInt;
     x, y, trackFall: LongInt;
 begin
-    if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
+    if Level = 1 then trackFall:= afTrackFall
     else trackFall:= 0;
-    Level:= Level; // avoid compiler hint
+
     ap.ExplR:= 0;
     ap.Time:= 0;
     ap.Power:= 1;
@@ -805,9 +809,9 @@
 var valueResult, v1, v2: LongInt;
     x, y, trackFall: LongInt;
 begin
-    if Me^.Hedgehog^.BotLevel = 1 then trackFall:= afTrackFall
+    if Level = 1 then trackFall:= afTrackFall
     else trackFall:= 0;
-    Level:= Level; // avoid compiler hint
+
     ap.ExplR:= 0;
     ap.Time:= 0;
     ap.Power:= 1;
@@ -822,7 +826,7 @@
             , 30, 30, 25
             , -1, -0.8, trackFall or afSetSkip);
     v1:= v1 +
-        RateShove(Me, x, y
+        RateShove(Me, x - 2, y
             , 30, 30, 25
             , -1, -0.8, trackFall);
     // now try opposite direction
@@ -830,7 +834,7 @@
             , 30, 30, 25
             , 1, -0.8, trackFall or afSetSkip);
     v2:= v2 +
-        RateShove(Me, x, y
+        RateShove(Me, x + 2, y
             , 30, 30, 25
             , 1, -0.8, trackFall);
 
@@ -854,6 +858,90 @@
     TestWhip:= valueResult;
 end;
 
+function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+const step = 8;
+var valueResult, i, v, tx: LongInt;
+    trackFall: LongInt;
+    t, d, x, y, dx, dy, cx: real;
+begin
+    ap.ExplR:= 0;
+    ap.Time:= 0;
+    ap.Power:= 1;
+
+    if Level = 1 then 
+        trackFall:= afTrackFall
+    else if Level = 2 then
+        trackFall:= 0
+    else
+        exit(BadTurn);
+        
+    valueResult:= 0;
+    v:= 0;
+
+    x:= hwFloat2Float(Me^.X);
+    y:= hwFloat2Float(Me^.Y);
+    d:= sqrt(sqr(Targ.X - x) + sqr(Targ.Y - y));
+    if d < 10 then
+        begin
+        dx:= 0;
+        dy:= 8;
+        ap.Angle:= 2048
+        end
+    else
+        begin
+        t:= step / d;
+        dx:= (Targ.X - x) * t;
+        dy:= (Targ.Y - y) * t;
+
+        ap.Angle:= DxDy2AttackAnglef(dx, -dy)
+        end;
+    
+    if dx >= 0 then cx:= 0.45 else cx:= -0.45;
+
+    for i:= 0 to 512 div step - 2 do
+        begin
+        valueResult:= valueResult + 
+            RateShove(Me, trunc(x), trunc(y)
+                , 30, 30, 25
+                , cx, -0.9, trackFall or afSetSkip);
+                
+        x:= x + dx;
+        y:= y + dy;
+        end;
+    if dx = 0 then
+        begin
+        x:= hwFloat2Float(Me^.X);
+        y:= hwFloat2Float(Me^.Y);
+        tx:= trunc(x);
+        v:= RateShove(Me, tx, trunc(y)
+                , 30, 30, 25
+                , -cx, -0.9, trackFall);
+        for i:= 1 to 512 div step - 2 do
+            begin
+            y:= y + dy;
+            v:= v + 
+                RateShove(Me, tx, trunc(y)
+                    , 30, 30, 25
+                    , -cx, -0.9, trackFall or afSetSkip);
+            end
+        end;
+    if v > valueResult then
+        begin
+        ap.Angle:= -2048;
+        valueResult:= v
+        end;
+        
+    v:= RateShove(Me, trunc(x), trunc(y)
+            , 30, 30, 25
+            , cx, -0.9, trackFall);
+    valueResult:= valueResult + v - KillScore * friendlyfactor div 100 * 1024;
+    
+    if v < 65536 then
+        inc(valueResult, RateExplosion(Me, trunc(x), trunc(y), 30));
+
+    TestKamikaze:= valueResult;
+end;
+
 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 var rate: LongInt;
 begin
--- a/hedgewars/uAILandMarks.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uAILandMarks.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -1,71 +1,71 @@
-unit uAILandMarks;
-
-interface
-const markWasHere = $01;
-
-procedure addMark(X, Y: LongInt; mark: byte);
-function  checkMark(X, Y: LongInt; mark: byte) : boolean;
-procedure clearAllMarks;
-procedure clearMarks(mark: byte);
-
-procedure initModule;
-procedure freeModule;
-
-implementation
-uses uVariables;
-
-const gr = 2;
-
-var marks: array of array of byte;
-    WIDTH, HEIGHT: Longword;
-
-procedure addMark(X, Y: LongInt; mark: byte);
-begin
-    if((X and LAND_WIDTH_MASK) = 0) and ((Y and LAND_HEIGHT_MASK) = 0) then
-        begin
-        X:= X shr gr;
-        Y:= Y shr gr;
-        marks[Y, X]:= marks[Y, X] or mark
-        end
-end;
-
-function  checkMark(X, Y: LongInt; mark: byte) : boolean;
-begin
-    checkMark:= ((X and LAND_WIDTH_MASK) = 0) 
-        and ((Y and LAND_HEIGHT_MASK) = 0) 
-        and ((marks[Y shr gr, X shr gr] and mark) <> 0)
-end;
-
-procedure clearAllMarks;
-var 
-    Y, X: Longword;
-begin
-    for Y:= 0 to Pred(HEIGHT) do
-        for X:= 0 to Pred(WIDTH) do
-            marks[Y, X]:= 0
-end;
-
-procedure clearMarks(mark: byte);
-var 
-    Y, X: Longword;
-begin
-    for Y:= 0 to Pred(HEIGHT) do
-        for X:= 0 to Pred(WIDTH) do
-            marks[Y, X]:= marks[Y, X] and (not mark)
-end;
-
-
-procedure initModule;
-begin
-    WIDTH:= LAND_WIDTH shr gr;
-    HEIGHT:= LAND_HEIGHT shr gr;
-    
-    SetLength(marks, HEIGHT, WIDTH);
-end;
-
-procedure freeModule;
-begin
-    SetLength(marks, 0, 0);
-end;
-
-end.
+unit uAILandMarks;
+
+interface
+const markWasHere = $01;
+
+procedure addMark(X, Y: LongInt; mark: byte);
+function  checkMark(X, Y: LongInt; mark: byte) : boolean;
+procedure clearAllMarks;
+procedure clearMarks(mark: byte);
+
+procedure initModule;
+procedure freeModule;
+
+implementation
+uses uVariables;
+
+const gr = 2;
+
+var marks: array of array of byte;
+    WIDTH, HEIGHT: Longword;
+
+procedure addMark(X, Y: LongInt; mark: byte);
+begin
+    if((X and LAND_WIDTH_MASK) = 0) and ((Y and LAND_HEIGHT_MASK) = 0) then
+        begin
+        X:= X shr gr;
+        Y:= Y shr gr;
+        marks[Y, X]:= marks[Y, X] or mark
+        end
+end;
+
+function  checkMark(X, Y: LongInt; mark: byte) : boolean;
+begin
+    checkMark:= ((X and LAND_WIDTH_MASK) = 0) 
+        and ((Y and LAND_HEIGHT_MASK) = 0) 
+        and ((marks[Y shr gr, X shr gr] and mark) <> 0)
+end;
+
+procedure clearAllMarks;
+var 
+    Y, X: Longword;
+begin
+    for Y:= 0 to Pred(HEIGHT) do
+        for X:= 0 to Pred(WIDTH) do
+            marks[Y, X]:= 0
+end;
+
+procedure clearMarks(mark: byte);
+var 
+    Y, X: Longword;
+begin
+    for Y:= 0 to Pred(HEIGHT) do
+        for X:= 0 to Pred(WIDTH) do
+            marks[Y, X]:= marks[Y, X] and (not mark)
+end;
+
+
+procedure initModule;
+begin
+    WIDTH:= LAND_WIDTH shr gr;
+    HEIGHT:= LAND_HEIGHT shr gr;
+    
+    SetLength(marks, HEIGHT, WIDTH);
+end;
+
+procedure freeModule;
+begin
+    SetLength(marks, 0, 0);
+end;
+
+end.
--- a/hedgewars/uAIMisc.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uAIMisc.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -86,12 +86,13 @@
         ar: array[0..Pred(MAXBONUS div 8)] of TBonus;  // don't use too many
         end;
 
+const KillScore = 200;
+var friendlyfactor: LongInt = 300;
+       
 implementation
 uses uCollisions, uVariables, uUtils, uDebug, uLandTexture;
 
-const KillScore = 200;
-
-var friendlyfactor: LongInt = 300;
+var 
     KnownExplosion: record
         X, Y, Radius: LongInt
         end = (X: 0; Y: 0; Radius: 0);
--- a/hedgewars/uCollisions.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uCollisions.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -82,7 +82,7 @@
     X:= hwRound(Gear^.X);
     Y:= hwRound(Gear^.Y);
     Radius:= Gear^.Radius;
-    ChangeRoundInLand(X, Y, Radius - 1, true, Gear = CurrentHedgehog^.Gear);
+    ChangeRoundInLand(X, Y, Radius - 1, true, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase));
     cGear:= Gear
     end;
 Gear^.CollisionIndex:= Count;
@@ -103,7 +103,7 @@
 if Gear^.CollisionIndex >= 0 then
     begin
     with cinfos[Gear^.CollisionIndex] do
-        ChangeRoundInLand(X, Y, Radius - 1, false, Gear = CurrentHedgehog^.Gear);
+        ChangeRoundInLand(X, Y, Radius - 1, false, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase));
     cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)];
     cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex;
     Gear^.CollisionIndex:= -1;
@@ -138,7 +138,7 @@
 var x, y, i: LongInt;
 begin
 // Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap
-if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and
+if (Gear^.CollisionMask = $FF7F) and (Gear^.Kind <> gtHedgehog) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and
     ((hwRound(Gear^.Hedgehog^.Gear^.X) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.X) - Gear^.Radius) or
      (hwRound(Gear^.Hedgehog^.Gear^.X) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.X) + Gear^.Radius)) then
     Gear^.CollisionMask:= $FFFF;
@@ -168,7 +168,7 @@
 var x, y, i: LongInt;
 begin
 // Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap
-if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and
+if (Gear^.CollisionMask = $FF7F) and (Gear^.Kind <> gtHedgehog) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and
     ((hwRound(Gear^.Hedgehog^.Gear^.Y) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.Y) - Gear^.Radius) or
      (hwRound(Gear^.Hedgehog^.Gear^.Y) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.Y) + Gear^.Radius)) then
     Gear^.CollisionMask:= $FFFF;
--- a/hedgewars/uCommandHandlers.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uCommandHandlers.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -626,13 +626,14 @@
 if CheckNoTeamOrHH or isPaused then
     exit;
 
-if FollowGear <> nil then
+if autoCameraOn then
     begin
+    FollowGear:= nil;
     AddCaption('Auto Camera Off', $CCCCCC, capgrpVolume);
     autoCameraOn:= false
     end
-    else
-        begin
+else
+    begin
     AddCaption('Auto Camera On', $CCCCCC, capgrpVolume);
     bShowFinger:= true;
     if not CurrentHedgehog^.Unplaced then
--- a/hedgewars/uConsts.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uConsts.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -166,7 +166,7 @@
     cMinZoomLevel = 3.5;
     cZoomDelta = 0.20;
 {$ELSE}
-    cMaxZoomLevel = 1.0;
+    cMaxZoomLevel = 0.25;
     cMinZoomLevel = 3.0;
     cZoomDelta = 0.25;
 {$ENDIF}
--- a/hedgewars/uGears.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uGears.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -77,6 +77,7 @@
     stAfterDelay, stChWin, stWater, stChWin2, stHealth,
     stSpawn, stNTurn);
     upd: Longword;
+    snowLeft,snowRight: LongInt;
     //SDMusic: shortstring;
 
 // For better maintainability the step handlers of gears are stored in
@@ -642,9 +643,12 @@
     AddGear(rx, ry, gtGenericFaller, gstInvisible, rdx, rdy, $FFFFFFFF);
     end;
 
+snowRight:= max(LAND_WIDTH,4096)+512;
+snowLeft:= -(snowRight-LAND_WIDTH);
+
 if not hasBorder and ((Theme = 'Snow') or (Theme = 'Christmas')) then
-    for i:= 0 to Pred(vobCount*2) do
-        AddGear(GetRandom(LAND_WIDTH+1024)-512, LAND_HEIGHT - GetRandom(LAND_HEIGHT div 2), gtFlake, 0, _0, _0, 0);
+    for i:= vobCount * max(LAND_WIDTH,4096) div 2048 downto 1 do
+        AddGear(GetRandom(snowRight-snowLeft)+snowLeft, LAND_HEIGHT-1300+GetRandom(750), gtFlake, 0, _0, _0, 0);
 end;
 
 
--- a/hedgewars/uGearsHedgehog.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uGearsHedgehog.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -455,11 +455,13 @@
 procedure AfterAttack;
 var s: shortstring;
     a: TAmmoType;
+    HHGear: PGear;
 begin
-with CurrentHedgehog^.Gear^, CurrentHedgehog^ do
+with CurrentHedgehog^ do
     begin
+    HHGear:= Gear;
     a:= CurAmmoType;
-    State:= State and (not gstAttacking);
+    if HHGear <> nil then HHGear^.State:= HHGear^.State and (not gstAttacking);
     if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then
         begin
         Inc(MultiShootAttacks);
@@ -484,8 +486,8 @@
                     TagTurnTimeLeft:= TurnTimeLeft;
                 TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
                 end;
-            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) then
-                State:= State or gstAttacked;
+            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then 
+                HHGear^.State:= HHGear^.State or gstAttacked;
             if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then
                 ApplyAmmoChanges(CurrentHedgehog^)
             end;
--- a/hedgewars/uGearsUtils.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uGearsUtils.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -510,7 +510,7 @@
     count: LongInt = 0;
 begin
     if (y and LAND_HEIGHT_MASK) = 0 then
-        for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do
+        for i:= min(x + r, LAND_WIDTH - 4) downto max(x - r, 0) do 
             if Land[y, i] and mask <> 0 then
             begin
                 inc(count);
--- a/hedgewars/uLand.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uLand.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -20,7 +20,7 @@
 
 unit uLand;
 interface
-uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes;
+uses SDLh, uLandTemplates, uFloat, uConsts, GLunit, uTypes, uAILandMarks;
 
 procedure initModule;
 procedure freeModule;
@@ -35,6 +35,28 @@
 
 var digest: shortstring;
 
+procedure ResizeLand(width, height: LongWord);
+var potW, potH: LongWord;
+begin 
+potW:= toPowerOf2(width);
+potH:= toPowerOf2(height);
+if (potW <> LAND_WIDTH) or (potH <> LAND_HEIGHT) then
+    begin
+    LAND_WIDTH:= potW;
+    LAND_HEIGHT:= potH;
+    LAND_WIDTH_MASK:= not(LAND_WIDTH-1);
+    LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1);
+    cWaterLine:= LAND_HEIGHT;
+    if (cReducedQuality and rqBlurryLand) = 0 then
+        SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH)
+    else
+        SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2);
+
+    SetLength(Land, LAND_HEIGHT, LAND_WIDTH);
+    SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32));
+    end;
+end;
+
 procedure ColorizeLand(Surface: PSDL_Surface);
 var tmpsurf: PSDL_Surface;
     r, rr: TSDL_Rect;
@@ -181,6 +203,7 @@
     i: Longword;
     y, x: Longword;
 begin
+    ResizeLand(Template.TemplateWidth, Template.TemplateHeight);
     for y:= 0 to LAND_HEIGHT - 1 do
         for x:= 0 to LAND_WIDTH - 1 do
             Land[y, x]:= lfBasic;
@@ -237,6 +260,7 @@
 
 procedure GenDrawnMap;
 begin
+    ResizeLand(4096, 2048);
     uLandPainted.Draw;
 
     MaxHedgehogs:= 48;
@@ -299,7 +323,7 @@
     WriteLnToConsole('Generating land...');
     case cMapGen of
         0: GenBlank(EdgeTemplates[SelectTemplate]);
-        1: GenMaze;
+        1: begin ResizeLand(4096,2048); GenMaze; end;
         2: GenDrawnMap;
     else
         OutError('Unknown mapgen', true);
@@ -489,7 +513,10 @@
     if tmpsurf = nil then
         tmpsurf:= LoadImage(Pathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
     end;
-TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true);
+// (bare) Sanity check. Considering possible LongInt comparisons as well as just how much system memoery it would take
+TryDo((tmpsurf^.w < $40000000) and (tmpsurf^.h < $40000000) and (tmpsurf^.w * tmpsurf^.h < 6*1024*1024*1024), 'Map dimensions too big!', true);
+
+ResizeLand(tmpsurf^.w, tmpsurf^.h);
 
 // unC0Rr - should this be passed from the GUI? I am not sure which layer does what
 s:= UserPathz[ptMapCurrent] + '/map.cfg';
@@ -676,12 +703,10 @@
                 LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask)
                 end
     end;
-
-UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false);
 end;
 
 procedure GenPreview(out Preview: TPreview);
-var x, y, xx, yy, t, bit, cbit, lh, lw: LongInt;
+var rh, rw, ox, oy, x, y, xx, yy, t, bit, cbit, lh, lw: LongInt;
 begin
     WriteLnToConsole('Generating preview...');
     case cMapGen of
@@ -692,8 +717,21 @@
         OutError('Unknown mapgen', true);
     end;
 
-    lh:= LAND_HEIGHT div 128;
-    lw:= LAND_WIDTH div 32;
+    // strict scaling needed here since preview assumes a rectangle
+    rh:= max(LAND_HEIGHT,2048);
+    rw:= max(LAND_WIDTH,4096);
+    ox:= 0;
+    if rw < rh*2 then
+        begin
+        rw:= rh*2;
+        end;
+    if rh < rw div 2 then rh:= rw * 2;
+    
+    ox:= (rw-LAND_WIDTH) div 2;
+    oy:= rh-LAND_HEIGHT;
+
+    lh:= rh div 128;
+    lw:= rw div 32;
     for y:= 0 to 127 do
         for x:= 0 to 31 do
         begin
@@ -704,7 +742,8 @@
                 cbit:= bit * 8;
                 for yy:= y * lh to y * lh + 7 do
                     for xx:= x * lw + cbit to x * lw + cbit + 7 do
-                        if Land[yy, xx] <> 0 then
+                        if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) 
+                           and (Land[yy-oy, xx-ox] <> 0) then
                             inc(t);
                 if t > 8 then
                     Preview[y, x]:= Preview[y, x] or ($80 shr bit);
--- a/hedgewars/uLandGraphics.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uLandGraphics.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -59,7 +59,7 @@
         begin
         addBgColor:= NewColor;
         exit
-        end; 
+        end;
     // Get colors
     oRed   := (OldColor shr RShift);
     oGreen := (OldColor shr GShift);
@@ -72,7 +72,7 @@
     // Mix colors
     nRed   := min(255,((nRed*nAlpha) div 255) + ((oRed*oAlpha*byte(255-nAlpha)) div 65025));
     nGreen := min(255,((nGreen*nAlpha) div 255) + ((oGreen*oAlpha*byte(255-nAlpha)) div 65025));
-    nBlue  := min(255,((nBlue*nAlpha) div 255) + ((oBlue*oAlpha*byte(255-nAlpha)) div 65025)); 
+    nBlue  := min(255,((nBlue*nAlpha) div 255) + ((oBlue*oAlpha*byte(255-nAlpha)) div 65025));
     nAlpha := min(255, oAlpha + nAlpha);
 
     addBgColor := (nAlpha shl AShift) or (nRed shl RShift) or (nGreen shl GShift) or (nBlue shl BShift);
@@ -82,19 +82,19 @@
 var i: LongInt;
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do
         if (Land[y + dy, i] and lfIndestructible) = 0 then
             Land[y + dy, i]:= Value;
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do
         if (Land[y - dy, i] and lfIndestructible) = 0 then
             Land[y - dy, i]:= Value;
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do
         if (Land[y + dx, i] and lfIndestructible) = 0 then
             Land[y + dx, i]:= Value;
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do
         if (Land[y - dx, i] and lfIndestructible) = 0 then
             Land[y - dx, i]:= Value;
 end;
@@ -105,26 +105,26 @@
 if not doSet then
     begin
     if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if isCurrent then 
+        for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do
+            if isCurrent then
                 Land[y + dy, i]:= Land[y + dy, i] and $FF7F
             else if Land[y + dy, i] and $007F > 0 then
                 Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) - 1);
     if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if isCurrent then 
+        for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do
+            if isCurrent then
                 Land[y - dy, i]:= Land[y - dy, i] and $FF7F
             else if Land[y - dy, i] and $007F > 0 then
                 Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) - 1);
     if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
-            if isCurrent then 
+        for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do
+            if isCurrent then
                 Land[y + dx, i]:= Land[y + dx, i] and $FF7F
             else if Land[y + dx, i] and $007F > 0 then
                 Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) - 1);
     if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
-            if isCurrent then 
+        for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do
+            if isCurrent then
                 Land[y - dx, i]:= Land[y - dx, i] and $FF7F
             else if Land[y - dx, i] and $007F > 0 then
                 Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) - 1)
@@ -132,28 +132,28 @@
 else
     begin
     if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if isCurrent then 
+        for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do
+            if isCurrent then
                 Land[y + dy, i]:= Land[y + dy, i] or $80
             else if Land[y + dy, i] and $007F < 127 then
                 Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) + 1);
-    if ((y - dy) and LAND_HEIGHT_MASK) = 0 then                                                   
-        for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do                                  
-            if isCurrent then                                                                     
-                Land[y - dy, i]:= Land[y - dy, i] or $80                                          
-            else if Land[y - dy, i] and $007F < 127 then                                          
+    if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
+        for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do
+            if isCurrent then
+                Land[y - dy, i]:= Land[y - dy, i] or $80
+            else if Land[y - dy, i] and $007F < 127 then
                 Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) + 1);
-    if ((y + dx) and LAND_HEIGHT_MASK) = 0 then                                                   
-        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do                                  
-            if isCurrent then                                                                     
-                Land[y + dx, i]:= Land[y + dx, i] or $80                                          
-            else if Land[y + dx, i] and $007F < 127 then                                          
+    if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
+        for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do
+            if isCurrent then
+                Land[y + dx, i]:= Land[y + dx, i] or $80
+            else if Land[y + dx, i] and $007F < 127 then
                 Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) + 1);
-    if ((y - dx) and LAND_HEIGHT_MASK) = 0 then                                                   
-        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do                                  
-            if isCurrent then                                                                     
-                Land[y - dx, i]:= Land[y - dx, i] or $80                                          
-            else if Land[y - dx, i] and $007F < 127 then                                          
+    if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
+        for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
+            if isCurrent then
+                Land[y - dx, i]:= Land[y - dx, i] or $80
+            else if Land[y - dx, i] and $007F < 127 then
                 Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) + 1)
     end
 end;
@@ -207,7 +207,7 @@
 begin
 t:= y + dy;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do 
         if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
             if (cReducedQuality and rqBlurryLand) = 0 then
                 LandPixels[t, i]:= 0
@@ -216,7 +216,7 @@
 
 t:= y - dy;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do 
         if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
             if (cReducedQuality and rqBlurryLand) = 0 then
                 LandPixels[t, i]:= 0
@@ -225,7 +225,7 @@
 
 t:= y + dx;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
         if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
             if (cReducedQuality and rqBlurryLand) = 0 then
                 LandPixels[t, i]:= 0
@@ -234,7 +234,7 @@
 
 t:= y - dx;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
         if ((Land[t, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
             if (cReducedQuality and rqBlurryLand) = 0 then
                 LandPixels[t, i]:= 0
@@ -250,7 +250,7 @@
 cnt:= 0;
 t:= y + dy;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do 
         if (Land[t, i] and lfIndestructible) = 0 then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -266,13 +266,13 @@
                 inc(cnt);
                 LandPixels[by, bx]:= LandBackPixel(i, t)
                 end
-            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then 
+            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
                 LandPixels[by, bx]:= 0
             end;
 
 t:= y - dy;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do 
         if (Land[t, i] and lfIndestructible) = 0 then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -288,13 +288,13 @@
                 inc(cnt);
                 LandPixels[by, bx]:= LandBackPixel(i, t)
                 end
-            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then 
+            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
                 LandPixels[by, bx]:= 0
             end;
 
 t:= y + dx;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
         if (Land[t, i] and lfIndestructible) = 0 then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -310,12 +310,12 @@
                 inc(cnt);
                 LandPixels[by, bx]:= LandBackPixel(i, t)
                 end
-            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then 
+            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
                 LandPixels[by, bx]:= 0
             end;
 t:= y - dx;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
         if (Land[t, i] and lfIndestructible) = 0 then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -331,7 +331,7 @@
                 inc(cnt);
                 LandPixels[by, bx]:= LandBackPixel(i, t)
                 end
-            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then 
+            else if ((Land[t, i] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
                 LandPixels[by, bx]:= 0
             end;
 FillLandCircleLinesBG:= cnt;
@@ -342,7 +342,7 @@
 begin
 t:= y + dy;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do 
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -357,7 +357,7 @@
 
 t:= y - dy;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
+    for i:= Min(x + dx, LAND_WIDTH - 1) downto Max(x - dx, 0) do 
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -371,7 +371,7 @@
 
 t:= y + dx;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -386,7 +386,7 @@
 
 t:= y - dx;
 if (t and LAND_HEIGHT_MASK) = 0 then
-    for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
+    for i:= Min(x + dy, LAND_WIDTH - 1) downto Max(x - dy, 0) do 
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -489,8 +489,8 @@
 begin
 for i:= 0 to Pred(Count) do
     begin
-    for ty:= Max(y - Radius, 0) to Min(y + Radius, LAND_HEIGHT) do
-        for tx:= Max(0, ar^[i].Left - Radius) to Min(LAND_WIDTH, ar^[i].Right + Radius) do
+    for ty:= Min(y + Radius, LAND_HEIGHT) downto Max(y - Radius, 0) do 
+        for tx:= Min(LAND_WIDTH, ar^[i].Right + Radius) downto Max(0, ar^[i].Left - Radius) do 
             begin
             if (Land[ty, tx] and lfIndestructible) = 0 then
                 begin
@@ -504,7 +504,7 @@
                     end;
                 if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then
                     LandPixels[by, bx]:= LandBackPixel(tx, ty)
-                else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then 
+                else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
                     LandPixels[by, bx]:= 0
                 end
             end;
@@ -516,8 +516,8 @@
 
 for i:= 0 to Pred(Count) do
     begin
-    for ty:= Max(y - Radius, 0) to Min(y + Radius, LAND_HEIGHT) do
-        for tx:= Max(0, ar^[i].Left - Radius) to Min(LAND_WIDTH, ar^[i].Right + Radius) do
+    for ty:= Min(y + Radius, LAND_HEIGHT) downto Max(y - Radius, 0) do 
+        for tx:= Min(LAND_WIDTH, ar^[i].Right + Radius) downto Max(0, ar^[i].Left - Radius) do 
             if ((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0) then
                 begin
                  if (cReducedQuality and rqBlurryLand) = 0 then
@@ -567,7 +567,7 @@
     and ((tx and LAND_WIDTH_MASK) = 0)
     and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        if despeckle then 
+        if despeckle then
             begin
             Land[ty, tx]:= Land[ty, tx] or lfDamaged;
             LandDirty[ty div 32, tx div 32]:= 1
@@ -837,7 +837,7 @@
 procedure Smooth(X, Y: LongInt);
 begin
 // a bit of AA for explosions
-if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and 
+if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and
     (Y < LAND_HEIGHT-2) and (X > LongInt(leftX) + 1) and (X < LongInt(rightX) - 1) then
     begin
     if ((((Land[y, x-1] and lfDamaged) <> 0) and (((Land[y+1,x] and lfDamaged) <> 0)) or ((Land[y-1,x] and lfDamaged) <> 0))
--- a/hedgewars/uLandTemplates.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uLandTemplates.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -1571,9 +1571,191 @@
       (
        (X: 512; Y:    0)
       );
+// Many islands
+const Template43Points: array[0..173] of TSDL_Rect =
+      (
+       (x:   95; y: 500; w:   1; h:   1),
+       (x:  100; y: 275; w:  25; h: 100),
+       (x:  325; y: 275; w:  25; h: 100),
+       (x:  330; y: 500; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x:  725; y: 125; w:   1; h:   1),
+       (x:  725; y:  25; w:   5; h:  25),
+       (x:  825; y:  35; w:   5; h:  10),
+       (x:  825; y: 135; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 1150; y: 550; w:  25; h:  50),
+       (x: 1250; y: 300; w:  25; h:  50),
+       (x: 1350; y: 300; w:  25; h:  50),
+       (x: 1400; y: 575; w:  25; h:  50),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x:  525; y:1050; w:  50; h:  50),
+       (x:  700; y: 800; w: 100; h: 150),
+       (x:  950; y: 900; w: 100; h: 150),
+       (x: 1100; y:1100; w:  50; h:  50),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x:  175; y:1500; w:   1; h:   1),
+       (x:  210; y:1400; w:   5; h:  25),
+       (x:  240; y:1400; w:   5; h:  25),
+       (x:  275; y:1510; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x:  450; y:1800; w: 100; h: 100),
+       (x:  600; y:1750; w: 100; h: 100),
+       (x:  750; y:1750; w: 100; h: 100),
+       (x:  950; y:1850; w: 100; h: 100),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 1075; y:1450; w:   1; h:   1),
+       (x: 1110; y:1300; w:   5; h:  25),
+       (x: 1140; y:1300; w:   5; h:  25),
+       (x: 1175; y:1430; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 1600; y:1250; w:  25; h: 100),
+       (x: 1700; y:1150; w:  25; h: 100),
+       (x: 1850; y: 500; w:  50; h: 100),
+       (x: 1950; y: 550; w:  50; h: 150),
+       (x: 2250; y:1150; w:  25; h: 100),
+       (x: 2350; y:1250; w:  25; h: 100),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 1750; y:2010; w:   1; h:   1),
+       (x: 1900; y:1870; w:  50; h:  50),
+       (x: 2050; y:1870; w:  50; h:  50),
+       (x: 2175; y:2010; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 2500; y:1700; w:   1; h:   1),
+       (x: 2575; y:1500; w:  10; h:  50),
+       (x: 2650; y:1500; w:  10; h:  50),
+       (x: 2700; y:1690; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 2000; y: 125; w:   1; h:   1),
+       (x: 2050; y:  50; w:  25; h:  25),
+       (x: 2100; y:  50; w:  25; h:  25),
+       (x: 2150; y: 150; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 2600; y: 250; w:  25; h: 100),
+       (x: 2750; y: 400; w:  50; h:  50),
+       (x: 2900; y: 525; w:  50; h:  50),
+       (x: 3150; y: 550; w:  50; h: 100),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 2800; y:1150; w:   1; h:   1),
+       (x: 2840; y: 950; w:  25; h:  25),
+       (x: 2880; y: 950; w:  25; h:  25),
+       (x: 2900; y:1150; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 3075; y:1985; w:   1; h:   1),
+       (x: 3325; y:1700; w:  50; h: 100),
+       (x: 3475; y:1700; w:  50; h: 100),
+       (x: 3625; y:1985; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 3200; y:1450; w:   1; h:   1),
+       (x: 3240; y:1350; w:  25; h:  25),
+       (x: 3280; y:1350; w:  25; h:  25),
+       (x: 3300; y:1450; w:   1; h:   1),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 3500; y:1050; w:  25; h:  50),
+       (x: 3650; y: 600; w:  50; h: 100),
+       (x: 3800; y: 600; w:  50; h: 100),
+       (x: 3900; y:1000; w:  25; h:  50),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x: 3800; y: 200; w:  25; h:  50),
+       (x: 3875; y: 100; w:  50; h:  50),
+       (x: 3925; y:  50; w:  50; h:  25),
+       (x: 4050; y: 125; w:  25; h:  50),
+       (x: NTPX; y:   0; w:   1; h:   1),
+       (x:   95; y:2548; w:   1; h:   1),
+       (x:  100; y:2323; w:  25; h: 100),
+       (x:  325; y:2323; w:  25; h: 100),
+       (x:  330; y:2548; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x:  725; y:2173; w:   1; h:   1),
+       (x:  725; y:2073; w:   5; h:  25),
+       (x:  825; y:2083; w:   5; h:  10),
+       (x:  825; y:2183; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 1150; y:2598; w:  25; h:  50),
+       (x: 1250; y:2348; w:  25; h:  50),
+       (x: 1350; y:2348; w:  25; h:  50),
+       (x: 1400; y:2623; w:  25; h:  50),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x:  525; y:3098; w:  50; h:  50),
+       (x:  700; y:2848; w: 100; h: 150),
+       (x:  950; y:2948; w: 100; h: 150),
+       (x: 1100; y:3148; w:  50; h:  50),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x:  175; y:3548; w:   1; h:   1),
+       (x:  210; y:3448; w:   5; h:  25),
+       (x:  240; y:3448; w:   5; h:  25),
+       (x:  275; y:3558; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x:  450; y:3848; w: 100; h: 100),
+       (x:  600; y:3798; w: 100; h: 100),
+       (x:  750; y:3798; w: 100; h: 100),
+       (x:  950; y:3898; w: 100; h: 100),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 1075; y:3498; w:   1; h:   1),
+       (x: 1110; y:3348; w:   5; h:  25),
+       (x: 1140; y:3348; w:   5; h:  25),
+       (x: 1175; y:3478; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 1600; y:3298; w:  25; h: 100),
+       (x: 1700; y:3198; w:  25; h: 100),
+       (x: 1850; y:2548; w:  50; h: 100),
+       (x: 1950; y:2598; w:  50; h: 150),
+       (x: 2250; y:3198; w:  25; h: 100),
+       (x: 2350; y:3298; w:  25; h: 100),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 1750; y:4058; w:   1; h:   1),
+       (x: 1900; y:3918; w:  50; h:  50),
+       (x: 2050; y:3918; w:  50; h:  50),
+       (x: 2175; y:4058; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 2500; y:3748; w:   1; h:   1),
+       (x: 2575; y:3548; w:  10; h:  50),
+       (x: 2650; y:3548; w:  10; h:  50),
+       (x: 2700; y:3738; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 2000; y:2173; w:   1; h:   1),
+       (x: 2050; y:2098; w:  25; h:  25),
+       (x: 2100; y:2098; w:  25; h:  25),
+       (x: 2150; y:2198; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 2600; y:2298; w:  25; h: 100),
+       (x: 2750; y:2448; w:  50; h:  50),
+       (x: 2900; y:2573; w:  50; h:  50),
+       (x: 3150; y:2598; w:  50; h: 100),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 2800; y:3198; w:   1; h:   1),
+       (x: 2840; y:2998; w:  25; h:  25),
+       (x: 2880; y:2998; w:  25; h:  25),
+       (x: 2900; y:3198; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 3075; y:4033; w:   1; h:   1),
+       (x: 3325; y:3748; w:  50; h: 100),
+       (x: 3475; y:3748; w:  50; h: 100),
+       (x: 3625; y:4033; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 3200; y:3498; w:   1; h:   1),
+       (x: 3240; y:3398; w:  25; h:  25),
+       (x: 3280; y:3398; w:  25; h:  25),
+       (x: 3300; y:3498; w:   1; h:   1),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 3500; y:3098; w:  25; h:  50),
+       (x: 3650; y:2648; w:  50; h: 100),
+       (x: 3800; y:2648; w:  50; h: 100),
+       (x: 3900; y:3048; w:  25; h:  50),
+       (x: NTPX; y:2048; w:   1; h:   1),
+       (x: 3800; y:2248; w:  25; h:  50),
+       (x: 3875; y:2148; w:  50; h:  50),
+       (x: 3925; y:2098; w:  50; h:  25),
+       (x: 4050; y:2173; w:  25; h:  50),
+       (x: NTPX; y:2048; w:   1; h:   1)
+      );
+      Template43FPoints: array[0..0] of TPoint =
+      (
+       (X: 4095; Y:    0)
+      );
 
 ////////////////////////////////////////////////////////////////////////
-var EdgeTemplates: array[0..42] of TEdgeTemplate =
+var EdgeTemplates: array[0..43] of TEdgeTemplate =
       (
        (BasePoints: @Template0Points;
         BasePointsCount: Succ(High(Template0Points));
@@ -2047,19 +2229,30 @@
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: false;
         MaxHedgeHogs: 8;
+       ),
+       (BasePoints: @Template43Points;
+        BasePointsCount: Succ(High(Template43Points));
+        FillPoints: @Template43FPoints;
+        FillPointsCount: Succ(High(Template43FPoints));
+        BezierizeCount: 3;
+        RandPassesCount: 5;
+        TemplateHeight: 4096; TemplateWidth: 4096;
+        canMirror: true; canFlip: true; isNegative: false; canInvert: false;
+        hasGirders: true;
+        MaxHedgeHogs: 48;
        )
       );
 const SmallTemplates: array[0..2] of Longword = ( 39, 40, 42 );
 const MediumTemplates: array[0..17] of Longword =
       ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 );
-const LargeTemplates: array[0..19] of Longword =
+const LargeTemplates: array[0..20] of Longword =
       (
         18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-        28, 29, 30, 31, 32, 33, 34, 35, 37, 38
+        28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 43
       );
 const CavernTemplates: array[0..4] of Longword = (36, 2, 3, 21, 29);
 //const WackyTemplates: array[0..4] of Longword = (37, 38, 39, 40, 41);
-const WackyTemplates: array[0..2] of Longword = (37, 38, 41);
+const WackyTemplates: array[0..3] of Longword = (37, 38, 41, 43);
 
 implementation
 
--- a/hedgewars/uStore.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uStore.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -135,10 +135,11 @@
 
 procedure WriteNames(Font: THWFont);
 var t: LongInt;
-    i: LongInt;
+    i, maxLevel: LongInt;
     r, rr: TSDL_Rect;
     drY: LongInt;
     texsurf, flagsurf, iconsurf: PSDL_Surface;
+    foundBot: boolean;
 begin
 r.x:= 0;
 r.y:= 0;
@@ -176,11 +177,28 @@
         DrawRoundRect(@r, cWhiteColor, cNearBlackColor, texsurf, true);
 
         // overwrite flag for cpu teams and keep players from using it
-        if (Hedgehogs[0].Gear <> nil) and (Hedgehogs[0].BotLevel > 0) then
-            if Flag = 'hedgewars' then
-                Flag:= 'cpu'
-        else if Flag = 'cpu' then
-            Flag:= 'hedgewars';
+        foundBot:= false;
+        maxLevel:= -1;
+        for i:= 0 to cMaxHHIndex do
+            with Hedgehogs[i] do
+                if (Gear <> nil) and (BotLevel > 0) then
+                    begin
+                    foundBot:= true;
+                    // initially was going to do the highest botlevel of the team, but for now, just apply if entire team has same bot level
+                    if maxLevel = -1 then maxLevel:= BotLevel
+                    else if (maxLevel > 0) and (maxLevel <> BotLevel) then maxLevel:= 0; 
+                    //if (maxLevel > 0) and (BotLevel < maxLevel) then maxLevel:= BotLevel
+                    end
+                else if Gear <> nil then  maxLevel:= 0;
+
+        if foundBot then
+            begin
+            // disabled the plain flag - I think it looks ok even w/ full bars obscuring CPU
+            //if (maxLevel > 0) and (maxLevel < 3) then Flag:= 'cpu_plain' else 
+            Flag:= 'cpu'
+            end
+        else if (Flag = 'cpu') or (Flag = 'cpu_plain') then
+                Flag:= 'hedgewars';
 
         flagsurf:= LoadImage(UserPathz[ptFlags] + '/' + Flag, ifNone);
         if flagsurf = nil then
@@ -190,16 +208,27 @@
         if flagsurf = nil then
             flagsurf:= LoadImage(Pathz[ptFlags] + '/hedgewars', ifNone);
         TryDo(flagsurf <> nil, 'Failed to load flag "' + Flag + '" as well as the default flag', true);
+
+        case maxLevel of
+            1: copyToXY(SpritesData[sprBotlevels].Surface, flagsurf, 0, 0); 
+            2: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 5, 2, 17, 13, 5, 2); 
+            3: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 9, 5, 13, 10, 9, 5); 
+            4: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 13, 9, 9, 6, 13, 9); 
+            5: copyToXYFromRect(SpritesData[sprBotlevels].Surface, flagsurf, 17, 11, 5, 4, 17, 11)
+            end;
+
         copyToXY(flagsurf, texsurf, 2, 2);
         SDL_FreeSurface(flagsurf);
         flagsurf:= nil;
 
+
         // restore black border pixels inside the flag
         PLongwordArray(texsurf^.pixels)^[32 * 2 +  2]:= cNearBlackColor;
         PLongwordArray(texsurf^.pixels)^[32 * 2 + 23]:= cNearBlackColor;
         PLongwordArray(texsurf^.pixels)^[32 * 16 +  2]:= cNearBlackColor;
         PLongwordArray(texsurf^.pixels)^[32 * 16 + 23]:= cNearBlackColor;
 
+
         FlagTex:= Surface2Tex(texsurf, false);
         SDL_FreeSurface(texsurf);
         texsurf:= nil;
@@ -208,7 +237,7 @@
 
         dec(drY, r.h + 2);
         DrawHealthY:= drY;
-        for i:= 0 to 7 do
+        for i:= 0 to cMaxHHIndex do
             with Hedgehogs[i] do
                 if Gear <> nil then
                     begin
@@ -298,7 +327,6 @@
             WriteLnToConsole(msgOK)
             end;
 
-WriteNames(fnt16);
 MakeCrossHairs;
 LoadGraves;
 if not reload then
@@ -395,6 +423,8 @@
                 Surface:= nil
         end;
 
+WriteNames(fnt16);
+
 if not reload then
     AddProgress;
 
--- a/hedgewars/uTypes.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uTypes.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -86,7 +86,7 @@
             sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb,
             sprBulletHit, sprSnowball, sprHandSnowball, sprSnow,
             sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis,
-            sprSlider
+            sprSlider, sprBotlevels
             );
 
     // Gears that interact with other Gears and/or Land
--- a/hedgewars/uVariables.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uVariables.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -654,7 +654,9 @@
             (FileName:  'TARDIS'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  48; Height: 79; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis
             (FileName:  'slider'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprSlider
+            Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider
+            (FileName:  'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+            Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprBotlevels
             );
 
 const
--- a/hedgewars/uWorld.pas	Thu Jul 26 21:58:25 2012 +0400
+++ b/hedgewars/uWorld.pas	Mon Aug 06 00:40:26 2012 +0400
@@ -1645,10 +1645,7 @@
     uCursor.updatePosition();
 {$ENDIF}
 z:= round(200/zoom);
-if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) then
-    if (not autoCameraOn) then
-        FollowGear:= nil
-    else
+if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) and autoCameraOn then
     if ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then
         begin
         FollowGear:= nil;
Binary file share/hedgewars/Data/Graphics/Flags/cpu_plain.png has changed
Binary file share/hedgewars/Data/Graphics/botlevels.png has changed
--- a/share/hedgewars/Data/Locale/en.txt	Thu Jul 26 21:58:25 2012 +0400
+++ b/share/hedgewars/Data/Locale/en.txt	Mon Aug 06 00:40:26 2012 +0400
@@ -492,7 +492,7 @@
 04:36=Well, sometimes you're just too bad in aiming. Get|some assistance using modern day technology.|Attack: Activate
 04:37=Don't fear the daylight. It will just last one turn|but will enable you to absorb the damage you do to|other hogs.|Attack: Activate
 04:38=The sniper rifle can be the most devastating weapon|in your whole arsenal, however it's very ineffective|at close quarters. The damage dealt increases with|the distance to its target.|Attack: Shoot (twice)
-04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility is able to|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons
+04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility can|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons
 04:40=Set some ground on fire using this bottle filled|with (soon to be) burning liquid.|Attack: Hold to shoot with more power
 04:41=The evidence nature might even top the flying|saucer. Birdy can carry your hog around and|drop eggs on your enemies!|Be quick, as using Birdy eats into your turn|time!|Attack: Activate and drop eggs|Up/Left/Right: Flap in one direction
 04:42=This portable portal device is capable|of instantly transporting you, your enemies,|or your weaponry between two points on the|terrain.|Use it wisely and your campaign will be a...|HUGE SUCCESS!|Attack: Shoot a portal|Switch: Cycle portal colours
@@ -506,7 +506,7 @@
 04:50=Is someone hiding underground?|Dig them out with a drill strike!|Timer controls how far it will dig.
 04:51=Get in a free shot by hurling a ball of mud.|Stings a bit, and knocks hogs back.
 04:52=UNUSED
-04:53=Go on an adventure through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King.
+04:53=Take a trip through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King.
 04:54=INCOMPLETE                                                                                                                                     
 04:55=Spray a stream of sticky flakes.|Build bridges, bury enemies, seal off tunnels.|Be careful you don't get any on you!