merge
authormikade <redgrinner@gmail.com>
Fri, 01 Jun 2012 00:19:30 +0200
changeset 7163 7db1e3a7422a
parent 7156 09262f82e99d (current diff)
parent 7161 21a9c70b2070 (diff)
child 7164 fad64b97947e
merge
--- a/hedgewars/ArgParsers.inc	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/ArgParsers.inc	Fri Jun 01 00:19:30 2012 +0200
@@ -24,7 +24,7 @@
         playReplayFileWithParameters()
     else
         begin
-        val(ParamStr(2), ipcPort);
+        ipcPort:= StrToInt(ParamStr(2));
         GameType:= gmtLandPreview;
         if ParamStr(3) <> 'landpreview' then
             GameType:= gmtSyntax
@@ -35,22 +35,21 @@
 var tmp: LongInt;
 begin
     UserPathPrefix:= ParamStr(1);
-    val(ParamStr(2), cScreenWidth);
-    val(ParamStr(3), cScreenHeight);
-    val(ParamStr(4), cBits);
-    val(ParamStr(5), ipcPort);
+    cScreenWidth:= StrToInt(ParamStr(2));
+    cScreenHeight:= StrToInt(ParamStr(3));
+    cBits:= StrToInt(ParamStr(4));
+    ipcPort:= StrToInt(ParamStr(5));
     cFullScreen:= ParamStr(6) = '1';
     SetSound(ParamStr(7) = '1');
     SetMusic(ParamStr(8) = '1');
-    val(ParamStr(9), tmp);
-    SetVolume(tmp);
-    val(ParamStr(10), cTimerInterval);
+    SetVolume(StrToInt(ParamStr(9)));
+    cTimerInterval:= StrToInt(ParamStr(10));
     PathPrefix:= ParamStr(11);
     cShowFPS:= ParamStr(12) = '1';
     cAltDamage:= ParamStr(13) = '1';
     UserNick:= DecodeBase64(ParamStr(14));
-    val(ParamStr(15), cReducedQuality);
-    val(ParamStr(16), tmp);
+    cReducedQuality:= StrToInt(ParamStr(15));
+    tmp:= StrToInt(ParamStr(16));
     GrayScale:= false;
     if (tmp > 9) and (tmp < 16) then 
         begin
@@ -72,11 +71,11 @@
 end;
 
 procedure setVideoWithParameters(screenWidthParam: string; screenHeightParam: string; bitsParam: string);
-var screenWidthAsInt, screenHeightAsInt, bitsStrAsInt: LongInt;
+var screenWidthAsInt, screenHeightAsInt, bitsStrAsInt, c: LongInt;
 begin
-    val(screenWidthParam, screenWidthAsInt);
-    val(screenHeightParam, screenHeightAsInt);
-    val(bitsParam, bitsStrAsInt);
+    val(screenWidthParam, screenWidthAsInt, c);
+    val(screenHeightParam, screenHeightAsInt, c);
+    val(bitsParam, bitsStrAsInt, c);
     setVideo(screenWidthAsInt,screenHeightAsInt,bitsStrAsInt)
 end;
 
@@ -108,10 +107,10 @@
 end;
 
 procedure setAudioWithParameters(initialVolumeParam: string; musicEnabledParam: string; soundEnabledParam: string);
-var initialVolumeAsInt: LongInt;
+var initialVolumeAsInt, c: LongInt;
     musicEnabled, soundEnabled: boolean;
 begin
-    val(initialVolumeParam, initialVolumeAsInt);
+    val(initialVolumeParam, initialVolumeAsInt, c);
     musicEnabled:= musicEnabledParam = '1';
     soundEnabled:= soundEnabledParam = '1';
     setAudio(initialVolumeAsInt,musicEnabled, soundEnabled)
@@ -139,7 +138,7 @@
                                       languageFileParam:string; fullScreenParam:string; showFPSParam:string;
                                       altDamageParam:string; timeItervalParam:string; reducedQualityParam: string);
 var showFPS, altDamage, reducedQuality: boolean;
-    timeIterval: LongInt;
+    timeIterval, c: LongInt;
 begin
     setMultimediaOptionsWithParameters(screenWidthParam,screenHeightParam, bitsParam,
                                        initialVolumeParam,musicEnabledParam,soundEnabledParam,
@@ -148,7 +147,7 @@
     setShowFPS(showFPS);
 
     altDamage:= altDamageParam = '1';
-    val(timeItervalParam, timeIterval);
+    val(timeItervalParam, timeIterval, c);
     reducedQuality:= reducedQualityParam = '1';
     setAltDamageTimerValueAndQuality(altDamage,timeIterval,reducedQuality);
 end;
--- a/hedgewars/LuaPas.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/LuaPas.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -1,4 +1,5 @@
 {$HINTS OFF}
+{$INCLUDE "options.inc"}
 
 unit LuaPas;
 
@@ -23,8 +24,7 @@
     lua_State = record end;
     Plua_State = ^lua_State;
 
-const
-    LuaLibName = cLuaLibrary;
+{$DEFINE LuaLibName:= cLuaLibrary}
 
 
 (*****************************************************************************)
@@ -81,8 +81,8 @@
 ** CHANGE them if you want to improve this functionality (e.g., by using
 ** GNU readline and history facilities).
 *)
-function  lua_readline(L : Plua_State;
-var b : PChar; p : PChar): Boolean;
+{function  lua_readline(L : Plua_State;
+var b : PChar; p : PChar): Boolean;}
 
 procedure lua_saveline(L : Plua_State; idx : LongInt);
 
@@ -119,7 +119,7 @@
     LUA_AUTHORS     = 'R. Ierusalimschy, L. H. de Figueiredo & W. Celes';
 
     (* mark for precompiled code (`<esc>Lua') *)
-    LUA_SIGNATURE = #27 + 'Lua';
+    //LUA_SIGNATURE = #27'Lua';
 
     (* option for multiple returns in `lua_pcall' and `lua_call' *)
     LUA_MULTRET = -1;
@@ -799,7 +799,7 @@
 (*****************************************************************************)
 (*                            luaconfig.h                                    *)
 (*****************************************************************************)
-
+{
 function  lua_readline(L : Plua_State;
 var
     b : PChar; p : PChar): Boolean;
@@ -811,7 +811,7 @@
     b := PChar(s);                   //   and return it
     lua_readline := (b[0] <> #4);          // test for ctrl-D
 end;
-
+}
 procedure lua_saveline(L : Plua_State; idx : LongInt);
 begin
 end;
@@ -1041,7 +1041,7 @@
         lua_ref := luaL_ref(L, LUA_REGISTRYINDEX)
     else
         begin
-        lua_pushstring(L, 'unlocked references are obsolete');
+        lua_pushstring(L, _P'unlocked references are obsolete');
         lua_error(L);
         lua_ref := 0;
         end;
--- a/hedgewars/hwengine.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/hwengine.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -104,7 +104,11 @@
     if flagMakeCapture then
         begin
         flagMakeCapture:= false;
+        {$IFDEF PAS2C}
+        s:= 'hw';
+        {$ELSE}
         s:= 'hw_' + FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now()) + inttostr(GameTicks);
+        {$ENDIF}
 
         playSound(sndShutter);
         
@@ -267,10 +271,10 @@
     cBits:= 32;
     cTimerInterval:= 8;
     cShowFPS:= {$IFDEF DEBUGFILE}true{$ELSE}false{$ENDIF};
-    val(gameArgs[0], ipcPort);
-    val(gameArgs[1], cScreenWidth);
-    val(gameArgs[2], cScreenHeight);
-    val(gameArgs[3], cReducedQuality);
+    ipcPort:= StrToInt(gameArgs[0]);
+    cScreenWidth:= StrToInt(gameArgs[1]);
+    cScreenHeight:= StrToInt(gameArgs[2]);
+    cReducedQuality:= StrToInt(gameArgs[3]);
     cLocaleFName:= gameArgs[4];
     // cFullScreen functionality is platform dependent, ifdef it if you need to modify it
     cFullScreen:= false;
@@ -493,26 +497,26 @@
 procedure DisplayUsage;
 var i: LongInt;
 begin
-    WriteLn('Wrong argument format: correct configurations is');
-    WriteLn();
-    WriteLn('  hwengine <path to user hedgewars folder> <path to global data folder> <path to replay file> [options]');
-    WriteLn();
-    WriteLn('where [options] must be specified either as:');
-    WriteLn(' --set-video [screen width] [screen height] [color dept]');
-    WriteLn(' --set-audio [volume] [enable music] [enable sounds]');
-    WriteLn(' --set-other [language file] [full screen] [show FPS]');
-    WriteLn(' --set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]');
-    WriteLn(' --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
-    WriteLn(' --stats-only');
-    WriteLn();
-    WriteLn('Read documentation online at http://code.google.com/p/hedgewars/wiki/CommandLineOptions for more information');
-    WriteLn();
-    Write('PARSED COMMAND: ');
+    WriteLn(stdout, 'Wrong argument format: correct configurations is');
+    WriteLn(stdout, '');
+    WriteLn(stdout, '  hwengine <path to user hedgewars folder> <path to global data folder> <path to replay file> [options]');
+    WriteLn(stdout, '');
+    WriteLn(stdout, 'where [options] must be specified either as:');
+    WriteLn(stdout, ' --set-video [screen width] [screen height] [color dept]');
+    WriteLn(stdout, ' --set-audio [volume] [enable music] [enable sounds]');
+    WriteLn(stdout, ' --set-other [language file] [full screen] [show FPS]');
+    WriteLn(stdout, ' --set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]');
+    WriteLn(stdout, ' --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
+    WriteLn(stdout, ' --stats-only');
+    WriteLn(stdout, '');
+    WriteLn(stdout, 'Read documentation online at http://code.google.com/p/hedgewars/wiki/CommandLineOptions for more information');
+    WriteLn(stdout, '');
+    Write(stdout, 'PARSED COMMAND: ');
     
     for i:=0 to ParamCount do
-        Write(ParamStr(i) + ' ');
+        Write(stdout, ParamStr(i) + ' ');
         
-    WriteLn();
+    WriteLn(stdout, '');
 end;
 
 ////////////////////
@@ -549,6 +553,6 @@
     else Game();
 
     // return 1 when engine is not called correctly
-    ExitCode:= LongInt(GameType = gmtSyntax);
+    halt(LongInt(GameType = gmtSyntax));
 {$ENDIF}
 end.
--- a/hedgewars/pas2c.h	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/pas2c.h	Fri Jun 01 00:19:30 2012 +0200
@@ -29,6 +29,7 @@
     } string15;
 
 typedef string255 shortstring;
+typedef string255 ansistring;
     
 typedef uint8_t Byte;
 typedef int8_t ShortInt;
@@ -71,6 +72,7 @@
 string255 _strconcat(string255 a, string255 b);
 string255 _strappend(string255 s, char c);
 string255 _strprepend(char c, string255 s);
+string255 _chrconcat(char a, char b);
 bool _strcompare(string255 a, string255 b);
 bool _strcomparec(string255 a, char b);
 bool _strncompare(string255 a, string255 b);
@@ -91,6 +93,7 @@
 typedef int TextFile;
 extern int FileMode;
 extern int IOResult;
+extern int stdout;
 extern int stderr;
 
 #define assign(a, b) assign_(&(a), b)
@@ -103,8 +106,8 @@
 void BlockWrite_(int f, void * p, int size);
 void close(int f);
 
-void write(string255 s);
-void writeLn(string255 s);
+void write(int f, string255 s);
+void writeLn(int f, string255 s);
 
 bool DirectoryExists(string255 dir);
 bool FileExists(string255 filename);
@@ -132,8 +135,8 @@
 string255 ParamStr(int n);
 int ParamCount();
 
-#define val(a, b) _val(a, (LongInt*)&(b))
-void _val(string255 str, LongInt * a);
+#define val(a, b, c) _val(a, (LongInt*)&(b), (LongInt*)&(c))
+void _val(string255 str, LongInt * a, LongInt * c);
 
 extern double pi;
 
--- a/hedgewars/pas2cSystem.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/pas2cSystem.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -43,7 +43,6 @@
     PInteger = ^Integer;
     
     Handle = integer;
-    stderr = Handle;
 
     png_structp = pointer;
     png_size_t = integer;
@@ -79,6 +78,7 @@
     FileExists, DirectoryExists, eof : function : boolean;
     ExtractFileName : function : string;
     exitcode : integer;
+    stdout, stderr : Handle;
     
     ParamCount : function : integer;
     ParamStr : function : string;
@@ -134,7 +134,7 @@
     
     Assigned : function : boolean;
     
-    _strconcat, _strappend, _strprepend : function : string;
+    _strconcat, _strappend, _strprepend, _chrconcat : function : string;
     _strcompare, _strncompare, _strcomparec : function : boolean;
 
     png_structp, png_set_write_fn, png_get_io_ptr,
--- a/hedgewars/uAIAmmoTests.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -163,7 +163,7 @@
         EX:= trunc(x);
         EY:= trunc(y);
         if Me^.Hedgehog^.BotLevel = 1 then
-            value:= RateExplosion(Me, EX, EY, 101, 3)
+            value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
         else value:= RateExplosion(Me, EX, EY, 101);
         if value = 0 then
             value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
@@ -220,7 +220,7 @@
         EX:= trunc(x);
         EY:= trunc(y);
 
-        value:= RateShove(Me, trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, 1);
+        value:= RateShove(Me, trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
         if value = 0 then
             value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
 
@@ -323,7 +323,7 @@
     EY:= trunc(y);
     if t < 50 then 
         if Me^.Hedgehog^.BotLevel = 1 then
-            Score:= RateExplosion(Me, EX, EY, 101, 3)
+            Score:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
         else Score:= RateExplosion(Me, EX, EY, 101)
     else 
         Score:= BadTurn;
@@ -650,7 +650,7 @@
 else
     ap.Angle:= - cMaxAngle div 4;
 
-valueResult:= RateShove(Me, trunc(x) + LongWord(10*hwSignf(Targ.X - x)), trunc(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, 1);
+valueResult:= RateShove(Me, trunc(x) + LongWord(10*hwSignf(Targ.X - x)), trunc(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, afTrackFall);
 if valueResult <= 0 then
     valueResult:= BadTurn
 else
@@ -659,7 +659,7 @@
 end;
 
 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var val1: LongInt;
+var val1, val2, i, t: LongInt;
     x, y: real;
 begin
 Level:= Level; // avoid compiler hint
@@ -670,24 +670,25 @@
 ap.Angle:= hwSign(Me^.dX);
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
-if (Abs(trunc(x) - Targ.X) < 25)
-    and (Abs(trunc(y) - 50 - Targ.Y) < 50) then
+{
+// this block is for digging with firepunch when blocked close to walls (notice TestColl check)
+if (Abs(trunc(x) - Targ.X) > 25)
+    or (Abs(trunc(y) + 50 - Targ.Y) > 50) then
     begin
-// TODO - find out WTH this works.
     if TestColl(trunc(x), trunc(y) - 16, 6) and 
        (RateShove(Me, trunc(x) + LongWord(10 * hwSign(Me^.dX)), 
-                      trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9,  1) = 0) then
+                      trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9,  1) >= 0) then
         val1:= Succ(BadTurn)
     else
         val1:= BadTurn;
     exit(val1);
     end;
-(*
-For some silly reason, having this enabled w/ the AI 
+    }
+// and this is actual try to attack
 val1:= 0;
 for i:= 0 to 4 do
     begin
-    t:= RateShove(Me, trunc(x) + 10 * hwSign(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX)*0.45, -0.9, 1);
+    t:= RateShove(Me, trunc(x) + 10 * hwSignf(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX)*0.45, -0.9, afTrackFall);
     if (val1 < 0) or (t < 0) then val1:= BadTurn
     else if t > 0 then val1:= t;
     end;
@@ -695,7 +696,7 @@
 val2:= 0;
 for i:= 0 to 4 do
     begin
-    t:= RateShove(Me, trunc(x) + 10 * hwSign(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, -hwSign(Me^.dX)*0.45, -0.9, 1);
+    t:= RateShove(Me, trunc(x) + 10 * hwSignf(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, -hwSign(Me^.dX)*0.45, -0.9, afTrackFall);
     if (val2 < 0) or (t < 0) then val2:= BadTurn
     else if t > 0 then val2:= t;
     end;
@@ -706,35 +707,57 @@
     ap.Angle:= -hwSign(Me^.dX);
     TestFirePunch:= val2
     end
-else TestFirePunch:= BadTurn;*)
+else TestFirePunch:= BadTurn;
 end;
 
+// TODO: TestWhip, TestFirepunch and TestBaseballBat could be called only once at each position 
+// (now they're called for each possible target in each position)
 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var i, valueResult: LongInt;
+var valueResult, v1, v2: LongInt;
     x, y: real;
 begin
 Level:= Level; // avoid compiler hint
 ap.ExplR:= 0;
 ap.Time:= 0;
 ap.Power:= 1;
-ap.Angle:= 0;
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
-if (Abs(trunc(x) - Targ.X) > 25)
-or (Abs(trunc(y) - 50 - Targ.Y) > 50) then
+
+if(abs(Targ.X - x) > 50) or (abs(Targ.Y - y) > 30) then // we're way too far from our target
+    exit(BadTurn);
+    
+// check left direction
+{first RateShove checks fartherest of two whip's AmmoShove attacks 
+to encourage distant attacks (damaged hog is excluded from view of second 
+RateShove call)}
+v1:= RateShove(Me, trunc(x) - 15, trunc(y)
+        , 30, 30, 40
+        , -1, -0.8, afTrackFall or afSetSkip);
+v1:= v1 +
+    RateShove(Me, trunc(x), trunc(y)
+        , 30, 30, 40
+        , -1, -0.8, afTrackFall);
+// now try opposite direction
+v2:= RateShove(Me, trunc(x) + 15, trunc(y)
+        , 30, 30, 40
+        , 1, -0.8, afTrackFall or afSetSkip);
+v2:= v2 +
+    RateShove(Me, trunc(x), trunc(y)
+        , 30, 30, 40
+        , 1, -0.8, afTrackFall);
+
+if (v2 > v1) 
+    or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
     begin
-    if TestColl(trunc(x), trunc(y) - 16, 6)
-    and (RateShove(Me, trunc(x) + LongWord(10 * hwSign(Me^.dX)), trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX), -0.8,  1) = 0) then
-        valueResult:= Succ(BadTurn)
-    else
-        valueResult:= BadTurn;
-    exit(valueResult);
+    ap.Angle:= 1;
+    valueResult:= v2
+    end
+else 
+    begin
+    ap.Angle:= -1;
+    valueResult:= v1
     end;
-
-valueResult:= 0;
-for i:= 0 to 4 do
-    valueResult:= valueResult + RateShove(Me, trunc(x) + LongWord(10 * hwSignf(Targ.X - x)),
-                                    trunc(y) - LongWord(20 * i) - 5, 10, 30, 40, hwSign(Me^.dX), -0.8, 1);
+   
 if valueResult <= 0 then
     valueResult:= BadTurn
 else
--- a/hedgewars/uAIMisc.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uAIMisc.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -24,9 +24,15 @@
 
 const MAXBONUS = 1024;
 
+      afTrackFall  = $00000001;
+      afErasesLand = $00000002;
+      afSetSkip    = $00000004;
+
+
 type TTarget = record
     Point: TPoint;
     Score: LongInt;
+    skip: boolean;
     end;
 TTargets = record
     Count: Longword;
@@ -100,6 +106,7 @@
                     begin
                     with Targets.ar[Targets.Count], Hedgehogs[i] do
                         begin
+                        skip:= false;
                         Point.X:= hwRound(Gear^.X);
                         Point.Y:= hwRound(Gear^.Y);
                         if Clan <> CurrentTeam^.Clan then
@@ -327,7 +334,6 @@
     end;
 end;
 
-// Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
 function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
 begin
     RateExplosion:= RateExplosion(Me, x, y, r, 0);
@@ -349,7 +355,7 @@
     end;
 // rate explosion
 dmgBase:= r + cHHRadius div 2;
-if (Flags and 2 <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r
+if (Flags and afErasesLand <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r
 else erasure:= 0;
 for i:= 0 to Targets.Count do
     with Targets.ar[i] do
@@ -360,7 +366,7 @@
 
         if dmg > 0 then
             begin
-            if Flags and 1 <> 0 then
+            if Flags and afTrackFall <> 0 then
                 begin
                 dX:= 0.005 * dmg + 0.01;
                 dY:= dX;
@@ -396,6 +402,9 @@
 rate:= 0;
 for i:= 0 to Pred(Targets.Count) do
     with Targets.ar[i] do
+      if skip then 
+        if (Flags and afSetSkip = 0) then skip:= false else {still skip}
+      else  
         begin
         dmg:= 0;
         if abs(Point.x - x) + abs(Point.y - y) < r then
@@ -405,8 +414,9 @@
             end;
         if dmg > 0 then
             begin
-            if (Flags and 1 <> 0) then 
-                fallDmg:= trunc(TraceShoveFall(Me, Point.x, Point.y-2, dX, dY) * dmgMod);
+            if (Flags and afSetSkip <> 0) then skip:= true;
+            if (Flags and afTrackFall <> 0) then 
+                fallDmg:= trunc(TraceShoveFall(Me, Point.x, Point.y - 2, dX, dY) * dmgMod);
             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
                 if Score > 0 then
                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
--- a/hedgewars/uCommandHandlers.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uCommandHandlers.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -86,11 +86,11 @@
 end;
 
 procedure chCheckProto(var s: shortstring);
-var i: LongInt;
+var i, c: LongInt;
 begin
     if isDeveloperMode then
         begin
-        val(s, i);
+        val(s, i, c);
         TryDo(i <= cNetProtoVersion, 'Protocol version mismatch: engine is too old (got '+intToStr(i)+', expecting '+intToStr(cNetProtoVersion)+')', true);
         TryDo(i >= cNetProtoVersion, 'Protocol version mismatch: engine is too new (got '+intToStr(i)+', expecting '+intToStr(cNetProtoVersion)+')', true);
         end
@@ -683,104 +683,102 @@
 
 procedure chMapGen(var s: shortstring);
 begin
-val(s, cMapGen)
+cMapGen:= StrToInt(s)
 end;
 
 procedure chTemplateFilter(var s: shortstring);
 begin
-val(s, cTemplateFilter)
+cTemplateFilter:= StrToInt(s)
 end;
 
 procedure chInactDelay(var s: shortstring);
 begin
-val(s, cInactDelay)
+cInactDelay:= StrToInt(s)
 end;
 
 procedure chReadyDelay(var s: shortstring);
 begin
-val(s, cReadyDelay)
+cReadyDelay:= StrToInt(s)
 end;
 
 procedure chCaseFactor(var s: shortstring);
 begin
-val(s, cCaseFactor)
+cCaseFactor:= StrToInt(s)
 end;
 
 procedure chHealthCaseProb(var s: shortstring);
 begin
-val(s, cHealthCaseProb)
+cHealthCaseProb:= StrToInt(s)
 end;
 
 procedure chHealthCaseAmount(var s: shortstring);
 begin
-val(s, cHealthCaseAmount)
+cHealthCaseAmount:= StrToInt(s)
 end;
 
 procedure chSuddenDTurns(var s: shortstring);
 begin
-val(s, cSuddenDTurns)
+cSuddenDTurns:= StrToInt(s)
 end;
 
 procedure chWaterRise(var s: shortstring);
 begin
-val(s, cWaterRise)
+cWaterRise:= StrToInt(s)
 end;
 
 procedure chHealthDecrease(var s: shortstring);
 begin
-val(s, cHealthDecrease)
+cHealthDecrease:= StrToInt(s)
 end;
 
 procedure chDamagePercent(var s: shortstring);
 begin
-val(s, cDamagePercent)
+cDamagePercent:= StrToInt(s)
 end;
 
 procedure chRopePercent(var s: shortstring);
 begin
-val(s, cRopePercent)
+cRopePercent:= StrToInt(s)
 end;
 
 procedure chGetAwayTime(var s: shortstring);
 begin
-val(s, cGetAwayTime)
+cGetAwayTime:= StrToInt(s)
 end;
 
 procedure chMineDudPercent(var s: shortstring);
 begin
-val(s, cMineDudPercent)
+cMineDudPercent:= StrToInt(s)
 end;
 
 procedure chLandMines(var s: shortstring);
 begin
-val(s, cLandMines)
+cLandMines:= StrToInt(s)
 end;
 
 procedure chExplosives(var s: shortstring);
 begin
-val(s, cExplosives)
+cExplosives:= StrToInt(s)
 end;
 
 procedure chGameFlags(var s: shortstring);
 begin
-val(s, GameFlags)
+GameFlags:= StrToInt(s)
 end;
 
 procedure chHedgehogTurnTime(var s: shortstring);
 begin
-val(s, cHedgehogTurnTime)
+cHedgehogTurnTime:= StrToInt(s)
 end;
 
 procedure chMinesTime(var s: shortstring);
 begin
-val(s, cMinesTime)
+cMinesTime:= StrToInt(s)
 end;
 
 procedure chFastUntilLag(var s: shortstring);
-var i: LongInt;
 begin
-val(s, i);
-fastUntilLag:= i <> 0
+fastUntilLag:= StrToInt(s) <> 0
 end;
 
 procedure initModule;
--- a/hedgewars/uConsole.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uConsole.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -85,7 +85,7 @@
 {$IFNDEF NOCONSOLE}
 WriteToConsole(s);
 {$IFNDEF ANDROID}
-WriteLn(stderr);
+WriteLn(stderr, '');
 inc(CurrLine);
 if CurrLine = cLinesCount then
     CurrLine:= 0;
--- a/hedgewars/uGears.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uGears.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -779,6 +779,7 @@
             Gear^.Active:= true;
             Gear^.State:= Gear^.State or gstMoving;
 
+            // move the gear upwards a bit to throw it over tiny obstacles at start
             if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
                 begin
                 if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
--- a/hedgewars/uInputHandler.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uInputHandler.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -283,7 +283,7 @@
     begin
     for j:= 0 to pred(ControllerNumControllers) do
         begin
-        WriteLnToConsole('Using game controller: ' + SDL_JoystickName(j));
+        WriteLnToConsole('Using game controller: ' + shortstring(SDL_JoystickName(j)));
         Controller[j]:= SDL_JoystickOpen(j);
         if Controller[j] = nil then
             WriteLnToConsole('* Failed to open game controller!')
--- a/hedgewars/uLand.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uLand.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -750,9 +750,9 @@
 
 procedure freeModule;
 begin
-    Land:= nil;
-    LandPixels:= nil;
-    LandDirty:= nil;
+    SetLength(Land, 0, 0);
+    SetLength(LandPixels, 0, 0);
+    SetLength(LandDirty, 0, 0);
 end;
 
 end.
--- a/hedgewars/uLandTexture.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uLandTexture.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -155,6 +155,6 @@
     if LandBackSurface <> nil then
         SDL_FreeSurface(LandBackSurface);
     LandBackSurface:= nil;
-    LandTextures:= nil;
+    SetLength(LandTextures, 0, 0);
 end;
 end.
--- a/hedgewars/uSound.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uSound.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -263,7 +263,7 @@
             if not FileExists(s) then
                 s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
             WriteToConsole(msgLoading + s + ' ');
-            voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
+            voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), _P'rb'), 1);
             if voicepack^.chunks[snd] = nil then
                 WriteLnToConsole(msgFailed)
             else
@@ -279,7 +279,7 @@
             if not FileExists(s) then
                 s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName;
             WriteToConsole(msgLoading + s + ' ');
-            defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
+            defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), _P'rb'), 1);
             SDLTry(defVoicepack^.chunks[snd] <> nil, true);
             WriteLnToConsole(msgOK);
             end;
@@ -363,7 +363,7 @@
             if not FileExists(s) then
                 s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
             WriteToConsole(msgLoading + s + ' ');
-            voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
+            voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), _P'rb'), 1);
             if voicepack^.chunks[snd] = nil then
                 WriteLnToConsole(msgFailed)
             else
@@ -379,7 +379,7 @@
             if not FileExists(s) then
                 s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName;
             WriteToConsole(msgLoading + s + ' ');
-            defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
+            defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), _P'rb'), 1);
             SDLTry(defVoicepack^.chunks[snd] <> nil, true);
             WriteLnToConsole(msgOK);
             end;
--- a/hedgewars/uStats.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uStats.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -185,10 +185,10 @@
 begin
 if time > 4000 then
     begin
-    writeln('FLIGHT');
-    writeln(Gear^.Hedgehog^.Team^.TeamName);
-    writeln(time);
-    writeln;
+    writeln(stdout, 'FLIGHT');
+    writeln(stdout, Gear^.Hedgehog^.Team^.TeamName);
+    writeln(stdout, inttostr(time));
+    writeln(stdout, '');
     end
 end;
 
@@ -293,14 +293,14 @@
 // now to console
 if winnersClan <> nil then 
     begin
-    writeln('WINNERS');
+    writeln(stdout, 'WINNERS');
     for t:= 0 to winnersClan^.TeamsNumber - 1 do
-        writeln(winnersClan^.Teams[t]^.TeamName);
+        writeln(stdout, winnersClan^.Teams[t]^.TeamName);
     end
 else
-    writeln('DRAW');
+    writeln(stdout, 'DRAW');
 
-writeln;
+writeln(stdout, '');
 end;
 
 procedure initModule;
--- a/hedgewars/uStore.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uStore.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -1010,7 +1010,7 @@
 {$ENDIF}
         begin
         // set window title
-        {$IFNDEF SDL13}SDL_WM_SetCaption('Hedgewars', nil);{$ENDIF}
+        {$IFNDEF SDL13}SDL_WM_SetCaption(_P'Hedgewars', nil);{$ENDIF}
         WriteToConsole('Init SDL_image... ');
         SDLTry(IMG_Init(IMG_INIT_PNG) <> 0, true);
         WriteLnToConsole(msgOK);
--- a/hedgewars/uTeams.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uTeams.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -482,6 +482,7 @@
 procedure chAddHH(var id: shortstring);
 var s: shortstring;
     Gear: PGear;
+    c: LongInt;
 begin
 s:= '';
 if (not isDeveloperMode) or (CurrentTeam = nil) then
@@ -490,10 +491,10 @@
     begin
     SplitBySpace(id, s);
     CurrentHedgehog:= @Hedgehogs[HedgehogsNumber];
-    val(id, CurrentHedgehog^.BotLevel);
+    val(id, CurrentHedgehog^.BotLevel, c);
     Gear:= AddGear(0, 0, gtHedgehog, 0, _0, _0, 0);
     SplitBySpace(s, id);
-    val(s, Gear^.Health);
+    val(s, Gear^.Health, c);
     TryDo(Gear^.Health > 0, 'Invalid hedgehog health', true);
     Gear^.Hedgehog^.Team:= CurrentTeam;
     if (GameFlags and gfSharedAmmo) <> 0 then
@@ -514,6 +515,7 @@
 
 procedure chAddTeam(var s: shortstring);
 var Color: Longword;
+    c: LongInt;
     ts, cs: shortstring;
 begin
 cs:= '';
@@ -522,7 +524,7 @@
     begin
     SplitBySpace(s, cs);
     SplitBySpace(cs, ts);
-    val(cs, Color);
+    val(cs, Color, c);
     TryDo(Color <> 0, 'Error: black team color', true);
 
     // color is always little endian so the mask must be constant also in big endian archs
@@ -539,15 +541,15 @@
 
 procedure chSetHHCoords(var x: shortstring);
 var y: shortstring;
-    t: Longint;
+    t, c: Longint;
 begin
 y:= '';
 if (not isDeveloperMode) or (CurrentHedgehog = nil) or (CurrentHedgehog^.Gear = nil) then
     exit;
 SplitBySpace(x, y);
-val(x, t);
+val(x, t, c);
 CurrentHedgehog^.Gear^.X:= int2hwFloat(t);
-val(y, t);
+val(y, t, c);
 CurrentHedgehog^.Gear^.Y:= int2hwFloat(t)
 end;
 
--- a/hedgewars/uTextures.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uTextures.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -167,7 +167,7 @@
     Surface2Tex^.rx:= Surf^.w / tw;
     Surface2Tex^.ry:= Surf^.h / th;
 
-    GetMem(tmpp, tw * th * surf^.format^.BytesPerPixel);
+    tmpp:= GetMem(tw * th * surf^.format^.BytesPerPixel);
 
     fromP4:= Surf^.pixels;
     toP4:= tmpp;
--- a/hedgewars/uUtils.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uUtils.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -39,6 +39,7 @@
 function  Max(a, b: LongInt): LongInt; inline;
 
 function  IntToStr(n: LongInt): shortstring;
+function  StrToInt(s: shortstring): LongInt;
 function  FloatToStr(n: hwFloat): shortstring;
 
 function  DxDy2Angle(const _dY, _dX: hwFloat): GLfloat;
@@ -65,6 +66,11 @@
 function  GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
 function  GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
 
+{$IFNDEF PAS2C}
+procedure Write(var f: textfile; s: shortstring);
+procedure WriteLn(var f: textfile; s: shortstring);
+{$ENDIF}
+
 procedure initModule(isGame: boolean);
 procedure freeModule;
 
@@ -158,6 +164,12 @@
 str(n, IntToStr)
 end;
 
+function  StrToInt(s: shortstring): LongInt;
+var c: LongInt;
+begin
+val(s, StrToInt, c)
+end;
+
 function FloatToStr(n: hwFloat): shortstring;
 begin
 FloatToStr:= cstr(n) + '_' + inttostr(Lo(n.QWordValue))
@@ -285,7 +297,7 @@
 begin
 s:= s;
 {$IFDEF DEBUGFILE}
-writeln(f, GameTicks, ': ', s);
+writeln(f, inttostr(GameTicks)  + ': ' + s);
 flush(f)
 {$ENDIF}
 end;
@@ -359,6 +371,18 @@
 CheckNoTeamOrHH:= (CurrentTeam = nil) or (CurrentHedgehog^.Gear = nil);
 end;
 
+{$IFNDEF PAS2C}
+procedure Write(var f: textfile; s: shortstring);
+begin
+system.write(f, s)
+end;
+
+procedure WriteLn(var f: textfile; s: shortstring);
+begin
+system.writeln(f, s)
+end;
+{$ENDIF}
+
 procedure initModule(isGame: boolean);
 {$IFDEF DEBUGFILE}
 var logfileBase: shortstring;
@@ -403,7 +427,7 @@
 recordFileName:= '';
 
 {$IFDEF DEBUGFILE}
-    writeln(f, 'halt at ', GameTicks, ' ticks. TurnTimeLeft = ', TurnTimeLeft);
+    writeln(f, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft));
     flush(f);
     close(f);
 {$ENDIF}
--- a/hedgewars/uVisualGears.pas	Thu May 31 15:50:25 2012 +0200
+++ b/hedgewars/uVisualGears.pas	Fri Jun 01 00:19:30 2012 +0200
@@ -184,15 +184,15 @@
                     FrameTicks:= random(vobFrameTicks);
                     Frame:= random(vobFramesCount);
                     end;
-                Angle:= random * 360;
+                Angle:= random(360);
                 dx:= 0.0000038654705 * random(10000);
                 dy:= 0.000003506096 * random(7000);
                 if random(2) = 0 then
                     dx := -dx;
                 if SuddenDeathDmg then
-                    dAngle:= (random(2) * 2 - 1) * (1 + random) * vobSDVelocity / 1000
+                    dAngle:= (random(2) * 2 - 1) * (vobSDVelocity + random(vobSDVelocity)) / 1000
                 else
-                    dAngle:= (random(2) * 2 - 1) * (1 + random) * vobVelocity / 1000
+                    dAngle:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) / 1000
                 end;
     vgtCloud:
                 begin
--- a/tools/pas2c.hs	Thu May 31 15:50:25 2012 +0200
+++ b/tools/pas2c.hs	Fri Jun 01 00:19:30 2012 +0200
@@ -335,7 +335,7 @@
 resolveType (DeriveType (InitFloat _)) = return BTFloat
 resolveType (DeriveType (InitString _)) = return BTString
 resolveType (DeriveType (InitBinOp {})) = return BTInt
-resolveType (DeriveType (InitPrefixOp {})) = return BTInt
+resolveType (DeriveType (InitPrefixOp _ e)) = initExpr2C e >> gets lastType
 resolveType (DeriveType (BuiltInFunction{})) = return BTInt
 resolveType (DeriveType (InitReference (Identifier{}))) = return BTBool -- TODO: derive from actual type
 resolveType (DeriveType _) = return BTUnknown
@@ -634,7 +634,7 @@
                     e <- expr2C expr
                     return $ r <+> text "=" <+> e <> semi
                 _ -> error $ "Assignment to string from " ++ show lt
-        (BTArray (Range _) _ _, _) -> phrase2C $ 
+        (BTArray _ _ _, _) -> phrase2C $ 
             ProcCall (FunCall
                 [
                 Reference $ Address ref
@@ -719,6 +719,7 @@
         ("+", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcat" (BTFunction 2 BTString))
         ("+", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappend" (BTFunction 2 BTString))
         ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (BTFunction 2 BTString))
+        ("+", BTChar, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_chrconcat" (BTFunction 2 BTString))
         ("==", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcomparec" (BTFunction 2 BTBool))
         ("==", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (BTFunction 2 BTBool))
         ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (BTFunction 2 BTBool))
@@ -902,9 +903,11 @@
     r <- ref2C ref
     return $ text "&" <> parens r
 ref2C (TypeCast t'@(Identifier i _) expr) = do
-    case map toLower i of
-        "pchar" -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pchar" $ BTPointerTo BTChar))
-        a -> do
+    lt <- expr2C expr >> gets lastType
+    case (map toLower i, lt) of
+        ("pchar", BTString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pchar" $ BTPointerTo BTChar))
+        ("shortstring", BTPointerTo _) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "pchar2str" $ BTString))
+        (a, _) -> do
             e <- expr2C expr
             t <- id2C IOLookup t'    
             return . parens $ parens t <> e