hedgewars/uMisc.pas
author nemo
Tue, 30 Mar 2010 13:33:01 +0000
changeset 3173 909b28b1b61a
parent 3169 c8c6ac44f51b
child 3295 ced0ee8280ad
permissions -rw-r--r--
This map has always been broken. This variant makes it slightly less broken (although something changed on the ceiling might prevent hiding on pixels on the slope). What will finally fix it is either moving nets closer together or adding angle bounce to hedgehogs or some other layout that prevents hiding.

(*
* Hedgewars, a free turn based strategy game
* Copyright (c) 2004-2008 Andrey Korotaev <unC0Rr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*)

{$INCLUDE "options.inc"}

unit uMisc;
interface

uses    SDLh, uConsts, uFloat, GLunit;

var
    isCursorVisible : boolean;
    isTerminated    : boolean;
    isInLag         : boolean;
    isPaused        : boolean;
    isSoundEnabled  : boolean;
    isMusicEnabled  : boolean;
    isSEBackup      : boolean;
    isInMultiShoot  : boolean;
    isSpeed         : boolean;
    isFirstFrame    : boolean;

    fastUntilLag    : boolean;

    GameState   : TGameState;
    GameType    : TGameType;
    GameFlags   : Longword;
    TrainingFlags   : Longword;
    TurnTimeLeft    : Longword;
    cSuddenDTurns   : LongInt;
    cDamagePercent  : LongInt;
    cMineDudPercent : LongWord;
    cTemplateFilter : LongInt;
    cMapGen         : LongInt;
    cMazeSize       : LongInt;

    cHedgehogTurnTime: Longword;
    cMinesTime       : LongInt;
    cMaxAIThinkTime  : Longword;

    cCloudsNumber    : LongInt;
    cScreenWidth     : LongInt;
    cScreenHeight    : LongInt;
    cInitWidth       : LongInt;
    cInitHeight      : LongInt;
    cVSyncInUse      : boolean;
    cBits            : LongInt;
    cBitsStr         : string[2];
    cTagsMask        : byte;
    zoom             : GLfloat;
    ZoomValue        : GLfloat;

    cWaterLine       : LongInt;
    cGearScrEdgesDist: LongInt;
    cAltDamage       : boolean;

    GameTicks   : LongWord;
    TrainingTimeInc : Longword;
    TrainingTimeInD : Longword;
    TrainingTimeInM : Longword;
    TrainingTimeMax : Longword;

    TimeTrialStartTime: Longword;
    TimeTrialStopTime : Longword;
    
    recordFileName  : shortstring;
    cShowFPS    : boolean;
    cCaseFactor : Longword;
    cLandAdditions  : Longword;
    cExplosives : Longword;
    cFullScreen : boolean;
    cReducedQuality : boolean;
    cLocaleFName    : shortstring;
    cSeed       : shortstring;
    cInitVolume : LongInt;
    cVolumeDelta    : LongInt;
    cTimerInterval  : Longword;
    cHasFocus   : boolean;
    cInactDelay : Longword;

    bBetweenTurns   : boolean;
    cHealthDecrease : LongWord;
    bWaterRising    : Boolean;

    ShowCrosshair   : boolean;
    CursorMovementX : LongInt;
    CursorMovementY : LongInt;
    cDrownSpeed : hwFloat;
    cMaxWindSpeed   : hwFloat;
    cWindSpeed  : hwFloat;
    cGravity    : hwFloat;
    cDamageModifier : hwFloat;
    cLaserSighting  : boolean;
    cVampiric   : boolean;
    cArtillery  : boolean;
    WeaponTooltipTex : PTexture;
    cWeaponTooltips: boolean;

    flagMakeCapture : boolean;

    InitStepsFlags  : Longword;
    RealTicks   : Longword;
    AttackBar   : LongInt;

    WaterColorArray : array[0..3] of HwColor4f;

    CursorPoint : TPoint;
    TargetPoint : TPoint;

    TextureList : PTexture;

    ScreenFade : TScreenFade;
    ScreenFadeValue : LongInt;
    ScreenFadeSpeed : LongInt;


procedure initModule;
procedure freeModule;
procedure SplitBySpace(var a, b: shortstring);
procedure SplitByChar(var a, b: ansistring; c: char);
procedure movecursor(dx, dy: LongInt);
function  hwSign(r: hwFloat): LongInt;
function  Min(a, b: LongInt): LongInt;
function  Max(a, b: LongInt): LongInt;
procedure OutError(Msg: shortstring; isFatalError: boolean);
procedure TryDo(Assert: boolean; Msg: shortstring; isFatal: boolean);
procedure SDLTry(Assert: boolean; isFatal: boolean);
function  IntToStr(n: LongInt): shortstring;
function  FloatToStr(n: hwFloat): shortstring;
function  DxDy2Angle(const _dY, _dX: hwFloat): GLfloat;
function  DxDy2Angle32(const _dY, _dX: hwFloat): LongInt;
function  DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt;
procedure AdjustColor(var Color: Longword);
procedure SetKB(n: Longword);
procedure SendKB;
procedure SetLittle(var r: hwFloat);
procedure SendStat(sit: TStatInfoType; s: shortstring);
function  Str2PChar(const s: shortstring): PChar;
function  NewTexture(width, height: Longword; buf: Pointer): PTexture;
function  Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
procedure FreeTexture(tex: PTexture);
function  toPowerOf2(i: Longword): Longword;
function  DecodeBase64(s: shortstring): shortstring;
function  doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface;
function  endian(independent: LongWord): LongWord;
{$IFDEF DEBUGFILE}
procedure AddFileLog(s: shortstring);
function  RectToStr(Rect: TSDL_Rect): shortstring;
{$ENDIF}
{$IFNDEF IPHONEOS}
procedure MakeScreenshot(filename: shortstring);
{$ENDIF}

implementation
uses Math, uConsole, uStore, uIO, uRandom, uSound;

var KBnum: Longword;
{$IFDEF DEBUGFILE}
    f: textfile;
{$ENDIF}

// should this include "strtolower()" for the split string?
procedure SplitBySpace(var a, b: shortstring);
var i, t: LongInt;
begin
i:= Pos(' ', a);
if i > 0 then
    begin
    for t:= 1 to Pred(i) do
        if (a[t] >= 'A')and(a[t] <= 'Z') then Inc(a[t], 32);
    b:= copy(a, i + 1, Length(a) - i);
    byte(a[0]):= Pred(i)
    end else b:= '';
end;

procedure SplitByChar(var a, b: ansistring; c: char);
var i: LongInt;
begin
i:= Pos(c, a);
if i > 0 then
    begin
    b:= copy(a, i + 1, Length(a) - i);
    setlength(a, Pred(i));
    end else b:= '';
end;

procedure movecursor(dx, dy: LongInt);
var x, y: LongInt;
begin
if (dx = 0) and (dy = 0) then exit;

SDL_GetMouseState(@x, @y);
Inc(x, dx);
Inc(y, dy);
SDL_WarpMouse(x, y);
end;

function hwSign(r: hwFloat): LongInt;
begin
// yes, we have negative zero for a reason
if r.isNegative then hwSign:= -1 else hwSign:= 1
end;

function Min(a, b: LongInt): LongInt;
begin
if a < b then Min:= a else Min:= b
end;

function Max(a, b: LongInt): LongInt;
begin
if a > b then Max:= a else Max:= b
end;

procedure OutError(Msg: shortstring; isFatalError: boolean);
begin
{$IFDEF DEBUGFILE}AddFileLog(Msg);{$ENDIF}
WriteLnToConsole(Msg);
if isFatalError then
begin
SendIPC('E' + GetLastConsoleLine);
SDL_Quit;
halt(1)
end
end;

procedure TryDo(Assert: boolean; Msg: shortstring; isFatal: boolean);
begin
if not Assert then OutError(Msg, isFatal)
end;

procedure SDLTry(Assert: boolean; isFatal: boolean);
begin
if not Assert then OutError(SDL_GetError, isFatal)
end;

procedure AdjustColor(var Color: Longword);
begin
Color:= SDL_MapRGB(PixelFormat, (Color shr 16) and $FF, (Color shr 8) and $FF, Color and $FF)
end;

function IntToStr(n: LongInt): shortstring;
begin
str(n, IntToStr)
end;

function FloatToStr(n: hwFloat): shortstring;
begin
FloatToStr:= cstr(n) + '_' + inttostr(Lo(n.QWordValue))
end;

procedure SetTextureParameters(enableClamp: Boolean);
begin
if enableClamp and not cReducedQuality then
    begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
    end;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
end;

function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat;
var dY, dX: Extended;
begin
dY:= _dY.QWordValue / $100000000;
if _dY.isNegative then dY:= - dY;
dX:= _dX.QWordValue / $100000000;
if _dX.isNegative then dX:= - dX;
DxDy2Angle:= arctan2(dY, dX) * 180 / pi
end;

function DxDy2Angle32(const _dY, _dX: hwFloat): LongInt;
const _16divPI: Extended = 16/pi;
var dY, dX: Extended;
begin
dY:= _dY.QWordValue / $100000000;
if _dY.isNegative then dY:= - dY;
dX:= _dX.QWordValue / $100000000;
if _dX.isNegative then dX:= - dX;
DxDy2Angle32:= trunc(arctan2(dY, dX) * _16divPI) and $1f
end;

function DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt;
const MaxAngleDivPI: Extended = cMaxAngle/pi;
var dY, dX: Extended;
begin
dY:= _dY.QWordValue / $100000000;
if _dY.isNegative then dY:= - dY;
dX:= _dX.QWordValue / $100000000;
if _dX.isNegative then dX:= - dX;
DxDy2AttackAngle:= trunc(arctan2(dY, dX) * MaxAngleDivPI)
end;

procedure SetKB(n: Longword);
begin
KBnum:= n
end;

procedure SendKB;
var s: shortstring;
begin
if KBnum <> 0 then
begin
s:= 'K' + inttostr(KBnum);
SendIPCRaw(@s, Length(s) + 1)
end
end;

procedure SetLittle(var r: hwFloat);
begin
r:= SignAs(cLittle, r)
end;

procedure SendStat(sit: TStatInfoType; s: shortstring);
const stc: array [TStatInfoType] of char = 'rDkKH';
var buf: shortstring;
begin
buf:= 'i' + stc[sit] + s;
SendIPCRaw(@buf[0], length(buf) + 1)
end;

function Str2PChar(const s: shortstring): PChar;
const CharArray: array[byte] of Char = '';
begin
CharArray:= s;
CharArray[Length(s)]:= #0;
Str2PChar:= @CharArray
end;

function isPowerOf2(i: Longword): boolean;
begin
if i = 0 then exit(true);
while (i and 1) = 0 do i:= i shr 1;
isPowerOf2:= (i = 1)
end;

function toPowerOf2(i: Longword): Longword;
begin
toPowerOf2:= 1;
while (toPowerOf2 < i) do toPowerOf2:= toPowerOf2 shl 1
end;

procedure ResetVertexArrays(texture: PTexture);
begin
with texture^ do
    begin
    vb[0].X:= 0;
    vb[0].Y:= 0;
    vb[1].X:= w;
    vb[1].Y:= 0;
    vb[2].X:= w;
    vb[2].Y:= h;
    vb[3].X:= 0;
    vb[3].Y:= h;

    tb[0].X:= 0;
    tb[0].Y:= 0;
    tb[1].X:= rx;
    tb[1].Y:= 0;
    tb[2].X:= rx;
    tb[2].Y:= ry;
    tb[3].X:= 0;
    tb[3].Y:= ry
    end;
end;

function NewTexture(width, height: Longword; buf: Pointer): PTexture;
begin
new(NewTexture);
NewTexture^.PrevTexture:= nil;
NewTexture^.NextTexture:= nil;
if TextureList <> nil then
    begin
    TextureList^.PrevTexture:= NewTexture;
    NewTexture^.NextTexture:= TextureList
    end;
TextureList:= NewTexture;

NewTexture^.w:= width;
NewTexture^.h:= height;
NewTexture^.rx:= 1.0;
NewTexture^.ry:= 1.0;

ResetVertexArrays(NewTexture);

glGenTextures(1, @NewTexture^.id);

glBindTexture(GL_TEXTURE_2D, NewTexture^.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);

SetTextureParameters(true);
end;

function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
var tw, th, x, y: Longword;
    tmpp: pointer;
    fromP4, toP4: PLongWordArray;
begin
new(Surface2Tex);
Surface2Tex^.PrevTexture:= nil;
Surface2Tex^.NextTexture:= nil;
if TextureList <> nil then
    begin
    TextureList^.PrevTexture:= Surface2Tex;
    Surface2Tex^.NextTexture:= TextureList
    end;
TextureList:= Surface2Tex;

Surface2Tex^.w:= surf^.w;
Surface2Tex^.h:= surf^.h;

if (surf^.format^.BytesPerPixel <> 4) then
begin
    TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
    Surface2Tex^.id:= 0;
    exit
end;


glGenTextures(1, @Surface2Tex^.id);

glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);

if SDL_MustLock(surf) then
    SDLTry(SDL_LockSurface(surf) >= 0, true);

if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
begin
    tw:= toPowerOf2(Surf^.w);
    th:= toPowerOf2(Surf^.h);

    Surface2Tex^.rx:= Surf^.w / tw;
    Surface2Tex^.ry:= Surf^.h / th;

    GetMem(tmpp, tw * th * surf^.format^.BytesPerPixel);

        fromP4:= Surf^.pixels;
        toP4:= tmpp;

        for y:= 0 to Pred(Surf^.h) do
        begin
            for x:= 0 to Pred(Surf^.w) do toP4^[x]:= fromP4^[x];
            for x:= Surf^.w to Pred(tw) do toP4^[x]:= 0;
            toP4:= @(toP4^[tw]);
            fromP4:= @(fromP4^[Surf^.pitch div 4]);
        end;

        for y:= Surf^.h to Pred(th) do
        begin
            for x:= 0 to Pred(tw) do toP4^[x]:= 0;
            toP4:= @(toP4^[tw]);
        end;

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpp);

    FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel)
end
else
begin
    Surface2Tex^.rx:= 1.0;
    Surface2Tex^.ry:= 1.0;
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
end;

ResetVertexArrays(Surface2Tex);

if SDL_MustLock(surf) then
    SDL_UnlockSurface(surf);

SetTextureParameters(enableClamp);
end;

procedure FreeTexture(tex: PTexture);
begin
if tex <> nil then
    begin
    if tex^.NextTexture <> nil then tex^.NextTexture^.PrevTexture:= tex^.PrevTexture;
    if tex^.PrevTexture <> nil then tex^.PrevTexture^.NextTexture:= tex^.NextTexture
    else TextureList:= tex^.NextTexture;
    glDeleteTextures(1, @tex^.id);
    Dispose(tex)
    end
end;

function DecodeBase64(s: shortstring): shortstring;
const table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var i, t, c: Longword;
begin
c:= 0;
for i:= 1 to Length(s) do
    begin
    t:= Pos(s[i], table);
    if s[i] = '=' then inc(c);
    if t > 0 then byte(s[i]):= t - 1 else byte(s[i]):= 0
    end;

i:= 1;
t:= 1;
while i <= length(s) do
    begin
    DecodeBase64[t    ]:= char((byte(s[i    ]) shl 2) or (byte(s[i + 1]) shr 4));
    DecodeBase64[t + 1]:= char((byte(s[i + 1]) shl 4) or (byte(s[i + 2]) shr 2));
    DecodeBase64[t + 2]:= char((byte(s[i + 2]) shl 6) or (byte(s[i + 3])      ));
    inc(t, 3);
    inc(i, 4)
    end;

if c < 3 then t:= t - c;

byte(DecodeBase64[0]):= t - 1
end;

{$IFNDEF IPHONEOS}
procedure MakeScreenshot(filename: shortstring);
var p: Pointer;
    size: Longword;
    f: file;
{$IFNDEF WIN32}
    // TGA Header
    head: array[0..8] of Word = (0, 2, 0, 0, 0, 0, 0, 0, 24);
{$ELSE}
    // Windows Bitmap Header
    head: array[0..53] of Byte = (
    $42, $4D, // identifier ("BM")
    0, 0, 0, 0, // file size
    0, 0, 0, 0, // reserved
    54, 0, 0, 0, // starting offset
    40, 0, 0, 0, // header size
    0, 0, 0, 0, // width
    0, 0, 0, 0, // height
    1, 0, // color planes
    24, 0, // bit depth
    0, 0, 0, 0, // compression method (uncompressed)
    0, 0, 0, 0, // image size
    96, 0, 0, 0, // horizontal resolution
    96, 0, 0, 0, // vertical resolution
    0, 0, 0, 0, // number of colors (all)
    0, 0, 0, 0 // number of important colors
    );
{$ENDIF}
begin
playSound(sndShutter);

// flash
ScreenFade:= sfFromWhite;
ScreenFadeValue:= sfMax;
ScreenFadeSpeed:= 5;

size:= cScreenWidth * cScreenHeight * 3;
p:= GetMem(size);

// update header information and file name
{$IFNDEF WIN32}
filename:= ParamStr(1) + '/' + filename + '.tga';

head[6]:= cScreenWidth;
head[7]:= cScreenHeight;
{$ELSE}
filename:= ParamStr(1) + '/' + filename + '.bmp';

head[$02]:= (size + 54) and $ff;
head[$03]:= ((size + 54) shr 8) and $ff;
head[$04]:= ((size + 54) shr 16) and $ff;
head[$05]:= ((size + 54) shr 24) and $ff;
head[$12]:= cScreenWidth and $ff;
head[$13]:= (cScreenWidth shr 8) and $ff;
head[$14]:= (cScreenWidth shr 16) and $ff;
head[$15]:= (cScreenWidth shr 24) and $ff;
head[$16]:= cScreenHeight and $ff;
head[$17]:= (cScreenHeight shr 8) and $ff;
head[$18]:= (cScreenHeight shr 16) and $ff;
head[$19]:= (cScreenHeight shr 24) and $ff;
head[$22]:= size and $ff;
head[$23]:= (size shr 8) and $ff;
head[$24]:= (size shr 16) and $ff;
head[$25]:= (size shr 24) and $ff;
{$ENDIF}

//remember that opengles operates on a single surface, so GL_FRONT *should* be implied
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, cScreenWidth, cScreenHeight, GL_BGR, GL_UNSIGNED_BYTE, p);

{$I-}
Assign(f, filename);
Rewrite(f, 1);
if IOResult = 0 then
    begin
    BlockWrite(f, head, sizeof(head));
    BlockWrite(f, p^, size);
    Close(f);
    end;
{$I+}

FreeMem(p)
end;
{$ENDIF}

{$IFDEF DEBUGFILE}
procedure AddFileLog(s: shortstring);
begin
writeln(f, GameTicks: 6, ': ', s);
flush(f)
end;

function RectToStr(Rect: TSDL_Rect): shortstring;
begin
RectToStr:= '(x: ' + inttostr(rect.x) + '; y: ' + inttostr(rect.y) + '; w: ' + inttostr(rect.w) + '; h: ' + inttostr(rect.h) + ')'
end;
{$ENDIF}

function doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface;
{* for more information http://www.idevgames.com/forum/showpost.php?p=85864&postcount=7 *}
var convertedSurf: PSDL_Surface = nil;
begin
    if (tmpsurf^.format^.bitsperpixel = 24) or ((tmpsurf^.format^.bitsperpixel = 32) and (tmpsurf^.format^.rshift > tmpsurf^.format^.bshift)) then
    begin
        convertedSurf:= SDL_ConvertSurface(tmpsurf, @conversionFormat, SDL_SWSURFACE);
        SDL_FreeSurface(tmpsurf);
        exit(convertedSurf);
    end;

    exit(tmpsurf);
end;

function endian(independent: LongWord): LongWord;
begin
{$IFDEF ENDIAN_LITTLE}
endian:= independent;
{$ELSE}
endian:= (((independent and $FF000000) shr 24) or
    ((independent and $00FF0000) shr 8) or
    ((independent and $0000FF00) shl 8) or
    ((independent and $000000FF) shl 24))
{$ENDIF}
end;


procedure initModule;
{$IFNDEF IPHONEOS}var i: LongInt;{$ENDIF}
begin
    cDrownSpeed.QWordValue  := 257698038;       // 0.06
    cMaxWindSpeed.QWordValue:= 2147484;     // 0.0005
    cWindSpeed.QWordValue   := 429496;      // 0.0001
    cGravity                := cMaxWindSpeed;
    cDamageModifier         := _1;
    TargetPoint             := cTargetPointRef;
    TextureList             := nil;
    
    // int, longint longword and byte
    CursorMovementX     := 0;
    CursorMovementY     := 0;
    GameTicks           := 0;
    TrainingTimeInc     := 10000;
    TrainingTimeInD     := 500;
    TrainingTimeInM     := 5000;
    TrainingTimeMax     := 60000;
    TimeTrialStartTime  := 0;
    TimeTrialStopTime   := 0;
    cWaterLine          := LAND_HEIGHT;
    cGearScrEdgesDist   := 240;
    cHealthDecrease     := 0;

    GameFlags           := 0;
    TrainingFlags       := 0;
    TurnTimeLeft        := 0;
    cSuddenDTurns       := 15;
    cDamagePercent      := 100;
    cMineDudPercent     := 0;
    cTemplateFilter     := 0;
    cMapGen             := 0;//MAPGEN_REGULAR
    cMazeSize           := 0;

    cHedgehogTurnTime   := 45000;
    cMinesTime          := 3000;
    cMaxAIThinkTime     := 9000;

    cCloudsNumber       := 9;
    cScreenWidth        := 1024;
    cScreenHeight       := 768;
    cInitWidth      := cScreenWidth;
    cInitHeight     := cScreenHeight;
    cBits           := 32;
    cTagsMask       := 0;
    KBnum           := 0;
    InitStepsFlags  := 0;
    RealTicks       := 0;
    AttackBar       := 0; // 0 - none, 1 - just bar at the right-down corner, 2 - like in WWP
    
    // tgametype and glfloat and string
    GameState       := Low(TGameState);
    GameType        := gmtLocal;
    zoom            := 2.0;
    ZoomValue       := 2.0;
    cBitsStr        := '32';
    WeaponTooltipTex:= nil;

    // booleans
    cLaserSighting  := false;
    cVampiric       := false;
    cArtillery      := false;
    flagMakeCapture := false;
    bBetweenTurns   := false;
    bWaterRising    := false;
    isCursorVisible := false;
    isTerminated    := false;
    isInLag         := false;
    isPaused        := false;
    isMusicEnabled  := false;
    isInMultiShoot  := false;
    isSpeed         := false;
    fastUntilLag    := false;
    isFirstFrame    := true;
    cVSyncInUse     := true;    
    isSoundEnabled  := true;
    isSEBackup      := true;
    
    // init flags
    recordFileName  := '';
    cShowFPS        := false;
    cCaseFactor     := 5;  {0..9}
    cLandAdditions  := 4;
    cExplosives     := 2;
    cFullScreen     := false;
    cReducedQuality := false;
    cLocaleFName    := 'en.txt';
    cSeed           := '';
    cInitVolume     := 50;
    cVolumeDelta    := 0;
    cTimerInterval  := 8;
    cHasFocus       := true;
    cInactDelay     := 1250;
    cAltDamage      := true;

    ScreenFade      := sfNone;
{$IFDEF DEBUGFILE}
{$I-}
{$IFDEF IPHONEOS}
    f:= stderr;
{$ELSE}
    if ParamStr(1) <> '' then
        begin
        for i:= 0 to 7 do
        begin
            assign(f, ParamStr(1) + '/debug' + inttostr(i) + '.txt');
            rewrite(f);
            if IOResult = 0 then break;
        end;
        if IOResult <> 0 then f:= stderr; // if everything fails, write to stderr
        end
    else
        f:= stderr;
{$ENDIF}
{$I+}
{$ENDIF}

end;

procedure freeModule;
begin
    //uRandom.DumpBuffer;
    while TextureList <> nil do FreeTexture(TextureList);

{$IFDEF DEBUGFILE}
    writeln(f, 'halt at ', GameTicks, ' ticks. TurnTimeLeft = ', TurnTimeLeft);
    flush(f);
    close(f);
{$ENDIF}
end;

end.