/*
 Links:
 http://pmg.org.ru/nehe/index.html
 https://khronos.org/registry/OpenGL/api/GL/wglext.h
*/

/*
 Libs:
 -lopengl32
 -lglu32 
 -lgdi32
 -lwinmm
 -mwindows
 -loleaut32
 -luuid
*/

/**************************
 * Includes
 *
 **************************/

#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glext.h>
#include "wglext.h"

#include <olectl.h>          // Заголовочный файл для библиотеки
                             // управляющих элементов OLE (используется в BuildTexture)

#include "resource.h"

/**************************
 * Function Declarations
 *
 **************************/

float rad=0.0174532925199f;// Уставливаем отношение радиан к градусам.
float theta=0.0f, angleX=0.0f, angleXlimit=35.0f,
      tCos, x=0.0f, z=0.0f, xL=-0.5f, xR=0.5f, yB=-0.5f, yT=0.5f,
      step=0.0f, speedK, squareL=1.0f,
      fogDist=17.0f, skyL=17.0f*7, skyH=3.25f*5, skyDist=17.0f*5,
      sndDist=17.0f, objDist=17.0f;
int fontStitle, fontS, fps=-1, paintC=0, timeS=0;
bool bQuit=false, keyUp=false, keyDown=false, keyLeft=false, keyRight=false,
     keyLookUp=false, keyLookDown=false, keyLookOff=false;
float keyLeftC=0.0f, keyRightC=0.0f;
bool noRest=false, blur_on=false, loaded=false;
int cx, cy, cm;
bool menuOn=false, statusOn=false, pointerOn=false, ctrl_key=false,
     keyLockEsc=false, keyLockI=false, keyLockC=false, keyLockW=false, keyLockEnter=false;
int infoOn=0, subOn=0;
int fpsOn=0;
bool clockTweak=false;
long clockL=0;
float clockD=0.0f;
int multisampleOn=1;
float hitEscZ=-2.5f, hitEscTill=-10.5f, hitEscR=0.0f;
float gamma=1.0f, gammaR=1.0f, gammaG=1.0f, gammaB=1.0f;
int timeOfDay=2;

int score=0, infoPage=1, infoPages;

char menuAr0 [96] [16]={"Идти", "История", "Клавиши", "Звук", "Мелодия", "Время", "Походка", "Статус", "Видимость", "Разрешение", "О программе", "Спасибо!", "Выход"};
char menuAr [96] [16];
int menuL0=13, menuL, menuSel0=0, menuFrom0=0, menuSel=0, menuFrom=0, menuQ=4, menuS=-1;
int subL, subSel=0, subFrom=0, subQ=4, subS=-1;
float menuR=0;

int dmW [96], dmH [96], dmB [96], dmC=0,
    dmH0, dmW0, dmB0, dmN=0,
    dmHs, dmWs, dmBs, dmHt, dmWt, dmBt;
bool dmBitsOff=true;

GLuint texture [55];
GLuint base; // База списка отображения для фонта
GLuint fogMode []={GL_EXP, GL_EXP2, GL_LINEAR};// Хранит три типа тумана
GLuint fogfilter=0;                            // Тип используемого тумана
GLuint PixelFormat;
GLUquadricObj *quadratic;// Место для хранения объекта Quadratic

float walkbiasangle=90.0f, walkbias=0.0f, walkbiasK0=0.05f, walkbiasK=0.05f, wbLast=0.0f;
int wbD=0, wbLD=0, walk12=1;// D - direction
bool walkIs=false, walkUp=false, walkDown=false;

#define treeQ 65
#define treeBQ 65
int treeVolMx, treeTime=0, treeWindAngleDir=-1, treeHold=0,
    treeWindTime=0, treeWindDir=1, treeWindState=0;
float treeWindX=0.0f, treeWindZ=0.0f, treeWindAngle=0.0f;
// Структура объекта
struct treeObject
{
   int angle;// угол наклона
 float angleX;// по X
 float angleZ;// по Z
 float cronaR;// размер кроны
 float cronaH;// высота
 float cronaColorR;// цвет R
 float cronaColorG;// цвет G
 float cronaColorB;// цвет B
 float colorR;
 float colorG;
 float colorB;
};
treeObject treeObj [treeQ];

// Структура объекта
struct treeObjectB
{
   int angle;// угол наклона
 float angleX;// по X
 float angleZ;// по Z
 float cronaColorR;// цвет R
 float cronaColorG;// цвет G
 float cronaColorB;// цвет B
 float colorR;
 float colorG;
 float colorB;
};
treeObjectB treeObjB [treeBQ];

#define bushQ 35
// Структура объекта
struct bushObject
{
   int type;
 float colorR;
 float colorG;
 float colorB;
};
bushObject bushObj [bushQ];

#define barrelQ 5
// Структура объекта
struct barrelObject
{
 float angle;
 float x;
 float z;
};
barrelObject barrelObj [barrelQ];

#define crateQ 5
// Структура объекта
struct crateObject
{
 int q;
 float angle1;
 float angle2;
};
crateObject crateObj [crateQ];

#define hillQ 2
// Структура объекта
struct hillObject
{
  char hillAr [32] [32];
   int hillZq;
   int hillXq;
   int hillCells;
 float hillHk;
 float hillBottom;
};
hillObject hillObj [hillQ];

#define mapQ 100
#define mapBQ 62// max visibility + max object size; 32
unsigned char map [mapQ] [mapQ];
unsigned char mapB [mapBQ] [mapBQ];// submap for large objects
unsigned char mapExt [mapQ] [mapQ];// map for trees
unsigned char mapH [mapQ+1] [mapQ+1];
int mapBX, mapBZ;
int villageX=mapQ/2, villageZ=mapQ/2;
int mapX=villageX, mapZ=villageZ;
int squareS=21;// visibile field
int sleep1=15, sleep2=10;
int visMode=0;

float mapHk=25.0f, mapHy=0.0f, mapHLy=0.0f;

char mb [64];

// Make the class name into a global variable
char szClassName []="OpenGL App";
char title []="Walker";

WNDCLASS wc;
HWND hWnd;
HINSTANCE gThisInstance; int gFunsterStil;
HDC hDC;
HGLRC hRC;        
MSG msg;
PAINTSTRUCT PaintStruct;
COLORREF bGround=RGB (0, 0, 0);
HFONT font, fontTitle;// Идентификатор фонта
GLYPHMETRICSFLOAT gmf [256];// Массив с информацией о нашем шрифте
POINT mypoint;
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

 void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC, GLuint pf);
 void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC);
 void InitGL ();
  int InitMultisample ();
 void LoadGLTextures ();
 void timeColor ();
 void timeSet ();
 void setWind ();
 void setFog ();
 void skyFog ();
 void BuildFont ();
 void KillFont();
 void glPrint ();
 void BuildLists ();
 void getScr ();
 bool fullScr (int fsWidth, int fsHeight, int fsBits);
 void setRes ();
 void screenSet ();
 void screenUp ();
 void keysOff ();
 void loading ();
 void loadMap ();
  int seekMap ();
float objFar ();
  int objSnd ();
 bool isMapped (int iZ, int iX);
 bool isEmpty (int iZ, int iX);
 bool isStone (int iZ, int iX);
 void steps ();
 void go ();
 void turn ();
 void look ();
 void lookOff ();
 void paint ();
 void view ();
 void column ();
 void columnCyl ();
 void crystal ();
 void crystalSnd ();
 void wall ();
 void wallX ();
 void wallXl ();
 void wallXr ();
 void fence ();
 void road ();
 void border ();
 void corner ();
 void bush ();
 void tree ();
 void treeB ();
 void treeWind ();
 void treeSnd1 ();
 void treeSnd2 ();
 void grass ();
 void grassH (int mapNZ, int mapNX);
 void hill ();
 void hillH (int hillX, int hillZ, int hillSV);
 void barrel ();
 void well ();
 void wellSnd ();
 void bench ();
 void crates ();
 void crateSmall ();
 void cellar ();
 void house ();
 void sky ();
 void pointer ();
 void fpsC ();
float fpsTweak ();
 void visOn ();
 void myColor3f (float myColorR, float myColorG, float myColorB);
 void statusBar ();
 void hitEsc ();
 void menuOut ();
 void menuBack ();
 void saveConf ();
 void loadConf ();

const unsigned int TIMER_AMBIENT=5, TIMER_CURSOR=10, TIMER_DAY=15;

char AppDir [_MAX_PATH];
int soundVol=0, meloVol=0;
bool soundOn=false, meloIs=false, audioOnce=false;
#include "sound.h"
#include "melody.h"



/**************************
 * WinMain
 *
 **************************/

int WINAPI WinMain (HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int iCmdShow)
{
 int i;

 gThisInstance=hInstance;
 gFunsterStil=iCmdShow;

 char AppPath [_MAX_PATH];
 int ap_l=0;
 memset (AppPath, 0, _MAX_PATH);
 memset (AppDir, 0, _MAX_PATH);
 GetModuleFileName (NULL, AppPath, _MAX_PATH);
 for (i=_MAX_PATH-1; i>=0 && ap_l==0; i--)
 {
  if (AppPath [i]=='\\')
   ap_l=i+1;
 }

 memcpy (AppDir, AppPath, ap_l);

 memset (mb, 0, 64);

 // initialize random seed:
 srand (time (NULL));

 getScr ();

 loadMap ();
 loadConf ();

 visOn ();

 timeSet ();
 timeColor ();
 setWind ();

 if (dmN==0)
 {
  dmWs=dmW0;
  dmHs=dmH0;
  dmBs=dmB0;
 }
 else
 {
  dmWs=dmW [dmN-1];
  dmHs=dmH [dmN-1];
  dmBs=dmB [dmN-1];

  if (!(dmWs==dmW0 && dmHs==dmH0 && dmBs==dmB0))// !same res
   fullScr (dmWs, dmHs, dmBs);
 }

 screenSet ();

 // register window class
 wc.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
 wc.lpfnWndProc=WndProc;
 wc.cbClsExtra=0;
 wc.cbWndExtra=0;
 wc.hInstance=hInstance;
 wc.hIcon=LoadIcon (hInstance, MAKEINTRESOURCE(ID_PIC));
 wc.hCursor=LoadCursor (NULL, IDC_ARROW);
 wc.hbrBackground=(HBRUSH)CreateSolidBrush (bGround);
 wc.lpszMenuName=NULL;
 wc.lpszClassName=szClassName;
 RegisterClass (&wc);

 for (i=0; i<2; i++)
 {
  hWnd=CreateWindowEx (
   0,           // Extended possibilites for variation
   szClassName, // Classname
   title,       // Title Text
   WS_POPUP,    // No caption & borders
   -1,          // Program decides the position
   -1,          // where the window ends up on the screen
   cx+2,        // The programs width
   cy+2,        // and height in pixels
   HWND_DESKTOP,// The window is a child-window to desktop
   NULL,        // No menu
   hInstance,   // Program Instance handler
   NULL         // No Window Creation data
  );

  if (i==0)
  {
   EnableOpenGL (hWnd, &hDC, &hRC, 0);
   PixelFormat=InitMultisample ();
   if (PixelFormat==0)
    break;
   DestroyWindow (hWnd);
  }
  else
   EnableOpenGL (hWnd, &hDC, &hRC, PixelFormat);
 }

 if (PixelFormat!=0)
 {
  for (i=menuL0-1; i>7; i--)
   sprintf (menuAr0 [i+1], "%s", menuAr0 [i]);

  sprintf (menuAr0 [8], "Сглаживать");
  menuL0++;
 }

 menuL=menuL0;

 for (i=0; i<menuL; i++)
  sprintf (menuAr [i], "%s", menuAr0 [i]);
  
 ShowWindow (hWnd, iCmdShow);
 SetForegroundWindow (hWnd);// Слегка повысим приоритет
 SetFocus (hWnd);// Установить фокус клавиатуры на наше окно
 InitGL ();

 soundInit ();
 meloInit ();
 SetTimer (hWnd, TIMER_AMBIENT, 1000, NULL);
 SetTimer (hWnd, TIMER_CURSOR, 500, NULL);
 SetTimer (hWnd, TIMER_DAY, 10000, NULL);

 loaded=true;

 // program main loop
 while (!bQuit)
 {
  // check for messages
  if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
  {
   // handle or dispatch messages
   if (msg.message==WM_QUIT)
    bQuit=true;
   else
   {
    TranslateMessage (&msg);
    DispatchMessage (&msg);
   }
  }
  if (!bQuit)
  {
   if (!blur_on)
   {
    if (!menuOn)
    {
     look ();
     turn ();
     go ();
    }

    paint ();
   }
  }

  if (audioOnce)// more FPS
   Sleep (sleep1);
  else
   Sleep (sleep2);
 }

 saveConf ();

 meloClose ();

 KillFont ();// Удаление шрифта

 // shutdown OpenGL
 DisableOpenGL (hWnd, hDC, hRC);

 ChangeDisplaySettings (NULL, 0);// Переключаемся обратно в оконный режим
 if (hRC)// Существует ли Контекст Рендеринга?
 {
  wglMakeCurrent (NULL, NULL);
  wglDeleteContext (hRC);
 }
 ReleaseDC (hWnd, hDC);// Возможно ли уничтожить DC?
 UnregisterClass (szClassName, gThisInstance);

 // destroy the window explicitly
 DestroyWindow (hWnd);

 return msg.wParam;
}

/********************
 * Window Procedure
 *
 ********************/

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)
 {
  case WM_CLOSE:
   PostQuitMessage (0);
   return 0;

  case WM_DESTROY:
   return 0;

  case WM_KILLFOCUS:
   keysOff ();

   meloBlurOn=true;
   blur_on=true;
   break;

  case WM_SETFOCUS:
   if (noRest==true || loaded==false)
    break;

   fpsOn=0;
   clockL=0;

   screenSet ();
   if (cx!=dmW0 || cy!=dmH0)
   {
    getScr ();
    dmN=0;
    dmWs=dmW0;
    dmHs=dmH0;
    dmBs=dmB0;
    screenUp ();
   }
   else
    SetWindowPos (hWnd, HWND_TOP, -1, -1, cx+2, cy+2, SWP_NOMOVE);// ?

   meloBlurOff=true;
   blur_on=false;
   break;

  case WM_SIZE:
   switch (wParam)
   {
    case SIZE_RESTORED:
     if (blur_on)
      break;

     if (noRest==true || loaded==false)
      break;

     screenSet ();
     if (cx!=dmW0 || cy!=dmH0)
     {
      getScr ();
      dmN=0;
      dmWs=dmW0;
      dmHs=dmH0;
      dmBs=dmB0;
      screenUp ();
     }
     else
      SetWindowPos (hWnd, HWND_TOP, -1, -1, cx+2, cy+2, SWP_NOMOVE);// ?

     break;
   }
   break;

  case WM_PAINT:
   BeginPaint(hWnd, &PaintStruct);
   if (blur_on && loaded)
   {
    hDC=GetDC (hWnd);
    paint ();
    ReleaseDC (hWnd, hDC);
   }
   EndPaint (hWnd, &PaintStruct);
   break;

  case WM_TIMER:
   if ((menuOn || blur_on) && wParam!=TIMER_CURSOR)
    break;

   switch (wParam)
   {
    case TIMER_AMBIENT:
     if (!isMapped (mapZ, mapX) && rand()%5==1)
     {
      if (rand()%2==1)
       playSound ("wind_one");
      else
       playSound ("wind_two");
     }
     break;

    case TIMER_DAY:
     if (timeOfDay==5)
     {
      timeSet ();
      timeColor ();
     }
     break;

    case TIMER_CURSOR:
     KillTimer (hWnd, TIMER_CURSOR);
     GetCursorPos (&mypoint);
     SetCursorPos (mypoint.x, mypoint.y);
     ShowCursor (false);
     break;
   }
   break;

  case WM_KEYDOWN:

   hitEscZ=hitEscTill;

   if (infoOn && !((wParam==81 || wParam==VK_CONTROL || wParam==87 || wParam==73 || wParam==80) && infoOn==1)
              && !((wParam==VK_RETURN || wParam==VK_SPACE || wParam==VK_CLEAR) && keyLockEnter))
   {
    if (infoOn==3 || infoOn==4)
    {
     if (infoPage<infoPages)
     {
      infoPage++;

      playSound ("shake");
     }
     else
     {
      infoPage=1;

      playSound ("turn_off");
      infoOn=0;
     }
    }
    else
    {
     playSound ("turn_off");
     infoOn=0;
    }
    break;
   }

   switch (wParam)
   {
    case 81:
     if (ctrl_key)
      PostQuitMessage(0);
     break;

    case VK_ESCAPE:
     if (keyLockEsc)
      break;

     if (!menuOn)
     {
      keysOff ();

      playSound ("menu_on");
      menuOn=true;
     }
     else
     {
      if (subOn)
      {
       menuBack ();
       playSound ("menu_off");
      }
      else
      {
       playSound ("menu_off");
       menuOn=false;
      }
     }
     keyLockEsc=true;
     break;

    case VK_RIGHT:
     if (menuOn)
     {
      if (!strcmp ("Звук", menuAr [menuSel]))
      {
       soundOn=true;
       soundVol+=100;
       if (soundVol>1000)
        soundVol=1000;
       else
        playSound ("turn_on");
      }
      else if (!strcmp ("Мелодия", menuAr [menuSel]))
      {
       if (meloVol<1000)
       {
        if (meloVol==0)
         meloTurnOn=true;

        meloVol+=100;
        if (meloVol>1000)
         meloVol=1000;

        playSound ("turn_on");
       }
      }
      else if (!strcmp ("Видимость", menuAr [menuSel]))
      {
       if (visMode<2)
       {
        visMode++;

        visOn ();
        playSound ("turn_on");
       }
      }
      break;
     }

     keyRight=true;
     break;

    case VK_LEFT:
     if (menuOn)
     {
      if (!strcmp ("Звук", menuAr [menuSel]))
      {
       soundVol-=100;
       if (soundVol<0)
        soundVol=0;
       else
        playSound ("turn_off");

       if (soundVol==0)
        soundOn=false;
      }
      else if (!strcmp ("Мелодия", menuAr [menuSel]))
      {
       if (meloVol>0)
       {
        meloVol-=100;
        if (meloVol<0)
         meloVol=0;

        playSound ("turn_off");

        if (meloVol==0)
         meloTurnOff=true;
       }
      }
      else if (!strcmp ("Видимость", menuAr [menuSel]))
      {
       if (visMode>0)
       {
        visMode--;

        visOn ();
        playSound ("turn_off");
       }
      }
      break;
     }

     keyLeft=true;
     break;

    case VK_NEXT:
     if (menuOn)
     {
      if (menuFrom<menuL-menuQ)
      {
       menuSel+=menuQ;
       menuFrom+=menuQ;
       if (menuFrom>menuL-menuQ)
       {
        menuSel-=menuFrom-(menuL-menuQ);
        menuFrom=menuL-menuQ;
       }
       playSound ("select");
      }
      else
      {
       if (menuSel!=menuL-1)
        playSound ("select");
       menuSel=menuL-1;
      }
      break;
     }

     keyLookDown=true;
     break;

    case VK_PRIOR:
     if (menuOn)
     {
      if (menuFrom>0)
      {
       menuSel-=menuQ;
       menuFrom-=menuQ;
       if (menuFrom<0)
       {
        menuSel-=menuFrom;
        menuFrom=0;
       }
       playSound ("select");
      }
      else
      {
       if (menuSel!=0)
        playSound ("select");
       menuSel=0;
      }
      break;
     }

     keyLookUp=true;
     break;

    case VK_CLEAR:
     if (menuOn)
      break;

     if (angleX==0.0f)
      break;

     keyLookOff=true;
     break;

    case VK_UP:
     if (menuOn)
     {
      if (menuSel>0)
      {
       menuSel--;
       if (menuSel<menuFrom)
        menuFrom=menuSel;
       menuR=0;
       playSound ("select");
      }
     }
     else
      keyUp=true;
     break;

    case VK_DOWN:
     if (menuOn)
     {
      if (menuSel<menuL-1)
      {
       menuSel++;
       if (menuSel>menuFrom+menuQ-1)
        menuFrom=menuSel-menuQ+1;
       menuR=0;
       playSound ("select");
      }
     }
     else
      keyDown=true;
     break;

    case VK_HOME:
     if (menuOn)
     {
      if (menuSel>0)
      {
       menuSel=0;
       menuFrom=0;
       menuR=0;
       playSound ("select");
      }
     }
     break;

    case VK_END:
     if (menuOn)
     {
      if (menuSel<menuL-1)
      {
       menuSel=menuL-1;
       if (menuFrom<menuSel-menuQ+1)
        menuFrom=menuSel-menuQ+1;
       menuR=0;
       playSound ("select");
      }
     }
     break;

    case VK_CONTROL:
     ctrl_key=true;
     break;

    case 87:
     if (keyLockW==false)
     {
      if (walkIs==true)
      {
       walkIs=false;
       playSound ("turn_off");
      }
      else
      {
       walkbiasangle=90;
       // Имитация походки человека
       walkbias=(float)sin (walkbiasangle*rad)*walkbiasK;
       walkIs=true;
       playSound ("turn_on");
      }

      keyLockW=true;
     }
     break;

    case 73:
     if (keyLockI==false)
     {
      if (statusOn==true)
      {
       statusOn=false;
       playSound ("turn_off");
      }
      else
      {
       statusOn=true;
       playSound ("turn_on");
      }

      keyLockI=true;
     }
     break;

    case 80:
     if (keyLockC==false)
     {
      if (pointerOn==true)
      {
       pointerOn=false;
       playSound ("turn_off");
      }
      else
      {
       pointerOn=true;
       playSound ("turn_on");
      }

      keyLockC=true;
     }
     break;
   }

   if ((wParam==VK_RETURN || wParam==VK_SPACE || wParam==VK_CLEAR) && !keyLockEnter)
   {
    if (menuOn)
    {
     if (subOn==1)
     {
      if (menuSel<=dmC && dmN!=menuSel)
      {
       dmN=menuSel;

       if (dmN==0)
       {
        dmWt=dmW0;
        dmHt=dmH0;
        dmBt=dmB0;
       }
       else
       {
        dmWt=dmW [dmN-1];
        dmHt=dmH [dmN-1];
        dmBt=dmB [dmN-1];
       }

       if (!(dmWt==dmWs && dmHt==dmHs && dmBt==dmBs))// !same res
       {
        dmWs=dmWt;
        dmHs=dmHt;
        dmBs=dmBt;
        fullScr (dmWs, dmHs, dmBs);
        fpsOn=0;
        clockL=0;
        screenSet ();
        screenUp ();
        meloBlurOff=true;
        blur_on=false;
       }
      }
      else if (!strcmp ("Вернуться", menuAr [menuSel]))
      {
       menuBack ();
       playSound ("turn_off");
      }
     }
     else if (!strcmp ("Идти", menuAr [menuSel]))
     {
      playSound ("menu_off");
      menuOn=false;
     }
     else if (!strcmp ("История", menuAr [menuSel]))
     {
      playSound ("shake");
      infoOn=4;
     }
     else if (!strcmp ("Клавиши", menuAr [menuSel]))
     {
      playSound ("shake");
      infoOn=1;
     }
     else if (!strcmp ("Звук", menuAr [menuSel]))
     {
      if (soundVol<1000)
      {
       soundVol+=200;
       if (soundVol>1000)
        soundVol=1000;
       soundOn=true;
       playSound ("turn_on");
      }
      else
      {
       soundVol=0;
       soundOn=false;
      }
     }
     else if (!strcmp ("Мелодия", menuAr [menuSel]))
     {
      if (meloVol<1000)
      {
       if (meloVol==0)
        meloTurnOn=true;

       meloVol+=200;
       if (meloVol>1000)
        meloVol=1000;
       playSound ("turn_on");
      }
      else
      {
       meloVol=0;
       meloTurnOff=true;
       playSound ("turn_off");
      }
     }
     else if (!strcmp ("Время", menuAr [menuSel]))
     {
      timeOfDay++;
      if (timeOfDay>5)
      {
       timeOfDay=1;
       playSound ("turn_off");
      }
      else
       playSound ("turn_on");

      timeSet ();
      timeColor ();
     }
     else if (!strcmp ("Походка", menuAr [menuSel]))
     {
      if (walkIs==true)
      {
       walkIs=false;
       playSound ("turn_off");
      }
      else
      {
       walkbiasangle=90;
       // Имитация походки человека
       walkbias=(float)sin(walkbiasangle*rad)*walkbiasK;
       walkIs=true;
       playSound ("turn_on");
      }
     }
     else if (!strcmp ("Статус", menuAr [menuSel]))
     {
      if (statusOn==true)
      {
       statusOn=false;
       playSound ("turn_off");
      }
      else
      {
       statusOn=true;
       playSound ("turn_on");
      }
     }
     else if (!strcmp ("Сглаживать", menuAr [menuSel]))
     {
      multisampleOn++;
      if (multisampleOn>2)
      {
       multisampleOn=0;
       playSound ("turn_off");
      }
      else
       playSound ("turn_on");

      if (multisampleOn==0)
       glDisable (GL_MULTISAMPLE_ARB);
      else if (multisampleOn==2)
       glEnable (GL_MULTISAMPLE_ARB);// Enable Our Multisampling
     }
     else if (!strcmp ("Видимость", menuAr [menuSel]))
     {
      visMode++;
      if (visMode>2)
      {
       visMode=0;
       playSound ("turn_off");
      }
      else
       playSound ("turn_on");

      visOn ();
     }
     else if (!strcmp ("Разрешение", menuAr [menuSel]))
     {
      menuL=dmC+2; menuSel0=menuSel; menuFrom0=menuFrom; menuSel=0; menuFrom=0; menuS=-1;
      sprintf (menuAr [0], "Системное");
      for (int i=0; i<dmC; i++)
      {
       if (dmBitsOff)
        sprintf (menuAr [i+1], "%dx%d", dmW [i], dmH [i]);
       else
        sprintf (menuAr [i+1], "%dx%d %d", dmW [i], dmH [i], dmB [i]);
      }
      sprintf (menuAr [menuL-1], "Вернуться");

      playSound ("turn_on");
      subOn=1;
     }
     else if (!strcmp ("О программе", menuAr [menuSel]))
     {
      playSound ("shake");
      infoOn=2;
     }
     else if (!strcmp ("Спасибо!", menuAr [menuSel]))
     {
      playSound ("shake");
      infoOn=3;
     }
     else if (!strcmp ("Выход", menuAr [menuSel]))
      PostQuitMessage(0);
    }

    keyLockEnter=true;
   }
   return 0;

  case WM_KEYUP:

   switch (wParam)
   {
    case VK_ESCAPE:
     keyLockEsc=false;
     break;

    case VK_UP:
     if (menuOn)
      break;

     keyUp=false;
     break;

    case VK_DOWN:
     if (menuOn)
      break;

     keyDown=false;
     break;

    case VK_LEFT:
     if (menuOn)
      break;

     keyLeftC=0.0f;
     keyLeft=false;
     break;

    case VK_RIGHT:
     if (menuOn)
      break;

     keyRightC=0.0f;
     keyRight=false;
     break;

    case VK_NEXT:
     if (menuOn)
      break;

     keyLookDown=false;
     break;

    case VK_PRIOR:
     if (menuOn)
      break;

     keyLookUp=false;
     break;

    case VK_CLEAR:
     if (menuOn)
      break;

     keyLookOff=false;
     break;

    case VK_CONTROL:
     ctrl_key=false;
     break;

    case 87:
     keyLockW=false;
     break;

    case 73:
     keyLockI=false;
     break;

    case 80:
     keyLockC=false;
     break;
   }

   if (wParam==VK_RETURN || wParam==VK_SPACE || wParam==VK_CLEAR)
    keyLockEnter=false;

   return 0;

  default:
   return DefWindowProc (hWnd, message, wParam, lParam);
 }
}

void keysOff ()
{
 keyUp=false;
 keyDown=false;
 keyLeft=false; keyLeftC=0.0f;
 keyRight=false; keyRightC=0.0f;
 keyLookUp=false;
 keyLookDown=false;
 keyLookOff=false;
 ctrl_key=false;
 keyLockI=false;
}

void menuBack ()
{
 menuL=menuL0; menuSel=menuSel0; menuFrom=menuFrom0; menuS=-1;
 for (int i=0; i<menuL; i++)
  sprintf (menuAr [i], "%s", menuAr0 [i]);

 subOn=0;
}

void getScr ()
{
 int i, i2, bitsN=0;
 bool dmRepeat;

 DEVMODE devMode;// Режим устройства
 memset (&devMode, 0, sizeof (devMode));// Очистка для хранения установок
 devMode.dmSize=sizeof (devMode);// Размер структуры Devmode

 for (i=0; EnumDisplaySettings (0, i, &devMode); i++)
 {
  dmRepeat=false;
  for (i2=0; i2<dmC; i2++)
  {
   if (dmW [i2]==devMode.dmPelsWidth && dmH [i2]==devMode.dmPelsHeight && dmB [i2]==devMode.dmBitsPerPel)
    dmRepeat=true;
  }
  if (!dmRepeat)
  {
   if (bitsN==0)
    bitsN=devMode.dmBitsPerPel;
   else if (bitsN!=devMode.dmBitsPerPel)
    dmBitsOff=false;

   dmW [dmC]=devMode.dmPelsWidth;
   dmH [dmC]=devMode.dmPelsHeight;
   dmB [dmC]=devMode.dmBitsPerPel;
   dmC++;
  }
 }

 int swpH, swpW, swpB;
 for (i=0; i<dmC; i++)
 {
  for (i2=i; i2<dmC; i2++)
  {
   if (dmW [i2]>dmW [i] || (dmW [i2]==dmW [i] && dmH [i2]>dmH [i])
   || (dmW [i2]==dmW [i] && dmH [i2]==dmH [i] && dmB [i2]>dmB [i]))
   {
    swpW=dmW [i];
    swpH=dmH [i];
    swpB=dmB [i];

    dmW [i]=dmW [i2];
    dmH [i]=dmH [i2];
    dmB [i]=dmB [i2];

    dmW [i2]=swpW;
    dmH [i2]=swpH;
    dmB [i2]=swpB;
   }
  }
 }

 memset (&devMode, 0, sizeof (devMode));// Очистка для хранения установок
 devMode.dmSize=sizeof (devMode);// Размер структуры Devmode
 EnumDisplaySettings (0, ENUM_CURRENT_SETTINGS, &devMode);
 dmW0=devMode.dmPelsWidth;
 dmH0=devMode.dmPelsHeight;
 dmB0=devMode.dmBitsPerPel;
}

bool fullScr (int fsWidth, int fsHeight, int fsBits)
{
 DEVMODE dmScreenSettings;// Режим устройства
 memset (&dmScreenSettings, 0, sizeof (dmScreenSettings));// Очистка для хранения установок
 dmScreenSettings.dmSize=sizeof (dmScreenSettings);// Размер структуры Devmode
 dmScreenSettings.dmPelsWidth=fsWidth;// Ширина экрана
 dmScreenSettings.dmPelsHeight=fsHeight;// Высота экрана
 dmScreenSettings.dmBitsPerPel=fsBits;// Глубина цвета
 dmScreenSettings.dmFields=DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;// Режим Пикселя
 if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN)!= DISP_CHANGE_SUCCESSFUL)
  return false;
 else
  return true;
}

void screenSet ()
{
 cx=(LONG)::GetSystemMetrics (SM_CXSCREEN);
 cy=(LONG)::GetSystemMetrics (SM_CYSCREEN);

 if (cx<cy)
  cm=cx;
 else
  cm=cy;

 fontS=cm/37;

 fogDist=cos (((float)cx/(float)cy)/(1600.0f/900.0f)*0.633537f)*(squareL*(squareS-1)+squareL/2)+0.5f;
// sndDist=fogDist;
// objDist=fogDist;

 if ((1600.0f/900.0f)>=((float)cx/(float)cy))
  skyDist=cos (0.633537f)*skyL-1.0f;
 else
  skyDist=cos (((float)cx/(float)cy)/(1600.0f/900.0f)*0.633537f)*skyL-1.0f;
}

void screenUp ()
{
 noRest=true;

 SetWindowPos (hWnd, HWND_TOP, -1, -1, cx+2, cy+2, SWP_NOMOVE);

 // shutdown OpenGL
 DisableOpenGL (hWnd, hDC, hRC);
 EnableOpenGL (hWnd, &hDC, &hRC, PixelFormat);
 InitGL ();

 noRest=false;
}

void InitGL ()
{
 glShadeModel (GL_SMOOTH);// Разрешить плавное затенение
 glViewport (0, 0, cx+2, cy+2);
 glMatrixMode (GL_PROJECTION);
 gluPerspective (45.0f, (GLfloat)cx/(GLfloat)cy, 0.1f, 100.0f);

 glClearDepth (1.0);      // Depth Buffer Setup
 glEnable (GL_DEPTH_TEST);// Enables Depth Testing
 glDepthFunc (GL_LEQUAL); // The Type Of Depth Testing To Do

 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 glMatrixMode (GL_MODELVIEW);

 BuildFont ();// Построить шрифт

 if (PixelFormat!=0)
 {
  if (!multisampleOn)
   glDisable (GL_MULTISAMPLE_ARB);
  else if (multisampleOn==2)
   glEnable (GL_MULTISAMPLE_ARB);
 }

 timeColor ();
 loading ();
 LoadGLTextures ();
 glEnable (GL_TEXTURE_2D);

 glEnable (GL_FOG);// Включает туман

 // Функция смешивания для непрозрачности, базирующаяся на значении альфы
 glBlendFunc (GL_SRC_ALPHA, GL_SRC_COLOR);// GL_ONE

 glPolygonMode (GL_BACK, GL_LINE); // нижняя (задняя) сторона прорисована линиями
 glPolygonMode (GL_FRONT, GL_FILL);// верхняя (передняя) сторона заполнена

 quadratic=gluNewQuadric ();// Создаем указатель на квадратичный объект
 gluQuadricNormals (quadratic, GLU_SMOOTH);// Создаем плавные нормали
 gluQuadricTexture (quadratic, GL_TRUE);   // Создаем координаты текстуры

 BuildLists ();// создаем список отображения
}

/*******************
 * Enable OpenGL
 *
 *******************/

void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC, GLuint pf)
{
 PIXELFORMATDESCRIPTOR pfd;
 int iFormat;

 // get the device context (DC)
 *hDC=GetDC (hWnd);

 if (pf==0)
 {
  // set the pixel format for the DC
  ZeroMemory (&pfd, sizeof (pfd));
  pfd.nSize=sizeof (pfd);
  pfd.nVersion=1;
  pfd.dwFlags=PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  pfd.iPixelType=PFD_TYPE_RGBA;
  pfd.cColorBits=dmBs;
  pfd.cDepthBits=24;
  pfd.iLayerType=PFD_MAIN_PLANE;
  iFormat=ChoosePixelFormat (*hDC, &pfd);
  SetPixelFormat (*hDC, iFormat, &pfd);
 }
 else
  SetPixelFormat(*hDC, pf, &pfd);

 // create and enable the render context (RC)
 *hRC=wglCreateContext (*hDC);
 wglMakeCurrent (*hDC, *hRC);
}


/******************
 * Disable OpenGL
 *
 ******************/

void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC)
{
 KillFont ();// Удаление шрифта
 wglMakeCurrent (NULL, NULL);
 wglDeleteContext (hRC);
 ReleaseDC (hWnd, hDC);
}

// читаем изображение и преобразуем его в текстуру
void LoadGLTextures ()
{
 HDC hdcTemp;                 // DC для растра
 HBITMAP hbmpTemp;            // иногда храним в ней растр
 IPicture *pPicture;          // интерфейс IPicture
 OLECHAR wszPath [MAX_PATH+1];// полный путь до картинки (WCHAR)
 long lWidth;                 // ширина в логических единицах
 long lHeight;                // высота в логических единицах
 long lWidthPixels;           // ширина в пикселях
 long lHeightPixels;          // высота в пикселях
 GLint glMaxTexDim ;          // максимальный размер текстуры

 char texs [49] [32]={"blank.gif", "grass.jpg", "road.jpg", "mud.jpg", "sand.jpg", "",
                      "bg.jpg", "sky.jpg", "column.jpg", "wall.jpg",
                      "wood.jpg", "", "house_wall.jpg", "lock.jpg", "glass.jpg",
                      "colcyl.jpg", "tree_bark.jpg", "tree_crona.jpg",
                      "well.jpg", "bush.gif", "house_base.jpg", "bushb.gif",
                      "", "houseb_wall.jpg", "roof.jpg",
                      "", "", "", "",
                      "pine.jpg", "grid.gif", "woodb.jpg", "crate.jpg",
                      "barrel.jpg", "barrel_line.jpg", "barrel_top.jpg",
                      "", "", "road_small.jpg", "road_hub.jpg",
                      "", "",
                      "road_border.jpg",
                      "sand_x.jpg", "sand_y.jpg", "sand_hub.jpg", "sand_road.jpg",
                      "wall_warn.jpg",
                      "treeb_crona.jpg"
                     };
 char texd [16]={"data\\textures"};
 char txt [_MAX_PATH];
 int i2;

 for (i2=0; i2<49; i2++)
 {
  if (strlen (texs [i2]))
  {
   sprintf (txt, "%s%s\\%s", AppDir, texd, texs [i2]);

   MultiByteToWideChar (CP_ACP, 0, txt, -1, wszPath, MAX_PATH);// преобразуем к юникоду
   HRESULT hr=OleLoadPicturePath (wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);

   if (!FAILED (hr)) // Если загрузка удачна
   {
    hdcTemp=CreateCompatibleDC (GetDC (0));// создать совместимый с устройством Windows контекст
    if (!hdcTemp)         // ну что, создали?
      pPicture->Release();// не-а… :( уменьшение счетчика ссылок на IPicture
    else
    {
     // получить максимально возможное разрешение изображения
     glGetIntegerv (GL_MAX_TEXTURE_SIZE, &glMaxTexDim);

     pPicture->get_Width (&lWidth);  // получить ширину изображения
     lWidthPixels=MulDiv (lWidth, GetDeviceCaps (hdcTemp, LOGPIXELSX), 2540);
     pPicture->get_Height (&lHeight);// получить высоту изображения
     lHeightPixels=MulDiv (lHeight, GetDeviceCaps (hdcTemp, LOGPIXELSY), 2540);

     // преобразовать изображение к ближайшей степени двойки
     if (lWidthPixels<=glMaxTexDim)
      // если ширина изображения меньше либо равна максимально-допустимому пределу карточки
      lWidthPixels=1<<(int)floor((log ((double)lWidthPixels)/log (2.0f))+0.5f);
     else
      // иначе установить размер равный максимальной степени двойки,
      // которую поддерживает карточка
      lWidthPixels=glMaxTexDim;
     // то же самое повторяется для высоты
     if (lHeightPixels<=glMaxTexDim)
      lHeightPixels=1<<(int)floor ((log ((double)lHeightPixels)/log (2.0f))+0.5f);
     else
      lHeightPixels=glMaxTexDim;

     // создать временный растр
     BITMAPINFO  bi={0}; // нужный нам тип растра
     DWORD   *pBits=0;   // указатель на биты растра

     bi.bmiHeader.biSize=sizeof (BITMAPINFOHEADER);// размер структуры
     bi.bmiHeader.biBitCount=32;                   // 32 бита
     bi.bmiHeader.biWidth=lWidthPixels;            // ширина кратная степени двойки
     // Сделаем изображение расположенным вверх (положительное направление оси Y)
     bi.bmiHeader.biHeight=lHeightPixels;
     bi.bmiHeader.biCompression=BI_RGB;            // RGB формат
     bi.bmiHeader.biPlanes=1;                      // 1 битовая плоскость 

     // создавая растр, таким образом, мы можем установить глубину цвета,
     // а также получить прямой доступ к битам.
     hbmpTemp=CreateDIBSection (hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);

     if (!hbmpTemp)        // создали?
     {                     // сам вижу что нет
      DeleteDC (hdcTemp);  // убить контекст устройства
      pPicture->Release ();// уменьшить счетчик количества интерфейсов IPicture
     }
     else
     {
      // есть растр!
      SelectObject (hdcTemp, hbmpTemp);// загрузить описатель временного растра
                                       // в описатель временного контекста устройства 
      // отрисовка IPicture в растр
      pPicture->Render (hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);

      long i, n=lWidthPixels*lHeightPixels;
      // преобразовать из BGR в RGB формат и устанавливаем значение
      // Alpha = 255
      if (i2==19 || i2==21 || i2==48)// bushes & treeB
      {
       for (i=0; i<n; i++) // Цикл по всем пикселям
       {
        BYTE* pPixel=(BYTE*)(&pBits[i]);// берем текущий пиксель
        BYTE  temp=pPixel [0];          // сохраняем первый цвет в переменной
                                        // Temp (Синий)
        pPixel [0]=pPixel [2];          // ставим  Красный на место (в первую позицию)
        pPixel [2]=temp;                // ставим значение Temp в третий параметр (3rd)

        if (i2==48)// tree
        {
         if (pPixel [0]>225 && pPixel [1]>225 && pPixel [2]>225)
         {
          pPixel [0]=65;
          pPixel [1]=65;
          pPixel [2]=65;
          pPixel [3]=0;                  // установить значение alpha =0
         }
         else
          pPixel [3]=255;                // установить значение alpha =255
        }
        else
        {
         if (pPixel [0]<10 && pPixel [1]<10 && pPixel [2]<10)
         {
          pPixel [1]=150;
          pPixel [3]=0;                  // установить значение alpha =0
         }
         else
          pPixel [3]=255;                // установить значение alpha =255
        }
       }
      }
      else if (i2==30)// grid
      {
       for (i=0; i<n; i++) // Цикл по всем пикселям
       {
        BYTE* pPixel=(BYTE*)(&pBits [i]);// берем текущий пиксель
        BYTE  temp=pPixel [0];           // сохраняем первый цвет в переменной
                                         // Temp (Синий)
        pPixel [0]=pPixel [2];           // ставим  Красный на место (в первую позицию)
        pPixel [2]=temp;                 // ставим значение Temp в третий параметр (3rd)

        if (pPixel [0]<10 && pPixel [1]<10 && pPixel [2]<10)
        {
         pPixel [0]=155;
         pPixel [1]=155;
         pPixel [2]=155;
         pPixel [3]=0;                  // установить значение alpha =0
        }
        else
         pPixel [3]=255;                // установить значение alpha =255
       }
      }
      else
      {
       for (i=0; i<n; i++)// Цикл по всем пикселям
       {
        BYTE* pPixel=(BYTE*)(&pBits[i]);// берем текущий пиксель
        BYTE  temp=pPixel [0];          // сохраняем первый цвет в переменной
                                        // Temp (Синий)
        pPixel [0]=pPixel [2];          // ставим  Красный на место (в первую позицию)
        pPixel [2]=temp;                // ставим значение Temp в третий параметр (3rd)
        pPixel [3]=255;                 // установить значение alpha =255
       }
      }

      glGenTextures (1, &texture [i2]);//  создаем текстуру texid

      // типичная генерация текстуры, используя данные из растра
      glBindTexture (GL_TEXTURE_2D, texture [i2]);// делаем привязку к texid

      if (i2==25 || i2==26)// x
       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      else if (i2==27 || i2==28 || i2==40 || i2==41)// z
       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      else if (i2==39)
      {
       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      }

      // (измените для нужного вам типа фильтрации)
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      // (измените, если хотите использовать мипмап-фильтрацию) 
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      // (мипмап - множественное отображение (последовательность текстур одного
      //  и того же изображения с уменьшающимся разрешением по мере удаления отображаемого
      // объекта от наблюдателя))

      glTexImage2D (GL_TEXTURE_2D, 0, 4, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);

      DeleteObject (hbmpTemp);// удаляем объект
      DeleteDC (hdcTemp);     // удаляем контекст устройства

      pPicture->Release();    //уменьшает счетчик IPicture
     }
    }
   }
  }
 }
}

int InitMultisample()
{
 // Get Our Pixel Format
 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
 wglChoosePixelFormatARB=(PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress ("wglChoosePixelFormatARB");
 if (!wglChoosePixelFormatARB)
  return 0;

 HDC hDC=GetDC(hWnd);
 int pixelFormat;
 UINT numFormats;
 float fAttributes []={0, 0};

 // These Attributes Are The Bits We Want To Test For In Our Sample
 // Everything Is Pretty Standard, The Only One We Want To 
 // Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
 // These Two Are Going To Do The Main Testing For Whether Or Not
 // We Support Multisampling On This Hardware.
 int iAttributes[] = {
  WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
  WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
  WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
  WGL_COLOR_BITS_ARB, dmBs,
  WGL_ALPHA_BITS_ARB, 8,
  WGL_DEPTH_BITS_ARB, 24,
  WGL_STENCIL_BITS_ARB, 0,
  WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
  WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
  WGL_SAMPLES_ARB, 6,
  0, 0};

 // First We Check To See If We Can Get A Pixel Format For 6 Samples
 int r=wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);

 // If We Returned False, Or Our Format Count Is Less Than 1
 if (!(r && numFormats>=1))
 {
  // Our Pixel Format With 6 Samples Failed, Test For 4 Samples
  iAttributes [19]=4;
  r=wglChoosePixelFormatARB (hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
  if (!(r && numFormats>=1))
  {
   // Our Pixel Format With 4 Samples Failed, Test For 2 Samples
   iAttributes [19]=2;
   r=wglChoosePixelFormatARB (hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
   if (!(r && numFormats>=1))
 	return 0;
  }
 }    

 return pixelFormat;
}

void timeColor ()
{
 glClearColor (0.5f*gamma, 0.5f*gamma, 0.5f*gamma, 1.0f);

 GLfloat LightAmbient []={gammaR, gammaG, gammaB, gamma};// Значения фонового света
 GLfloat LightDiffuse []={gammaR, gammaG, gammaB, gamma};// Значения диффузного света
 GLfloat LightPosition []={0.0f, 0.0f, 1.0f, 1.0f};      // Позиция света

 glLightfv (GL_LIGHT1, GL_AMBIENT, LightAmbient);  // Установка Фонового Света
 glLightfv (GL_LIGHT1, GL_DIFFUSE, LightDiffuse);  // Установка Диффузного Света
 glLightfv (GL_LIGHT1, GL_POSITION, LightPosition);// Позиция света
 glEnable (GL_LIGHT1); // Разрешение источника света номер один
}

void timeSet ()
{
 if (timeOfDay==1)
 {
  gamma=0.5f;
  gammaR=gamma*1.5f;
  gammaG=gamma;
  gammaB=gamma*1.2f;
 }
 else if (timeOfDay==2)
 {
  gamma=1.0f;
  gammaR=gamma;
  gammaG=gamma;
  gammaB=gamma;
 }
 else if (timeOfDay==3)
 {
  gamma=0.35f;
  gammaR=gamma*1.5f;
  gammaG=gamma*1.2f;
  gammaB=gamma;
 }
 else if (timeOfDay==4)
 {
  gamma=0.1f;
  gammaR=gamma;
  gammaG=gamma;
  gammaB=gamma;
 }
 else if (timeOfDay==5)
 {
  char timeStr [9], timeH [3], timeM [3];
  float time1, time2, timeF,
        gammaMor=0.35f, gammaDay=1.0f, gammaEv=0.35f, gammaNight=0.1f,
        gammaMorR=1.5f, gammaDayR=1.0f, gammaEvR=1.5f, gammaNightR=1.0f,
        gammaMorG=1.0f, gammaDayG=1.0f, gammaEvG=1.2f, gammaNightG=1.0f,
        gammaMorB=1.2f, gammaDayB=1.0f, gammaEvB=1.0f, gammaNightB=1.0f;

  memset (timeH, 0, 3);
  memset (timeM, 0, 3);

  _strtime (timeStr);
  timeH [0]=timeStr [0];
  timeH [1]=timeStr [1];
  timeM [0]=timeStr [3];
  timeM [1]=timeStr [4];
  time1=atof (timeH);
  time2=atof (timeM)/60.0f;
  timeF=time1+time2;

  // 6-12: morning, 12-18: day, 18-24: ev, 00-6: night
  if (timeF>=6.0f && timeF<=12.0f)
  {
   gamma=gammaMor+(gammaDay-gammaMor)*(timeF-6.0f)/6.0f;
   gammaR=gammaMorR+(gammaDayR-gammaMorR)*(timeF-6.0f)/6.0f;
   gammaG=gammaMorG+(gammaDayG-gammaMorG)*(timeF-6.0f)/6.0f;
   gammaB=gammaMorB+(gammaDayB-gammaMorB)*(timeF-6.0f)/6.0f;
  }
  else if (timeF>=12.0f && timeF<=18.0f)
  {
   gamma=gammaDay+(gammaEv-gammaDay)*(timeF-12.0f)/6.0f;
   gammaR=gammaDayR+(gammaEvR-gammaDayR)*(timeF-12.0f)/6.0f;
   gammaG=gammaDayG+(gammaEvG-gammaDayG)*(timeF-12.0f)/6.0f;
   gammaB=gammaDayB+(gammaEvB-gammaDayB)*(timeF-12.0f)/6.0f;
  } 
  else if (timeF>=18.0f && timeF<=24.0f)
  {
   gamma=gammaEv+(gammaNight-gammaEv)*(timeF-18.0f)/6.0f;
   gammaR=gammaEvR+(gammaNightR-gammaEvR)*(timeF-18.0f)/6.0f;
   gammaG=gammaEvG+(gammaNightG-gammaEvG)*(timeF-18.0f)/6.0f;
   gammaB=gammaEvB+(gammaNightB-gammaEvB)*(timeF-18.0f)/6.0f;
  } 
  else if (timeF>=0.0f && timeF<=6.0f)
  {
   gamma=gammaNight+(gammaMor-gammaNight)*(timeF-0.0f)/6.0f;
   gammaR=gammaNightR+(gammaMorR-gammaNightR)*(timeF-0.0f)/6.0f;
   gammaG=gammaNightG+(gammaMorG-gammaNightG)*(timeF-0.0f)/6.0f;
   gammaB=gammaNightB+(gammaMorB-gammaNightB)*(timeF-0.0f)/6.0f;
  } 

  gammaR*=gamma;
  gammaG*=gamma;
  gammaB*=gamma;
 }
}

void visOn ()
{
 if (visMode==0)
 {
  squareS=21;
  sleep1=15;
  sleep2=10;
 }
 else if (visMode==1)
 {
  squareS=31;
  sleep1=12;
  sleep2=7;
 }
 else
 {
  squareS=51;
  sleep1=10;
  sleep2=5;
 }

 if (loaded)
 {
  screenSet ();
  BuildLists ();
 }
}

void setWind ()
{
 treeWindX=float (rand ()%100)/100.0f;
 treeWindZ=float (rand ()%100)/100.0f;
 if (rand ()%2==1)
  treeWindDir=1;
 else
  treeWindDir=-1;
}

void setFog ()
{
 GLfloat fogColor [4]={0.5f*gamma, 0.5f*gamma, 0.5f*gamma, 1.0f};// Цвет тумана

 glFogi (GL_FOG_MODE, fogMode [2]);  // Выбираем тип тумана
 glFogfv (GL_FOG_COLOR, fogColor);   // Устанавливаем цвет тумана
 glFogf (GL_FOG_DENSITY, 0.35f);     // Насколько густым будет туман
 glHint (GL_FOG_HINT, GL_NICEST);    // Вспомогательная установка тумана DONT_CARE
 glFogf (GL_FOG_START, fogDist-5.0f);// Глубина, с которой начинается туман
 glFogf (GL_FOG_END, fogDist);       // Глубина, где туман заканчивается.
}

void skyFog ()
{
 GLfloat fogColor [4]={0.5f*gamma, 0.5f*gamma, 0.5f*gamma, 1.0f};// Цвет тумана

 glFogi (GL_FOG_MODE, fogMode [2]);          // Выбираем тип тумана
 glFogfv (GL_FOG_COLOR, fogColor);           // Устанавливаем цвет тумана
 glFogf (GL_FOG_DENSITY, 0.65f);             // Насколько густым будет туман
 glHint (GL_FOG_HINT, GL_NICEST);            // Вспомогательная установка тумана DONT_CARE GL_FASTEST
 glFogf (GL_FOG_START, skyDist-skyDist/2.5f);// Глубина, с которой начинается туман
 glFogf (GL_FOG_END, skyDist-skyDist/10.0f); // Глубина, где туман заканчивается.
}

void BuildFont ()// Построение нашего растрового шрифта
{
 base=glGenLists (256);// массив для 256 букв

 font=CreateFont (-fontS,                   // Высота фонта
                  0,                        // Ширина фонта
                  0,                        // Угол отношения
                  0,                        // Угол наклона
                  FW_BOLD,                  // Ширина шрифта
                  false,                    // Курсив
                  false,                    // Подчеркивание
                  false,                    // Перечеркивание
                  RUSSIAN_CHARSET,          // Идентификатор набора символов ANSI_CHARSET
                  OUT_TT_PRECIS,            // Точность вывода
                  CLIP_DEFAULT_PRECIS,      // Точность отсечения
                  ANTIALIASED_QUALITY,      // Качество вывода
                  FF_DONTCARE|DEFAULT_PITCH,// Семейство и шаг
                  "Courier New");           // Имя шрифта

 SelectObject (hDC, font);// Выбрать шрифт, созданный нами

 wglUseFontOutlines (hDC,        // Выбрать текущий контекст устройства (DC)
               0,                // Стартовый символ
               256,              // Количество создаваемых списков отображения
               base,             // Стартовое значение списка отображения
               0.0f,             // Отклонение от настоящего контура
               0.0f,             // Толщина шрифта по оси Z
               WGL_FONT_POLYGONS,// Использовать полигоны, а не линии WGL_FONT_LINES
               gmf);             // буфер адреса для данных списка отображения
}

void KillFont ()// Удаление шрифта
{
 glDeleteLists (base, 256); // Удаление всех 256 списков отображения
}

void glPrint (const char *fmt, ...)// Заказная функция «Печати» GL
{
 float length=0; // Переменная для нахождения физической длины текста
 char text [256];// Здесь наша строка
 va_list ap;     // Указатель на переменный список аргументов
 if (fmt==NULL)  // Если нет текста
  return;        // Ничего не делать

 va_start (ap, fmt);         // Анализ строки на переменные
 vsprintf (text, fmt, ap);   // И конвертация символов в реальные коды
 va_end (ap);                // Результат сохраняется в text

 for (int i=0; i<strlen (text); i++)// %
 {
  if (text [i]==17)
   text [i]=37;
 }

 for (unsigned int loop=0; loop<(strlen (text)); loop++)// Цикл поиска размера строки
  length+=gmf [(unsigned char)text [loop]].gmfCellIncX; // Увеличение размера на ширину символа
 glTranslatef (-length/2, 0.0f, 0.0f);                  // Центровка на экране нашей строки

 if (PixelFormat!=0 && multisampleOn==1)
  glEnable (GL_MULTISAMPLE_ARB);// Enable Our Multisampling
 glPushAttrib (GL_LIST_BIT);    // Сохраняет в стеке значения битов списка отображения
 glListBase (base);             // Устанавливает базовый символ в 0

 // Создает списки отображения текста
 glCallLists (strlen (text), GL_UNSIGNED_BYTE, text);
 glPopAttrib ();// Восстанавливает значение Display List Bits
 if (PixelFormat!=0 && multisampleOn==1)
  glDisable (GL_MULTISAMPLE_ARB);

 glTranslatef (-length/2, 0.0f, 0.0f);// Центровка на экране нашей строки
}

GLuint grassList, roadList, desertList, skyList, borderLowList, borderHighList,
       bushList [2], cronaList, crateList [2];// Память для списка отображения
void BuildLists ()// создаем список отображения
{
 int i;

 grassList=glGenLists (12);// создаем списки
 glNewList (grassList, GL_COMPILE);// Новый откомпилированный список отображения
 glBindTexture (GL_TEXTURE_2D, texture [1]);
 glBegin (GL_QUADS);
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-squareL, 0.0f, -squareL);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-squareL, 0.0f,  squareL);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( squareL, 0.0f,  squareL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( squareL, 0.0f, -squareL);// Верх право
 glEnd ();
 glEndList ();// Закончили создание списка

 roadList=grassList+1;// Значение roadList это значение groundList + 1
 glNewList (roadList, GL_COMPILE);// Новый откомпилированный список отображения 'roadList'
 glBindTexture (GL_TEXTURE_2D, texture [2]);
 glBegin (GL_QUADS);
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-squareL, 0.0f, -squareL);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-squareL, 0.0f,  squareL);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( squareL, 0.0f,  squareL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( squareL, 0.0f, -squareL);// Верх право
 glEnd ();
 glEndList ();// Закончили создание списка

 desertList=roadList+1;// Значение desertList это значение roadList + 1
 glNewList (desertList, GL_COMPILE);// Новый откомпилированный список отображения 'desertList'
 glBindTexture (GL_TEXTURE_2D, texture [3]);
 glBegin (GL_QUADS);
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-squareL, 0.0f, -squareL);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-squareL, 0.0f,  squareL);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( squareL, 0.0f,  squareL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( squareL, 0.0f, -squareL);// Верх право
 glEnd ();
 glEndList ();// Закончили создание списка

 skyList=desertList+1;// Значение skyList это значение desertList + 1
 glNewList (skyList, GL_COMPILE);// Новый откомпилированный список отображения 'skyList'
 glBindTexture (GL_TEXTURE_2D, texture [7]);
 glBegin (GL_QUADS);
 glNormal3f (0.0f, -1.0f, 0.0f);// Нормаль указывает вниз
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-skyL, 0.0f, -skyL);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( skyL, 0.0f, -skyL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( skyL, 0.0f,  skyL);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-skyL, 0.0f,  skyL);// Верх лево
 glEnd ();
 glEndList ();// Закончили создание списка

 float tX=tan (((float)cx/(float)cy)/(1600.0f/900.0f)*0.633537f)*fogDist+2.5f,
       tZ=-fogDist-0.5f, tY=0.0f, tH=4.75f+0.1f;//1.85f+(walkIs ? walkbias-1.0f*walkbiasK : 0.0f)+2.15f+0.1f;// 2.15 - max hill height
 borderLowList=skyList+1;
 glNewList (borderLowList, GL_COMPILE);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 glBegin (GL_QUADS);
 // Передняя грань
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-tX, tY, tZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( tX, tY, tZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( tX, tH, tZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-tX, tH, tZ);// Верх лево
 glEnd ();
 glEndList ();

 tZ=-skyDist-1.0f; tY=-skyH-1.0f; tH=0.0f;
 if ((1600.0f/900.0f)>=((float)cx/(float)cy))
  tX=tan (0.633537f)*(skyDist+1.0f)+5.0f;
 else
  tX=tan (((float)cx/(float)cy)/(1600.0f/900.0f)*0.633537f)*(skyDist+1.0f)+5.0f;
 borderHighList=borderLowList+1;
 glNewList (borderHighList, GL_COMPILE);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 glBegin (GL_QUADS);
 // Передняя грань
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-tX, tY, tZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( tX, tY, tZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( tX, tH, tZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-tX, tH, tZ);// Верх лево
 glEnd ();
 glEndList ();

 for (i=0; i<2; i++)
 {
  bushList [i]=borderHighList+1+i;
  glNewList (bushList [i], GL_COMPILE);
  glEnable (GL_ALPHA_TEST);
  glAlphaFunc (GL_NOTEQUAL, 0.0f);
  if (i==0)
   glBindTexture (GL_TEXTURE_2D, texture [19]);
  else
   glBindTexture (GL_TEXTURE_2D, texture [21]);
  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);

  tY=0.0f;
  if (i==0)
   tY=-0.15f;

  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-squareL, 1.0f, 0.0f);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-squareL, tY,   0.0f);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( squareL, tY,   0.0f);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( squareL, 1.0f, 0.0f);// Верх право
  glEnd ();

  tX=cos (60.0f*rad)*squareL;
  tZ=sin (60.0f*rad)*squareL;

  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-tX, 1.0f, tZ); // Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-tX, tY,   tZ); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( tX, tY,   -tZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( tX, 1.0f, -tZ);// Верх право
  glEnd ();

  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-tX, 1.0f, -tZ);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-tX, tY,   -tZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( tX, tY,   tZ); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( tX, 1.0f, tZ); // Верх право
  glEnd ();

  glPolygonMode (GL_BACK, GL_LINE);
  glPolygonMode (GL_FRONT, GL_FILL);
  glDisable (GL_ALPHA_TEST);
  glEndList ();
 }

 cronaList=bushList [1]+1;
 glNewList (cronaList, GL_COMPILE);
 glEnable (GL_ALPHA_TEST);
 glAlphaFunc (GL_NOTEQUAL, 0.0f);
 glBindTexture (GL_TEXTURE_2D, texture [48]);
 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 tY=1.5f;
 tH=tY+3.5f;
 float tW=1.5f, tStock=0.2f, tStockZ=sin (60.0f*rad)*tStock, tStockX=cos (60.0f*rad)*tStock;

 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-tW, tH, -tStock);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-tW, tY, -tStock);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( tW, tY, -tStock);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( tW, tH, -tStock);// Верх право
 glEnd ();

 tX=cos (60.0f*rad)*tW;
 tZ=sin (60.0f*rad)*tW;

 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-tX+tStockX, tH, tZ+tStockZ); // Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-tX+tStockX, tY, tZ+tStockZ); // Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( tX+tStockX, tY, -tZ+tStockZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( tX+tStockX, tH, -tZ+tStockZ);// Верх право
 glEnd ();

 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-tX-tStockX, tH, -tZ+tStockZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-tX-tStockX, tY, -tZ+tStockZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( tX-tStockX, tY, tZ+tStockZ); // Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( tX-tStockX, tH, tZ+tStockZ); // Верх право
 glEnd ();

 glPolygonMode (GL_BACK, GL_LINE);
 glPolygonMode (GL_FRONT, GL_FILL);
 glDisable (GL_ALPHA_TEST);
 glEndList ();

 float crateX, crateY, crateZ;
 for (i=0; i<2; i++)
 {
  if (i==0)
  {
   crateX=1.0f;
   crateY=1.0f;
   crateZ=1.0f;
  }
  else
  {
   crateX=0.5f;
   crateY=0.5f;
   crateZ=0.5f;
  }

  crateList [i]=cronaList+1+i;
  glNewList (crateList [i], GL_COMPILE);
  glBindTexture (GL_TEXTURE_2D, texture [32]);
  glBegin (GL_QUADS);

  // Передняя грань
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-crateX, 0.0f,     crateZ);// Точка 1 (Перед)
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( crateX, 0.0f,     crateZ);// Точка 2 (Перед)
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( crateX, crateY*2, crateZ);// Точка 3 (Перед)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-crateX, crateY*2, crateZ);// Точка 4 (Перед)

  // Задняя грань
  glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-crateX, 0.0f,     -crateZ);// Точка 1 (Зад)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-crateX, crateY*2, -crateZ);// Точка 2 (Зад)
  glTexCoord2f (0.0f, 1.0f); glVertex3f ( crateX, crateY*2, -crateZ);// Точка 3 (Зад)
  glTexCoord2f (0.0f, 0.0f); glVertex3f ( crateX, 0.0f,     -crateZ);// Точка 4 (Зад)

  // Верхняя грань
  glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-crateX,  crateY*2, -crateZ);// Точка 1 (Верх)
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-crateX,  crateY*2,  crateZ);// Точка 2 (Верх)
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( crateX,  crateY*2,  crateZ);// Точка 3 (Верх)
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( crateX,  crateY*2, -crateZ);// Точка 4 (Верх)

  // Нижняя грань
  glNormal3f (0.0f, -1.0f, 0.0f);// Нормаль указывает вниз
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-crateX, 0.0f, -crateZ);// Точка 1 (Низ)
  glTexCoord2f (0.0f, 1.0f); glVertex3f ( crateX, 0.0f, -crateZ);// Точка 2 (Низ)
  glTexCoord2f (0.0f, 0.0f); glVertex3f ( crateX, 0.0f,  crateZ);// Точка 3 (Низ)
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-crateX, 0.0f,  crateZ);// Точка 4 (Низ)

  // Правая грань
  glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
  glTexCoord2f (1.0f, 0.0f); glVertex3f (crateX, 0.0f,     -crateZ);// Точка 1 (Право)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (crateX, crateY*2, -crateZ);// Точка 2 (Право)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (crateX, crateY*2,  crateZ);// Точка 3 (Право)
  glTexCoord2f (0.0f, 0.0f); glVertex3f (crateX, 0.0f,      crateZ);// Точка 4 (Право)

  // Левая грань
  glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-crateX, 0.0f,     -crateZ);// Точка 1 (Лево)
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-crateX, 0.0f,      crateZ);// Точка 2 (Лево)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-crateX, crateY*2,  crateZ);// Точка 3 (Лево)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-crateX, crateY*2, -crateZ);// Точка 4 (Лево)

  glEnd ();// Кончили рисовать четырехугольник
  glEndList ();
 }
}

void paint ()
{
 // OpenGL animation code goes here
 glPushMatrix ();
 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// glDisable (GL_FOG);
 setFog ();

 treeWind ();
 view ();
 treeSnd2 ();

 skyFog ();
 sky ();

 pointer ();

 fpsC ();

 if (statusOn)
  statusBar ();

 hitEsc ();

 if (menuOn)
  menuOut ();

 glPopMatrix ();
 SwapBuffers (hDC);
}

int mapVX, mapVZ, mapSV;
float hillRh=0.0f, hillRh0=0.0f, hillRl=0.0f, hillLeapFall=0.0f, hillLd=-0.85f, hillLh=1.25f;
bool hillStart=true, hillLeap=false, noWalk=false, borderUp=false,
     hillLeapDown=false, hillLeapUp=false;
float hillUpDown=0.0f;

void view ()
{
 int mapI2, mapI;
 int i, i2, mapV;
 memset (mapB, 0, mapBQ*mapBQ*sizeof (unsigned char));
 borderUp=false;
 hillUpDown=0.0f;

 if (hillLeapUp)
 {
  hillRl+=0.025f*fpsTweak ();
  if (hillRl>0.0f)
  {
   hillRl=0.0f;
   hillLeapUp=false;
   noWalk=false;
  }
 }
 else if (hillLeapDown)
 {
  float hillLh0=hillLh;
  if (hillLh>2.5f)
   hillLh0=2.5f;

  hillRl-=0.065f*hillLh/1.25f*fpsTweak ();
  if (hillRl<hillLd*hillLh0/2.5f)
  {
   hillRl=hillLd;
   hillLeapDown=false;
   hillLeapUp=true;
  }
 }
 else if (hillRl!=hillRh)
 {
  if (hillStart)
  {
   hillStart=false;
   hillRl=hillRh;
  }
  else
  {
   if (hillRl<hillRh)
   {
    hillRl+=0.035f*fpsTweak ();
    if (hillRl>hillRh)
     hillRl=hillRh;
   }
   else if (hillRl>hillRh)
   {
    if (hillRl-hillRh>1.25f)
    {
     hillLeap=true;
     noWalk=true;
     hillLeapFall=0.035f;
     hillLh=1.25f;
    }
    if (!hillLeap)
    {
     hillRl-=0.035f*fpsTweak ();
     if (hillRl<hillRh)
      hillRl=hillRh;
    }
    else
    {
     hillRl-=hillLeapFall*fpsTweak ();
     hillLeapFall+=hillLeapFall/5;
     if (hillRl<hillRh)
      hillRl=hillRh;
     if (hillRl==0.0f)
     {
      hillLeap=false;
      hillLeapDown=true;
      int psVol=100;
      playSound ("down_soft", psVol);
     }
    }
   }
  }
 }
 hillRh0=hillRl;
 hillStart=false;

 glLoadIdentity();

 glRotatef (-angleX, 1.0f, 0.0f, 0.0f);
 glTranslatef (0.0f, -1.85f-(walkIs && !noWalk ? walkbias-1.0f*walkbiasK : 0.0f)-hillRh0, -0.1f);

 // far border
 glColor3f (0.5f*gamma, 0.5f*gamma, 0.5f*gamma);
 glCallList (borderLowList);

 glRotatef (-theta, 0.0f, 1.0f, 0.0f);
 glTranslatef (-x, 0.0f, z);

 glTranslatef (0.0f, 0.0f, squareL*(squareS-1));

 hillRh=0.0f;
 mapHy=0.0f;
 mapHLy=0.0f;
 mapHLy=mapHy;
 int mapNZ, mapNX;
 mapNZ=mapZ-squareS/2;
 mapNX=mapX-squareS/2;
 grassH (mapNZ, mapNX);

 for (i2=0; i2<squareS; i2++)
 {
  if (i2==0)
   glTranslatef (-squareL*(squareS-1), mapHy-mapHLy, 0.0f);
  else
   glTranslatef (-squareL*(squareS-1), 0.0f, 0.0f);

  for (i=0; i<squareS; i++)
  {
   myColor3f (1.0f, 1.0f, 1.0f);

   mapV=0;
   mapVZ=mapZ-squareS/2+i2;
   mapVX=mapX-squareS/2+i;

   float mapAngle, mapAngleR;
   if (mapZ==mapVZ)
   {
    if (mapVX>=mapX)
     mapAngle=90.0f;
    else
     mapAngle=-90.0f;
   }
   else
   {
    mapAngle=atan (abs (mapVX-mapX)/abs (mapVZ-mapZ))/rad;

    if (mapVX>=mapX && mapVZ>mapZ)// right top
     mapAngle=mapAngle;
    else if (mapVX>=mapX && mapVZ<mapZ)// right bottom
     mapAngle=180.0f-mapAngle;
    else if (mapVX<mapX && mapVZ<mapZ)// left bottom
     mapAngle=180.0f+mapAngle;
    else if (mapVX<mapX && mapVZ>mapZ)// left top
     mapAngle=360.0f-mapAngle;
    if (mapAngle>180.0f)
     mapAngle-=360.0f;
   }
   mapAngleR=mapAngle+theta;
   if (mapAngleR>180.0f)
    mapAngleR-=360.0f;
   if (mapAngleR<-180.0f)
    mapAngleR+=360.0f;

   mapSV=-1;
   if ((mapAngleR>=-90.0f && mapAngleR<=90.0f) || (abs (mapVX-mapX)<3 && abs (mapVZ-mapZ)<3))// forward only
   {
    if (!isMapped (mapVZ, mapVX))
    {
     if ((mapVZ==villageZ-2 || mapVZ==villageZ-1) && (mapVX<0 || mapVX>mapQ-1))
      road ();
     else
      glCallList (grassList);
    }
    else
    {
     mapV=map [mapVZ] [mapVX];

     if (mapV==32 || mapV==38 || mapV==55 || mapV==57 || mapV>=100)
     {
      if (mapH [mapVZ+1] [mapVX]==0 &&
          mapH [mapVZ] [mapVX]==0 &&
          mapH [mapVZ] [mapVX+1]==0 &&
          mapH [mapVZ+1] [mapVX+1]==0)
       glCallList (grassList);
      else
       grass ();
     }
     else if (mapV==34)
      road ();

     if (mapV==195)
      tree ();

     else if (mapV==196)
      treeB ();

     else if (mapV==100)
      column ();

     else if (mapV==120)
      columnCyl ();

     else if (mapV==115)
      barrel ();

     else if (mapV==237)
      crateSmall ();

     else if (mapV==150)
      wall ();

     else if (mapV==160)
      fence ();

     else if (mapV==175)
      crystal ();

     else if (mapV==38)
      bush ();

     else if (mapV==165)
      corner ();

     if (mapV==55 || mapV==56 || mapV==57 || mapV==225 || mapV==185)
      mapSV=seekMap ();

     if (mapSV>0)
     {
      mapI2=mapBZ-mapVZ;
      mapI=mapBX-mapVX;

      glLoadIdentity();
      glRotatef (-angleX, 1.0f, 0.0f, 0.0f);
      glTranslatef (0.0f, -1.85f-(walkIs && !noWalk ? walkbias-1.0f*walkbiasK : 0.0f)-hillRh0, -0.1f);
      glRotatef (-theta, 0.0f, 1.0f, 0.0f);
      glTranslatef (-x, 0.0f, z);
      glTranslatef (0.0f, 0.0f, squareL*(squareS-1)-squareL*2*(i2+mapI2));
      glTranslatef (-squareL*(squareS-1)+squareL*2*(i+mapI), 0.0f, 0.0f);

      if (mapSV==215)
       house ();

      else if (mapSV==225)
       well ();

      else if (mapSV==185)
       bench ();

      else if (mapSV==235)
       cellar ();

      else if (mapSV==236)
       crates ();

      else if (mapSV==63 || mapSV==65 || mapSV==67)
       hill ();

      glLoadIdentity();
      glRotatef (-angleX, 1.0f, 0.0f, 0.0f);
      glTranslatef (0.0f, -1.85f-(walkIs && !noWalk ? walkbias-1.0f*walkbiasK : 0.0f)-hillRh0, -0.1f);
      glRotatef (-theta, 0.0f, 1.0f, 0.0f);
      glTranslatef (-x, 0.0f, z);
      glTranslatef (0.0f, 0.0f, squareL*(squareS-1)-squareL*2*i2);
      glTranslatef (-squareL*(squareS-1)+squareL*i*2, 0.0f, 0.0f);
     }
    }
   }

   if (isMapped (mapVZ, mapVX))
   {
    mapV=map [mapVZ] [mapVX];

    if (mapV==176)
     crystalSnd ();

    else if (mapV==195)
     treeSnd1 ();

    else if (mapV==225 || mapSV==225)
     wellSnd ();
   }

   mapHLy=mapHy;
   if (i<squareS-1)
   {
    mapNZ=mapZ-squareS/2+i2;
    mapNX=mapX-squareS/2+i+1;
    grassH (mapNZ, mapNX);
   }
   else if (i2<squareS-1)
   {
    mapNZ=mapZ-squareS/2+i2+1;
    mapNX=mapX-squareS/2;
    grassH (mapNZ, mapNX);
   }
   if (i<squareS-1)
    glTranslatef (squareL*2, mapHy-mapHLy, 0.0f);
   else
    glTranslatef (squareL*2-squareL*(squareS+1), mapHy-mapHLy, -squareL*2);
  }
 }
}

int seekMap ()
{
 int tCZ=mapBQ/2, tCX=mapBQ/2;

 int r=-1;
 if (mapB [tCZ+(mapVZ-mapZ)] [tCX+(mapVX-mapX)]!=0)
  return r;

 bool isHill=false;

 char mapSZ [64], mapSX [64];
 int mapSZa [4]={0, 0, -1, 1};
 int mapSXa [4]={-1, 1,  0, 0};
 int i, i2, mapV, rX, rZ, c=0;
 mapSZ [c]=mapVZ;
 mapSX [c]=mapVX;

 if (isMapped (mapSZ [c], mapSX [c]))
 {
  if (mapB [tCZ+(mapSZ [c]-mapZ)] [tCX+(mapSX [c]-mapX)]==0)
  {
   mapV=map [mapSZ [c]] [mapSX [c]];
   if (mapV==225 || mapV==185)
   {
    mapBZ=mapSZ [c];
    mapBX=mapSX [c];
    mapB [tCZ+(mapSZ [c]-mapZ)] [tCX+(mapSX [c]-mapX)]=215;
    r=mapV;
   }
  }
 }
 if (r!=-1)
  mapB [tCZ+(mapVZ-mapZ)] [tCX+(mapVX-mapX)]=56;

 for (i=0; i<=c; i++)
 {
  for (i2=0; i2<4; i2++)
  {
   if (isMapped (mapSZ [i]+mapSZa [i2], mapSX [i]+mapSXa [i2]))
   {
    if (mapB [tCZ+(mapSZ [i]-mapZ)+mapSZa [i2]] [tCX+(mapSX [i]-mapX)+mapSXa [i2]]==0)
    {
     mapV=map [mapSZ [i]+mapSZa [i2]] [mapSX [i]+mapSXa [i2]];

     if ((mapV==55 || mapV==63 || mapV==65 || mapV==67) && mapX==mapSX [i]+mapSXa [i2] && mapZ==mapSZ [i]+mapSZa [i2])
      isHill=true;

     if (mapV==63 || mapV==65 || mapV==67 || mapV==185 || mapV==215 || mapV==217 || mapV==225 || mapV==235 || mapV==236)
     {
      mapBZ=mapSZ [i]+mapSZa [i2];
      mapBX=mapSX [i]+mapSXa [i2];
      mapB [tCZ+(mapSZ [i]-mapZ)+mapSZa [i2]] [tCX+(mapSX [i]-mapX)+mapSXa [i2]]=215;
      r=mapV;
      rX=mapSX [i]+mapSXa [i2];
      rZ=mapSZ [i]+mapSZa [i2];

      c++;
      mapSZ [c]=mapSZ [i]+mapSZa [i2];
      mapSX [c]=mapSX [i]+mapSXa [i2];
     }
     else if (mapV==55 || mapV==56 || mapV==57)
     {
      c++;
      mapSZ [c]=mapSZ [i]+mapSZa [i2];
      mapSX [c]=mapSX [i]+mapSXa [i2];
      mapB [tCZ+(mapSZ [i]-mapZ)+mapSZa [i2]] [tCX+(mapSX [i]-mapX)+mapSXa [i2]]=56;
     }
    }
   }
  }
 }

 if (isHill && r!=-1)
  hillH (rX, rZ, r);

 return r;
}

float objFar ()
{
 float tX, tZ;

 if (mapX>=mapVX)
  tX=(mapX-mapVX)*squareL*2+x;
 else
  tX=(mapVX-mapX)*squareL*2-x;
 if (mapZ>=mapVZ)
  tZ=(mapZ-mapVZ)*squareL*2+z;
 else
  tZ=(mapVZ-mapZ)*squareL*2-z;

 float objR=sqrt (pow (tX, 2)+pow (tZ, 2));

 return objR;
}

int objSnd ()
{
 int sndVolume=(sndDist-(objFar ()-sqrt (pow (squareL, 2)*2)))*100.0f/sndDist;
 if (sndVolume<0 || menuOn)
  sndVolume=0;
 else if (sndVolume>100)
  sndVolume=100;

 return sndVolume;
}

void grassH (int mapNZ, int mapNX)
{
 mapHy=0.0f;

 if (!isMapped (mapNZ, mapNX))
  return;

 if (map [mapNZ] [mapNX]!=38 && map [mapNZ] [mapNX]!=195 && map [mapNZ] [mapNX]!=196)
  return;

 if (!(mapH [mapNZ+1] [mapNX]==0 &&
       mapH [mapNZ] [mapNX]==0 &&
       mapH [mapNZ] [mapNX+1]==0 &&
       mapH [mapNZ+1] [mapNX+1]==0))
  mapHy=(mapH [mapNZ+1] [mapNX]+mapH [mapNZ] [mapNX]+mapH [mapNZ] [mapNX+1]+mapH [mapNZ+1] [mapNX+1])/mapHk/4.0f;
}

void grass ()
{
 glBindTexture (GL_TEXTURE_2D, texture [1]);
 glBegin (GL_QUADS);
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-squareL, mapH [mapVZ+1] [mapVX]/mapHk-mapHy, -squareL);  // Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-squareL, mapH [mapVZ] [mapVX]/mapHk-mapHy,  squareL);    // Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( squareL, mapH [mapVZ] [mapVX+1]/mapHk-mapHy,  squareL);  // Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( squareL, mapH [mapVZ+1] [mapVX+1]/mapHk-mapHy, -squareL);// Верх право
 glEnd ();

 if (mapX==mapVX && mapZ==mapVZ)
 {
  float h1, h2;
  float y1=mapH [mapVZ+1] [mapVX]/mapHk,
        y2=mapH [mapVZ] [mapVX]/mapHk,
        y3=mapH [mapVZ] [mapVX+1]/mapHk,
        y4=mapH [mapVZ+1] [mapVX+1]/mapHk;
  h1=y1*(squareL*2-(squareL-z))/(squareL*2.0f)+y2*(squareL*2-(squareL+z))/(squareL*2.0f);
  h2=y4*(squareL*2-(squareL-z))/(squareL*2.0f)+y3*(squareL*2-(squareL+z))/(squareL*2.0f);
  hillRh=h1*(squareL*2-(squareL+x))/(squareL*2.0f)+h2*(squareL*2-(squareL-x))/(squareL*2.0f);

  if (hillRh>10/mapHk || hillRh0>10/mapHk)// !terrain
  {
   if (hillRh>hillRh0)// up
    hillUpDown=1.0f/1.5f;
   else if (hillRh<hillRh0)// down
    hillUpDown=1.25f;
   else
    hillUpDown=1.0f;
  }
  else
   hillUpDown=1.0f;
 }
}

void road ()
{
 if (mapZ<villageZ-5 && mapX>villageX-8 && mapX<villageX+7 && hillRh==0.0f)// wall opt
 {
  if (mapVX>villageX-8 && mapVX<villageX+7)//map [villageZ-5] [villageX+7]
   return;
 }

 if ((mapVX<0 || mapVX>mapQ-1) || (mapExt [mapVZ] [mapVX]==1 || mapExt [mapVZ] [mapVX]==2
                                || mapExt [mapVZ] [mapVX]==3 || mapExt [mapVZ] [mapVX]==4))
 {
  glCallList (roadList);

  bool thisL=false;
  float thisX=1.0f, thisW=0.1f, thisY=0.1f;
  float thisZ=-(1.0f-thisW);//-0.95f

  if (mapVX<0 || mapVX>mapQ-1)
  {
   if (mapVZ==villageZ-2)
    thisL=true;
  }
  else if (mapExt [mapVZ] [mapVX]==2 || mapExt [mapVZ] [mapVX]==4)
   thisL=true;

  if (thisL)
   thisZ*=-1;

  glBindTexture (GL_TEXTURE_2D, texture [42]);
  glBegin (GL_QUADS);

  if ((mapZ<mapVZ && thisL) || (mapZ<=mapVZ && !thisL))
  {
   if (!thisL)
    myColor3f (0.5f, 0.5f, 0.5f);
   else
    myColor3f (0.75f, 0.75f, 0.75f);
   // Передняя грань
   glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
   glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, 0.0f, thisZ+thisW);// Точка 1 (Перед)
   glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX, 0.0f,  thisZ+thisW);// Точка 2 (Перед)
   glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX, thisY, thisZ+thisW);// Точка 3 (Перед)
   glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX, thisY, thisZ+thisW);// Точка 4 (Перед)
  }

  if ((mapZ>=mapVZ && thisL) || (mapZ>mapVZ && !thisL))
  {
   if (!thisL)
    myColor3f (0.75f, 0.75f, 0.75f);
   else
    myColor3f (0.5f, 0.5f, 0.5f);
   // Задняя грань
   glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
   glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, 0.0f,  thisZ-thisW);// Точка 1 (Зад)
   glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX, thisY, thisZ-thisW);// Точка 2 (Зад)
   glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX, thisY, thisZ-thisW);// Точка 3 (Зад)
   glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX, 0.0f,  thisZ-thisW);// Точка 4 (Зад)
  }

  myColor3f (1.0f, 1.0f, 1.0f);

  // Верхняя грань
  glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX,  thisY, thisZ-thisW);// Точка 1 (Верх)
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX,  thisY, thisZ+thisW);// Точка 2 (Верх)
  glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX,  thisY, thisZ+thisW);// Точка 3 (Верх)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX,  thisY, thisZ-thisW);// Точка 4 (Верх)

  if (mapExt [mapVZ] [mapVX]==3 || mapExt [mapVZ] [mapVX]==4)
  {
   // Правая грань
   glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
   glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX, 0.0f,     thisZ-thisW);// Точка 1 (Право)
   glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX, thisY, thisZ-thisW);// Точка 2 (Право)
   glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX, thisY,  thisZ+thisW);// Точка 3 (Право)
   glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX, 0.0f,      thisZ+thisW);// Точка 4 (Право)

   // Левая грань
   glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
   glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, 0.0f,     thisZ-thisW);// Точка 1 (Лево)
   glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, 0.0f,      thisZ+thisW);// Точка 2 (Лево)
   glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX, thisY,  thisZ+thisW);// Точка 3 (Лево)
   glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX, thisY, thisZ-thisW);// Точка 4 (Лево)
  }

  glEnd ();// Кончили рисовать четырехугольник

  if (mapX==mapVX && mapZ==mapVZ)
  {
   if ((thisL && z*-1>=thisZ-thisW) || (!thisL && z*-1<=thisZ+thisW))
   {
    hillRh=thisY;
    borderUp=true; 
   }
  }
 }
 else
 {
  myColor3f (1.0f, 1.0f, 1.0f);

  if (mapExt [mapVZ] [mapVX]==21)
   glBindTexture (GL_TEXTURE_2D, texture [38]);
  else if (mapExt [mapVZ] [mapVX]==25)
   glBindTexture (GL_TEXTURE_2D, texture [39]);
  else if (mapExt [mapVZ] [mapVX]==51)
   glBindTexture (GL_TEXTURE_2D, texture [44]);// sand y
  else if (mapExt [mapVZ] [mapVX]==52)
   glBindTexture (GL_TEXTURE_2D, texture [43]);// sand x
  else if (mapExt [mapVZ] [mapVX]==55)
   glBindTexture (GL_TEXTURE_2D, texture [45]);// sand hub
  else if (mapExt [mapVZ] [mapVX]==56)
   glBindTexture (GL_TEXTURE_2D, texture [46]);// sand road

  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-squareL, 0.0f, -squareL);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-squareL, 0.0f,  squareL);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( squareL, 0.0f,  squareL);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( squareL, 0.0f, -squareL);// Верх право
  glEnd ();
 }
}

void well ()
{
 float wellH=1.15f, wellR=1.25f, wellR2=0.85f, well4R=0.15f, well4H=2.25f,
       wellRoofR=1.75f, wellRoofH=1.25f,
       wellBucketR=0.3f, wellBucketR2=0.21f, wellBucketH=0.5f;

 // внешняя поверхность
 myColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [18]);
 glTranslatef (1.0f, 0.0f, -1.0f);
 glRotatef (-90, 1.0f, 0.0f, 0.0f);
 //                основание, вершина, длина
 gluCylinder (quadratic, wellR, wellR, wellH, 32, 2);// Рисуем наш цилиндр

 // внутренняя поверхность
 myColor3f (0.5f, 0.5f, 0.5f);
 glPolygonMode (GL_BACK, GL_FILL);
 glPolygonMode (GL_FRONT, GL_LINE);
 gluCylinder (quadratic, wellR2, wellR2, wellH, 32, 2);// Рисуем наш цилиндр
 glPolygonMode (GL_BACK, GL_LINE);
 glPolygonMode (GL_FRONT, GL_FILL);

 // вода
 glTranslatef (0.0f, 0.0f, 0.1f);
 myColor3f (0.0f, 0.05f, 0.15f);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 gluDisk (quadratic, 0, wellR2, 32, 2);// Рисуем диск

 // верх
 glTranslatef (0.0f, 0.0f, wellH-0.1f);
 myColor3f (0.35f, 0.35f, 0.25f);
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 gluDisk (quadratic, wellR2, wellR, 32, 2);// Рисуем диск

 // ведро
 glTranslatef (0.0f, -1.0f, 0.0f);
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 myColor3f (0.5f, 0.5f, 0.5f);
 glPolygonMode (GL_BACK, GL_FILL);
 gluCylinder (quadratic, wellBucketR2, wellBucketR, wellBucketH, 32, 2);// Рисуем наш цилиндр
 myColor3f (0.15f, 0.15f, 0.15f);
 gluCylinder (quadratic, wellBucketR2-0.01f, wellBucketR, wellBucketH, 32, 2);// Рисуем наш цилиндр
 glPolygonMode (GL_BACK, GL_LINE);
 glTranslatef (0.0f, 1.0f, 0.0f);

 // низ крыши
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 myColor3f (0.45f, 0.25f, 0.05f);
 glTranslatef (0.0f, 0.0f, well4H-wellH);
 glPolygonMode (GL_BACK, GL_FILL);
 glPolygonMode (GL_FRONT, GL_LINE);
 gluDisk (quadratic, 0, wellRoofR, 48, 2);// Рисуем диск
 glPolygonMode (GL_BACK, GL_LINE);
 glPolygonMode (GL_FRONT, GL_FILL);

 // верх крыши
 myColor3f (0.5f, 0.5f, 0.5f);
 gluCylinder (quadratic, wellRoofR, 0, wellRoofH, 48, 2);// Рисуем наш цилиндр
 glTranslatef (0.0f, 0.0f, -well4H);

 // столбики
 myColor3f (0.35f, 0.35f, 0.35f);
 glTranslatef (-1.0f, 1.0f, 0.0f);
 gluCylinder (quadratic, well4R, well4R, well4H, 16, 2);// Рисуем наш цилиндр
 glTranslatef (2.0f, 0.0f, 0.0f);
 gluCylinder (quadratic, well4R, well4R, well4H, 16, 2);// Рисуем наш цилиндр
 glTranslatef (0.0f, -2.0f, 0.0f);
 gluCylinder (quadratic, well4R, well4R, well4H, 16, 2);// Рисуем наш цилиндр
 glTranslatef (-2.0f, 0.0f, 0.0f);
 gluCylinder (quadratic, well4R, well4R, well4H, 16, 2);// Рисуем наш цилиндр
 glRotatef (90, 1.0f, 0.0f, 0.0f);
}

int wellTime=0;
void wellSnd ()
{
 if (rand()%2==1 && clock ()-wellTime>2500)
 {
  int wellVol=objSnd ();
  if (wellVol>0)
  {
   char t [16];
   sprintf (t, "drop%d", (rand ()%5+1));
   playSound (t, wellVol);

   wellTime=clock ();
  }
 }
}

void bench ()
{
 int i;
 float thisX=2.75f, thisH=0.5f, thisB=0.1f, thisZ=0.55f, thisW;

 glEnable (GL_LIGHTING);// Разрешить освещение

 glBindTexture (GL_TEXTURE_2D, texture [10]);
 glBegin (GL_QUADS);

 // Передняя грань
 glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, thisH,       thisZ);// Точка 1 (Перед)
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( thisX, thisH,       thisZ);// Точка 2 (Перед)
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( thisX, thisH+thisB, thisZ);// Точка 3 (Перед)
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX, thisH+thisB, thisZ);// Точка 4 (Перед)

 // Задняя грань
 glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, thisH,       -thisZ);// Точка 1 (Зад)
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX, thisH+thisB, -thisZ);// Точка 2 (Зад)
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( thisX, thisH+thisB, -thisZ);// Точка 3 (Зад)
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( thisX, thisH,       -thisZ);// Точка 4 (Зад)

 // Верхняя грань
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX,  thisH+thisB, -thisZ);// Точка 1 (Верх)
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX,  thisH+thisB,  thisZ);// Точка 2 (Верх)
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( thisX,  thisH+thisB,  thisZ);// Точка 3 (Верх)
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( thisX,  thisH+thisB, -thisZ);// Точка 4 (Верх)

 // Правая грань
 glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
 glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX, thisH,       -thisZ);// Точка 1 (Право)
 glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX, thisH+thisB, -thisZ);// Точка 2 (Право)
 glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX, thisH+thisB,  thisZ);// Точка 3 (Право)
 glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX, thisH,        thisZ);// Точка 4 (Право)

 // Левая грань
 glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, thisH,       -thisZ);// Точка 1 (Лево)
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, thisH,        thisZ);// Точка 2 (Лево)
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX, thisH+thisB,  thisZ);// Точка 3 (Лево)
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX, thisH+thisB, -thisZ);// Точка 4 (Лево)

 glEnd ();// Кончили рисовать четырехугольник


 thisW=0.25f; thisH=0.5f;
 for (i=0; i<2; i++)
 {
  if (i==0)
   thisX=-1.5f;
  else
   thisX=1.5f;

  glBindTexture (GL_TEXTURE_2D, texture [31]);
  glBegin (GL_QUADS);

  // Передняя грань
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX-thisW, 0.0f,  thisW);// Точка 1 (Перед)
  glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX+thisW, 0.0f,  thisW);// Точка 2 (Перед)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX+thisW, thisH, thisW);// Точка 3 (Перед)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX-thisW, thisH, thisW);// Точка 4 (Перед)

  // Задняя грань
  glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
  glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX-thisW, 0.0f,  -thisW);// Точка 1 (Зад)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX-thisW, thisH, -thisW);// Точка 2 (Зад)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX+thisW, thisH, -thisW);// Точка 3 (Зад)
  glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX+thisW, 0.0f,  -thisW);// Точка 4 (Зад)

  // Правая грань
  glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
  glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX+thisW, 0.0f,  -thisW);// Точка 1 (Право)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX+thisW, thisH, -thisW);// Точка 2 (Право)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX+thisW, thisH,  thisW);// Точка 3 (Право)
  glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX+thisW, 0.0f,   thisW);// Точка 4 (Право)

  // Левая грань
  glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (thisX-thisW, 0.0f,  -thisW);// Точка 1 (Лево)
  glTexCoord2f (1.0f, 0.0f); glVertex3f (thisX-thisW, 0.0f,   thisW);// Точка 2 (Лево)
  glTexCoord2f (1.0f, 1.0f); glVertex3f (thisX-thisW, thisH,  thisW);// Точка 3 (Лево)
  glTexCoord2f (0.0f, 1.0f); glVertex3f (thisX-thisW, thisH, -thisW);// Точка 4 (Лево)

  glEnd ();// Кончили рисовать четырехугольник
 }

 glDisable (GL_LIGHTING);// Запрет освещения

 if ((mapX==mapBX || mapX==mapBX-1 || mapX==mapBX+1) && mapZ==mapBZ)
  hillRh=thisH+thisB;
}

void barrel ()
{
 float barH=1.35f, // высота
       barR=0.615f,// радиус
       barT=0.05f, // толщина окаймления
       barB=0.15f, // высота окаймления
       barH2=0.1f, // высота пробки
       barR2=0.1f, // радиус пробки
       barX=0.4f;  // смещение пробки

 int barN=mapExt [mapVZ] [mapVX];
 glEnable (GL_LIGHTING);// Разрешить освещение

 myColor3f (1.0f, 1.0f, 1.0f);

 if (barrelObj [barN].x!=0.0f || barrelObj [barN].z!=0.0f)
  glTranslatef (barrelObj [barN].x, 0.0f, barrelObj [barN].z);
 glRotatef (-90, 1.0f, 0.0f, 0.0f);
 if (barrelObj [barN].angle!=0.0f)
  glRotatef (barrelObj [barN].angle, 0.0f, 0.0f, 1.0f);

 //                основание, вершина, длина
 glBindTexture (GL_TEXTURE_2D, texture [34]);
 gluCylinder (quadratic, barR+barT, barR, barB, 32, 1);// основание
 glTranslatef (0.0f, 0.0f, barB);
 glBindTexture (GL_TEXTURE_2D, texture [33]);
 gluCylinder (quadratic, barR, barR, barH, 32, 1);// бочка
 glTranslatef (0.0f, 0.0f, barH);
 gluCylinder (quadratic, barR, barR+barT, barB, 32, 1);// внешняя кайма
 glTranslatef (0.0f, 0.0f, barB/2);
 glPolygonMode (GL_BACK, GL_FILL);
 glPolygonMode (GL_FRONT, GL_LINE);
 glBindTexture (GL_TEXTURE_2D, texture [35]);
 gluCylinder (quadratic, barR-barT, barR, barB/2, 32, 1);// внутренняя кайма
 glPolygonMode (GL_BACK, GL_LINE);
 glPolygonMode (GL_FRONT, GL_FILL);
 gluDisk (quadratic, 0.0f, barR-barT, 32, 2);// крышка
 glTranslatef (-barX, 0.0f, 0.0f);
 glBindTexture (GL_TEXTURE_2D, texture [34]);
 gluCylinder (quadratic, barR2, barR2, barH2, 18, 1);// край пробки
 glTranslatef (0.0f, 0.0f, barH2);
 glBindTexture (GL_TEXTURE_2D, texture [35]);
 gluDisk (quadratic, 0.0f, barR2, 18, 2);// верх пробки
 glTranslatef (barX, 0.0f, -barH2-barB/2+barB);
 gluDisk (quadratic, barR, barR+barT, 32, 2);// верхняя кайма
 glTranslatef (0.0f, 0.0f, -barB*2-barH);

 if (barrelObj [barN].angle!=0.0f)
  glRotatef (-barrelObj [barN].angle, 0.0f, 0.0f, 1.0f);
 glRotatef (90, 1.0f, 0.0f, 0.0f);
 if (barrelObj [barN].x!=0.0f || barrelObj [barN].z!=0.0f)
  glTranslatef (-barrelObj [barN].x, 0.0f, -barrelObj [barN].z);

 glDisable (GL_LIGHTING);// Запрет освещения
}

void cellar ()
{
 float thisH=2.5f, thisHb=1.5f, thisRoofAdd=0.15f, thisRoofH=0.05f, thisX=2.0f, thisZ=2.0f;

 // Крыша
 float thisAngle=atan ((thisH-thisHb)/(thisX*2));
 float thisHa=sin (thisAngle)*thisRoofAdd;

 glBindTexture (GL_TEXTURE_2D, texture [10]);
 myColor3f (0.45f, 0.25f, 0.05f);
 glBegin (GL_QUADS);
 // Нижняя грань
 glNormal3f (0.0f, -1.0f, 0.0f);// Нормаль указывает вниз
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa,  -thisZ-thisRoofAdd);
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa, -thisZ-thisRoofAdd);
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa,  thisZ+thisRoofAdd);
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa,   thisZ+thisRoofAdd);

 myColor3f (0.5f, 0.5f, 0.5f);
 // Верхняя грань
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa+thisRoofH,  -thisZ-thisRoofAdd);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa+thisRoofH,   thisZ+thisRoofAdd);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa+thisRoofH,  thisZ+thisRoofAdd);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa+thisRoofH, -thisZ-thisRoofAdd);// Верх право

 myColor3f (0.5f, 0.35f, 0.15f);
 // Левая грань
 glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa,            thisZ+thisRoofAdd);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa+thisRoofH,  thisZ+thisRoofAdd);// Верх право
 glTexCoord2f (0.0f, 0.5f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa+thisRoofH, -thisZ-thisRoofAdd);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX-thisRoofAdd, thisH+thisHa,           -thisZ-thisRoofAdd);// Низ лево

 // Правая грань
 glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
 glTexCoord2f (1.0f, 0.0f);         glVertex3f (thisX+thisRoofAdd, thisHb-thisHa,           -thisZ-thisRoofAdd);// Низ право
 glTexCoord2f (1.0f, thisHb/thisH); glVertex3f (thisX+thisRoofAdd, thisHb-thisHa+thisRoofH, -thisZ-thisRoofAdd);// Верх право
 glTexCoord2f (0.0f, thisHb/thisH); glVertex3f (thisX+thisRoofAdd, thisHb-thisHa+thisRoofH,  thisZ+thisRoofAdd);// Верх лево
 glTexCoord2f (0.0f, 0.0f);         glVertex3f (thisX+thisRoofAdd, thisHb-thisHa,            thisZ+thisRoofAdd);// Низ лево

 // Передняя грань
 glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
 glTexCoord2f (0.0f, 0.0f);         glVertex3f (-thisX-thisRoofAdd, thisH+thisHa,            thisZ+thisRoofAdd);// Низ лево
 glTexCoord2f (1.0f, 0.0f);         glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa,           thisZ+thisRoofAdd);// Низ право
 glTexCoord2f (1.0f, thisHb/thisH); glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa+thisRoofH, thisZ+thisRoofAdd);// Верх право
 glTexCoord2f (0.0f, 1.0f);         glVertex3f (-thisX-thisRoofAdd, thisH+thisHa+thisRoofH,  thisZ+thisRoofAdd);// Верх лево

 // Задняя грань
 glNormal3f (0.0f, 0.0f,-1.0f);// Нормаль указывает от наблюдателя
 glTexCoord2f (1.0f, 0.0f);         glVertex3f (-thisX-thisRoofAdd, thisH+thisHa,            -thisZ-thisRoofAdd);// Низ право
 glTexCoord2f (1.0f, 1.0f);         glVertex3f (-thisX-thisRoofAdd, thisH+thisHa+thisRoofH,  -thisZ-thisRoofAdd);// Верх право
 glTexCoord2f (0.0f, thisHb/thisH); glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa+thisRoofH, -thisZ-thisRoofAdd);// Верх лево
 glTexCoord2f (0.0f, 0.0f);         glVertex3f ( thisX+thisRoofAdd, thisHb-thisHa,           -thisZ-thisRoofAdd);// Низ лево

 glEnd ();

 glEnable (GL_LIGHTING);// Разрешить освещение

 myColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [29]);
 glBegin (GL_QUADS);

 // Передняя грань
 glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
 glTexCoord2f (0.0f, 0.0f);         glVertex3f (-thisX, 0.0f,   thisZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f);         glVertex3f ( thisX, 0.0f,   thisZ);// Низ право
 glTexCoord2f (1.0f, thisHb/thisH); glVertex3f ( thisX, thisHb, thisZ);// Верх право
 glTexCoord2f (0.0f, 1.0f);         glVertex3f (-thisX, thisH,  thisZ);// Верх лево

 // Задняя грань
 glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
 glTexCoord2f (1.0f, 0.0f);         glVertex3f (-thisX, 0.0f,   -thisZ);// Низ право
 glTexCoord2f (1.0f, 1.0f);         glVertex3f (-thisX, thisH,  -thisZ);// Верх право
 glTexCoord2f (0.0f, thisHb/thisH); glVertex3f ( thisX, thisHb, -thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f);         glVertex3f ( thisX, 0.0f,   -thisZ);// Низ лево

 // Правая грань
 glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
 glTexCoord2f (1.0f, 0.0f);         glVertex3f ( thisX, 0.0f,   -thisZ);// Низ право
 glTexCoord2f (1.0f, thisHb/thisH); glVertex3f ( thisX, thisHb, -thisZ);// Верх право
 glTexCoord2f (0.0f, thisHb/thisH); glVertex3f ( thisX, thisHb,  thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f);         glVertex3f ( thisX, 0.0f,    thisZ);// Низ лево

 // Левая грань
 glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, 0.0f,   thisZ);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f (-thisX, thisH,  thisZ);// Верх право
 glTexCoord2f (0.0f, 0.5f); glVertex3f (-thisX, thisH, -thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, 0.0f,  -thisZ);// Низ лево

 glEnd ();


 glDisable (GL_LIGHTING);// Запрет освещения

 if (!(mapX>mapBX && abs (mapZ-mapBZ)<4))
 {
  // Дверь
  float doorH=2.05f, doorW=0.65f, doorZ=0.65f, doorT=0.1f;

  // Внешняя поверхность
  myColor3f (0.5f, 0.5f, 0.5f);
  glBindTexture (GL_TEXTURE_2D, texture [10]);
  glBegin(GL_QUADS);
  glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX-doorT, 0.0f,  -doorW+doorZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX-doorT, 0.0f,   doorW+doorZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX-doorT, doorH,  doorW+doorZ);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX-doorT, doorH, -doorW+doorZ);// Верх лево
  glEnd ();

  glBindTexture (GL_TEXTURE_2D, texture [31]);
  myColor3f (0.45f, 0.25f, 0.05f);
  glBegin (GL_QUADS);
  // Правая боковина
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX-doorT, 0.0f,  doorW+doorZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX,       0.0f,  doorW+doorZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX,       doorH, doorW+doorZ);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX-doorT, doorH, doorW+doorZ);// Верх лево

  // Левая
  glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX-doorT, 0.0f,  -doorW+doorZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX-doorT, doorH, -doorW+doorZ);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX,       doorH, -doorW+doorZ);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX,       0.0f,  -doorW+doorZ);// Низ лево

  // Верхняя
  glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX-doorT, doorH, -doorW+doorZ);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX-doorT, doorH,  doorW+doorZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX,       doorH,  doorW+doorZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-thisX,       doorH, -doorW+doorZ);// Верх право
  glEnd ();

  glEnable (GL_LIGHTING);// Разрешить освещение

  // Ручка
  glTranslatef (-thisX-doorT, doorH/2, doorW+doorZ-0.25f);
  glRotatef (-90, 0.0f, 1.0f, 0.0f);

  glBindTexture (GL_TEXTURE_2D, texture [31]);
  myColor3f (0.45f, 0.25f, 0.05f);
  gluCylinder (quadratic, 0.05f, 0.1f, 0.15f, 16, 2);// Рисуем наш цилиндр
  glTranslatef (0.0f, 0.0f, 0.15f);
  myColor3f (0.65f, 0.45f, 0.25f);
  gluCylinder (quadratic, 0.1f, 0.07f, 0.025f, 16, 2);// Рисуем наш цилиндр
  glTranslatef (0.0f, 0.0f, 0.025f);
  glBindTexture (GL_TEXTURE_2D, texture [10]);
  myColor3f (1.0f, 1.0f, 1.0f);
  gluDisk (quadratic, 0.0f, 0.07f, 16, 2);// Рисуем диск
  glTranslatef (0.0f, 0.0f, -(0.15f+0.025f));

  glRotatef (90, 0.0f, 1.0f, 0.0f);
  glTranslatef (thisX+doorT+0.15f, -(doorH/2+0.1f), -(doorW-0.35f));

  glDisable (GL_LIGHTING);// Запрет освещения
 }
}

void crates ()
{
 glEnable (GL_LIGHTING);// Разрешить освещение

 glTranslatef (1.0f, 0.0f, -1.0f);
 glCallList (crateList [0]);

 glTranslatef (-2.25f, 0.0f, -0.25f);
 glCallList (crateList [0]);

 glTranslatef (0.0f, 0.0f, 2.25f);
 glRotatef (10, 0.0f, 1.0f, 0.0f);
 glCallList (crateList [0]);
 glRotatef (-10, 0.0f, 1.0f, 0.0f);

 glTranslatef (2.25f, 0.0f, 0.25f);
 glCallList (crateList [0]);

 glTranslatef (-1.0f, 2.0f, -1.0f);
 glRotatef (35, 0.0f, 1.0f, 0.0f);
 glCallList (crateList [0]);

 glDisable (GL_LIGHTING);// Запрет освещения
}

void crateSmall ()
{
 glEnable (GL_LIGHTING);// Разрешить освещение

 int thisN=mapExt [mapVZ] [mapVX];

 myColor3f (1.0f, 1.0f, 1.0f);

 if (crateObj [thisN].angle1!=0.0f)
 {
  glRotatef (crateObj [thisN].angle1, 0.0f, 1.0f, 0.0f);
  glCallList (crateList [1]);
  glRotatef (-crateObj [thisN].angle1, 0.0f, 1.0f, 0.0f);
 }
 else
  glCallList (crateList [1]);

 if (crateObj [thisN].q>1)
 {
  glTranslatef (0.0f, 1.0f, 0.0f);

  if (crateObj [thisN].angle2!=0.0f)
  {
   glRotatef (crateObj [thisN].angle2, 0.0f, 1.0f, 0.0f);
   glCallList (crateList [1]);
   glRotatef (-crateObj [thisN].angle2, 0.0f, 1.0f, 0.0f);
  }
  else
   glCallList (crateList [1]);

  glTranslatef (0.0f, -1.0f, 0.0f);
 }

 glDisable (GL_LIGHTING);// Запрет освещения

 if (mapX==mapVX && mapZ==mapVZ)
  hillRh=1.0f;
}

void hill ()
{
 int zi, xi, zt=0, xt, n=0;
 float tx, tz, txa, tza, xtq, ztq;

 if (mapSV==63)
  n=1;

 xtq=1.0f/float(hillObj [n].hillXq/hillObj [n].hillCells),
 ztq=1.0f/float(hillObj [n].hillZq/hillObj [n].hillCells);

 myColor3f (0.75f, 0.75f, 0.75f);
 if (mapSV!=67)
  glBindTexture (GL_TEXTURE_2D, texture [1]);
 else
  glBindTexture (GL_TEXTURE_2D, texture [4]);

 glBegin (GL_QUADS);// Полигоны
 for (zi=0; zi<hillObj [n].hillZq; zi++)
 {
  xt=0;
  for (xi=0; xi<hillObj [n].hillXq; xi++)
  {
   txa=squareL*2.0f*(float)hillObj [n].hillCells/(float)hillObj [n].hillXq;
   tza=squareL*2.0f*(float)hillObj [n].hillCells/(float)hillObj [n].hillZq;
   tx=-squareL*(float)hillObj [n].hillCells+txa*xi;
   tz=-squareL*(float)hillObj [n].hillCells+tza*zi;

   glTexCoord2f ((float)xt*xtq, 1.0f-(float)zt*ztq);         glVertex3f (tx, hillObj [n].hillAr [zi] [xi]/hillObj [n].hillHk+hillObj [n].hillBottom, tz);// Верх лево
   glTexCoord2f ((float)xt*xtq, 1.0f-(float)(zt+1)*ztq);     glVertex3f (tx, hillObj [n].hillAr [zi+1] [xi]/hillObj [n].hillHk+hillObj [n].hillBottom, tz+tza);// Низ лево
   glTexCoord2f ((float)(xt+1)*xtq, 1.0f-(float)(zt+1)*ztq); glVertex3f (tx+txa, hillObj [n].hillAr [zi+1] [xi+1]/hillObj [n].hillHk+hillObj [n].hillBottom,  tz+tza);// Низ право
   glTexCoord2f ((float)(xt+1)*xtq, 1.0f-(float)zt*ztq);     glVertex3f (tx+txa, hillObj [n].hillAr [zi] [xi+1]/hillObj [n].hillHk+hillObj [n].hillBottom, tz);// Верх право

   xt++;
   if (xt==(hillObj [n].hillXq/hillObj [n].hillCells))
    xt=0;
  }
  zt++;
  if (zt==(hillObj [n].hillZq/hillObj [n].hillCells))
   zt=0;
 }
 glEnd ();
}

void hillH (int hillX, int hillZ, int hillSV)
{
 int hillCellX=0, hillCellZ=0, hillSubCellX=0, hillSubCellZ=0, hillRx=0, hillRz=0, n=0;

 if (hillSV==63)
  n=1;

 hillCellX=(mapX-hillX)+(hillObj [n].hillCells+1)/2;
 hillCellZ=(hillZ-mapZ)+(hillObj [n].hillCells+1)/2;

 hillSubCellX=(x+squareL)/(squareL*2)*100.0f/(100.0f/(hillObj [n].hillXq/hillObj [n].hillCells));
 hillSubCellZ=(squareL-z)/(squareL*2)*100.0f/(100.0f/(hillObj [n].hillZq/hillObj [n].hillCells));

 hillRx=(hillCellX-1)*(hillObj [n].hillXq/hillObj [n].hillCells)+hillSubCellX+1;
 hillRz=(hillCellZ-1)*(hillObj [n].hillZq/hillObj [n].hillCells)+hillSubCellZ+1;

 hillRh=float (hillObj [n].hillAr [hillRz-1] [hillRx-1]+hillObj [n].hillAr [hillRz-1] [hillRx]+
               hillObj [n].hillAr [hillRz] [hillRx-1]+hillObj [n].hillAr [hillRz] [hillRx])/
               hillObj [n].hillHk/4.0f+hillObj [n].hillBottom;
 if (hillRh<0.0f)
  hillRh=0.0f;
}

void bush ()
{
 int bushN=mapExt [mapVZ] [mapVX];

 myColor3f (bushObj [bushN].colorR, bushObj [bushN].colorG, bushObj [bushN].colorB);
 glCallList (bushList [bushObj [bushN].type]);
}

void treeB ()
{
 int i, treeN=mapExt [mapVZ] [mapVX];
 float treeFar=(objDist-(objFar ()-sqrt (pow (squareL, 2)*2)))/objDist;;
 if (treeFar>1.0f)
  treeFar=1.0f;
 else if (treeFar<0.0f)
  treeFar=0.0f;

 int treeCyl=int (4.0f+25.0f*treeFar);//, treeSphere=10, treeSphereB=7;

 glTranslatef (0.0f, -0.1f, 0.0f);
 glRotatef (treeObjB [treeN].angle, 0.0f, treeObjB [treeN].angleX, treeObjB [treeN].angleZ);

 myColor3f (treeObjB [treeN].cronaColorR, treeObjB [treeN].cronaColorG, treeObjB [treeN].cronaColorB);
 glCallList (cronaList);

 glRotatef (-90, 1.0f, 0.0f, 0.0f);

 myColor3f (treeObjB [treeN].colorR, treeObjB [treeN].colorG, treeObjB [treeN].colorB);
 glBindTexture (GL_TEXTURE_2D, texture [16]);
 //                основание, вершина, длина
 gluCylinder (quadratic, 0.25f, 0.05f, 4.55f, treeCyl, 2);// Рисуем наш цилиндр

 glRotatef (90, 1.0f, 0.0f, 0.0f);
 glRotatef (-treeObjB [treeN].angle, 0.0f, treeObjB [treeN].angleX, treeObjB [treeN].angleZ);
 glTranslatef (0.0f, 0.1f, 0.0f);
}

void tree ()
{
 int i, treeN=mapExt [mapVZ] [mapVX];
 float treeFar=(objDist-(objFar ()-sqrt (pow (squareL, 2)*2)))/objDist;;
 if (treeFar>1.0f)
  treeFar=1.0f;
 else if (treeFar<0.0f)
  treeFar=0.0f;

 int treeCyl=int (4.0f+25.0f*treeFar), treeSphere=10, treeSphereB=7;

 myColor3f (treeObj [treeN].colorR, treeObj [treeN].colorG, treeObj [treeN].colorB);
 glBindTexture (GL_TEXTURE_2D, texture [16]);

 glTranslatef (0.0f, -0.1f, 0.0f);
 glRotatef (treeObj [treeN].angle, 0.0f, treeObj [treeN].angleX, treeObj [treeN].angleZ);
 glRotatef (-90, 1.0f, 0.0f, 0.0f);

 //                основание, вершина, длина
 gluCylinder (quadratic, 0.55f, 0.25f, treeObj [treeN].cronaH-treeObj [treeN].cronaR+0.35f, treeCyl, 2);// Рисуем наш цилиндр

 myColor3f (treeObj [treeN].cronaColorR, treeObj [treeN].cronaColorG, treeObj [treeN].cronaColorB);
 glBindTexture (GL_TEXTURE_2D, texture [17]);
 glRotatef (-treeWindAngle*treeWindDir/50.0f, treeWindX, treeWindZ, 0.0f);
 glTranslatef (0.0f, 0.0f, treeObj [treeN].cronaH);
 gluSphere (quadratic, treeObj [treeN].cronaR, treeSphere, treeSphere);// Рисуем сферу
 glTranslatef (0.0f, 0.0f, -treeObj [treeN].cronaH);

 glTranslatef (0.0f, 0.0f, treeObj [treeN].cronaH+treeObj [treeN].cronaR-0.5f);
 gluSphere (quadratic, treeObj [treeN].cronaR-0.65f, treeSphere, treeSphereB);// Рисуем сферу
 glTranslatef (0.0f, 0.0f, -(treeObj [treeN].cronaH+treeObj [treeN].cronaR-0.5f));
 glRotatef (treeWindAngle*treeWindDir/50.0f, treeWindX, treeWindZ, 0.0f);

 glRotatef (90, 1.0f, 0.0f, 0.0f);
 glRotatef (-treeObj [treeN].angle, 0.0f, treeObj [treeN].angleX, treeObj [treeN].angleZ);
 glTranslatef (0.0f, 0.1f, 0.0f);
}

void treeWind ()
{
 treeVolMx=0;

 if (!(treeWindTime && clock ()-treeWindTime<35000) && treeHold)
 {
  if (rand ()%2==1)
  {
   treeWindAngle=0;
   setWind ();
  }
  treeWindTime=clock ();
 }

 if (treeHold && clock ()-treeHold<3500)
  return;

 treeWindAngle+=float (rand ()%5)*fpsTweak ()*(float)treeWindAngleDir;
 if (treeWindAngle>50)
 {
  treeWindAngle=50;
  treeWindAngleDir=-1;
  treeWindState++;
 }
 else if (treeWindAngle<-250)
 {
  treeWindAngle=-250;
  treeWindAngleDir=1;
  treeWindState++;
 }

 treeHold=0;
 if (treeWindState==2 && treeWindAngle<2)
 {
  if (rand ()%2==1)
   treeHold=clock ();
  treeWindState=0;
 }
}

void treeSnd1 ()
{
 int treeVol=objSnd ();

 if (treeVol>treeVolMx)
  treeVolMx=treeVol;
}

void treeSnd2 ()
{
 if (rand()%2==1 && clock ()-treeTime>1500 && treeVolMx>0)
 {
  if (rand()%5==0)
   playSound ("bird1", treeVolMx);
  else if (rand()%5==1)
   playSound ("bird2", treeVolMx);
  else if (rand()%5==2)
   playSound ("bird3", treeVolMx);
  else if (rand()%5==3)
   playSound ("bird4", treeVolMx);
  else
   playSound ("bird5", treeVolMx);

  treeTime=clock ();
 }
}

void wall ()
{
 int n=mapExt [mapVZ] [mapVX];

 if (n==0 || n==5)
  wallX ();
 else if (n==1)
  wallXl ();
 else if (n==2)
  wallXr ();
}

void wallX ()
{
 float fenceH=2.0f, fX=1.0f, fZ=0.5f;

 myColor3f (1.0f, 1.0f, 1.0f);

 if (mapExt [mapVZ] [mapVX]==5 && mapZ<=mapVZ)
 {
  glBindTexture (GL_TEXTURE_2D, texture [47]);
  glBegin (GL_QUADS);

  // Передняя грань
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX, 0.0f,   fZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( fX, 0.0f,   fZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( fX, fenceH, fZ);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-fX, fenceH, fZ);// Верх лево

  glEnd ();
 }

 glBindTexture (GL_TEXTURE_2D, texture [9]);
 glBegin (GL_QUADS);

 if (mapZ<=mapVZ && mapExt [mapVZ] [mapVX]!=5)
 {
  // Передняя грань
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX, 0.0f,   fZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( fX, 0.0f,   fZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f ( fX, fenceH, fZ);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-fX, fenceH, fZ);// Верх лево
 }
 if (mapZ>=mapVZ)
 {
  // Задняя грань
  glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-fX, 0.0f,   -fZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-fX, fenceH, -fZ);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f ( fX, fenceH, -fZ);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f ( fX, 0.0f,   -fZ);// Низ лево
 }

 if (hillRh0>0.1f)
 {
  // Верхняя грань
  glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
  glTexCoord2f (0.0f, 0.5f); glVertex3f (-fX,  fenceH, -fZ);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,  fenceH,  fZ);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( fX,  fenceH,  fZ);// Низ право
  glTexCoord2f (1.0f, 0.5f); glVertex3f ( fX,  fenceH, -fZ);// Верх право
 }

 glEnd ();

 if (mapX==mapVX && mapZ==mapVZ)
  hillRh=2.0f;
}

void wallXl ()
{
 glRotatef (-180, 0.0f, 1.0f, 0.0f);
 wallXr ();
 glRotatef (-180, 0.0f, 1.0f, 0.0f);
}

void wallXr ()
{
 float fenceH=2.0f, fX=1.0f, fZ=0.5f;

 myColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [9]);
 glBegin (GL_QUADS);

 // Передняя грань
 glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,   0.0f,   fZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( 0.0f, 0.0f,   fZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( 0.0f, fenceH, fZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-fX,   fenceH, fZ);// Верх лево

 // Задняя грань
 glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-fX,   0.0f,   -fZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-fX,   fenceH, -fZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( 0.0f, fenceH, -fZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( 0.0f, 0.0f,   -fZ);// Низ лево

 // Верхняя грань
 glNormal3f (0.0f, 1.0f, 0.0f);// Нормаль указывает вверх
 glTexCoord2f (0.0f, 0.5f); glVertex3f (-fX,   fenceH, -fZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,   fenceH,  fZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( 0.0f, fenceH,  fZ);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f ( 0.0f, fenceH, -fZ);// Верх право

 // Правая грань
 glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( 0.0f, 0.0f,   -fZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( 0.0f, fenceH, -fZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( 0.0f, fenceH,  fZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( 0.0f, 0.0f,    fZ);// Низ лево

 glEnd ();

 if (mapX==mapVX && mapZ==mapVZ)
  hillRh=2.0f;
}

void fence ()
{
 float fBaseH=0.5f, fGridH=1.65f, fX=0.5f, fZ=1.0f, fR=0.15f, fLeft=0.0f, fRight=0.0f, fB=0.05f, fB2=0.01f;

 int n=mapExt [mapVZ] [mapVX];

 if (n==1)
  fLeft=0.25f;
 else if (n==2)
  fRight=0.25f;


 // Сетка
 glEnable (GL_ALPHA_TEST);
 glAlphaFunc (GL_NOTEQUAL, 0.0f);
 myColor3f (0.75f, 0.75f, 0.75f);
 glBindTexture (GL_TEXTURE_2D, texture [30]);

 glBegin (GL_QUADS);
 if (mapX==mapVX)
 {
  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  // Передняя грань
  glTexCoord2f (0.0f, 0.0f); glVertex3f (0.0f, fBaseH,        -fZ+fLeft); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (0.0f, fBaseH,         fZ-fRight);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH,  fZ-fRight);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH, -fZ+fLeft); // Верх лево
  glPolygonMode (GL_BACK, GL_LINE);
  glPolygonMode (GL_FRONT, GL_FILL);
 }
 if (mapX<mapVX)
 {
  // Передняя грань
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (0.0f, fBaseH,        -fZ+fLeft); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (0.0f, fBaseH,         fZ-fRight);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH,  fZ-fRight);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH, -fZ+fLeft); // Верх лево
 }
 else
 {
  // Задняя грань
  glNormal3f (0.0f, 0.0f, -1.0f);     // Нормаль указывает от наблюдателя
  glTexCoord2f (1.0f, 0.0f); glVertex3f (0.0f, fBaseH,        -fZ+fLeft); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH, -fZ+fLeft); // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH,  fZ-fRight);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (0.0f, fBaseH,         fZ-fRight);// Низ лево
 }
 glEnd ();

 glDisable (GL_ALPHA_TEST);

 // Основание
 myColor3f (0.35f, 0.35f, 0.35f);
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 glBegin (GL_QUADS);

 if (n==0)
 {
  // Передняя грань
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,  0.0f,   -fZ+fLeft); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-fX,  0.0f,    fZ-fRight);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH,  fZ-fRight);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH, -fZ+fLeft); // Верх лево

  // Задняя грань
  glTexCoord2f (1.0f, 0.0f); glVertex3f (fX,   0.0f,   -fZ+fLeft); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH, -fZ+fLeft); // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH,  fZ-fRight);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (fX,   0.0f,    fZ-fRight);// Низ лево
 }
 else if (n==1)
 {
  // Передняя грань
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,  0.0f,   -fZ+fLeft-fB); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-fX,  0.0f,    fZ-fRight);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH,  fZ-fRight);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH, -fZ+fLeft-fB); // Верх лево

  // Задняя грань
  glTexCoord2f (1.0f, 0.0f); glVertex3f (fX,   0.0f,   -fZ+fLeft-fB); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH, -fZ+fLeft-fB); // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH,  fZ-fRight);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (fX,   0.0f,    fZ-fRight);// Низ лево
 }
 else if (n==2)
 {
  // Передняя грань
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,  0.0f,   -fZ+fLeft); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-fX,  0.0f,    fZ-fRight+fB);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH,  fZ-fRight+fB);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH, -fZ+fLeft); // Верх лево

  // Задняя грань
  glTexCoord2f (1.0f, 0.0f); glVertex3f (fX,   0.0f,   -fZ+fLeft); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH, -fZ+fLeft); // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH,  fZ-fRight+fB);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (fX,   0.0f,    fZ-fRight+fB);// Низ лево
 }

 glEnd ();

 // Верх
 int fEdges=4;

 myColor3f (0.35f, 0.35f, 0.35f);
 glBindTexture (GL_TEXTURE_2D, texture [10]);

 //                основание, вершина, длина
 if (n==1)
 {
  glTranslatef (0.0f, fBaseH+fGridH+fR, -fZ+fLeft-fB);
  gluCylinder (quadratic, fR, fR, fZ*2-fLeft+fB, fEdges, 1);// Рисуем наш цилиндр
  glTranslatef (0.0f, -(fBaseH+fGridH+fR), fZ-fLeft+fB);
 }
 else if (n==2)
 {
  glTranslatef (0.0f, fBaseH+fGridH+fR, -fZ);
  gluCylinder (quadratic, fR, fR, fZ*2-fRight+fB, fEdges, 1);// Рисуем наш цилиндр
  glTranslatef (0.0f, -(fBaseH+fGridH+fR), fZ);
 }
 else
 {
  glBegin (GL_QUADS);
  // Передняя грань
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fR,  fBaseH+fGridH+fR,   -fZ+fLeft); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-fR,  fBaseH+fGridH+fR,    fZ-fRight);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH+fR*2,  fZ-fRight);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH+fR*2, -fZ+fLeft); // Верх лево

  // Передняя грань
  glTexCoord2f (0.0f, 0.0f); glVertex3f (0.0f,  fBaseH+fGridH,   -fZ+fLeft); // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (0.0f,  fBaseH+fGridH,    fZ-fRight);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-fR, fBaseH+fGridH+fR,  fZ-fRight);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-fR, fBaseH+fGridH+fR, -fZ+fLeft); // Верх лево

  // Задняя грань
  glTexCoord2f (1.0f, 0.0f); glVertex3f (fR,   fBaseH+fGridH+fR,   -fZ+fLeft); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH+fR*2, -fZ+fLeft); // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (0.0f, fBaseH+fGridH+fR*2,  fZ-fRight);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (fR,   fBaseH+fGridH+fR,    fZ-fRight);// Низ лево

  // Задняя грань
  glTexCoord2f (1.0f, 0.0f); glVertex3f (0.0f,   fBaseH+fGridH,   -fZ+fLeft); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (fR, fBaseH+fGridH+fR, -fZ+fLeft); // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (fR, fBaseH+fGridH+fR,  fZ-fRight);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (0.0f,   fBaseH+fGridH,    fZ-fRight);// Низ лево

  glEnd ();
 }

 // Боковины
 if (n==1)
 {
  glTranslatef (0.0f, 0.0f, -fZ+fLeft+fR-fB2);
  glRotatef (-90, 1.0f, 0.0f, 0.0f);
  gluCylinder (quadratic, fR, fR, fBaseH+fGridH+fR, fEdges, 1);// Рисуем наш цилиндр
  glRotatef (90, 1.0f, 0.0f, 0.0f);

  myColor3f (0.55f, 0.55f, 0.55f);
  glTranslatef (0.0f, fBaseH+fGridH+fR, -fR-fB+fB2);
  glRotatef (-180, 0.0f, 1.0f, 0.0f);
  gluDisk (quadratic, 0, fR, fEdges, 2);// Рисуем диск
  glRotatef (180, 0.0f, 1.0f, 0.0f);
  glTranslatef (0.0f, -(fBaseH+fGridH+fR), fR+fB);

  glTranslatef (0.0f, 0.0f, fZ-fLeft-fR);

  glBegin(GL_TRIANGLES);
  glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f ( fX,   0.0f,   -fZ+fLeft-fB);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-fX,   0.0f,   -fZ+fLeft-fB);// Низ право
  glTexCoord2f (0.5f, 1.0f); glVertex3f ( 0.0f, fBaseH, -fZ+fLeft-fB);// Верх
  glEnd ();
 }
 else if (n==2)
 {
  glTranslatef (0.0f, 0.0f, fZ-fRight-fR+fB2);
  glRotatef (-90, 1.0f, 0.0f, 0.0f);
  gluCylinder (quadratic, fR, fR, fBaseH+fGridH+fR, fEdges, 1);// Рисуем наш цилиндр
  glRotatef (90, 1.0f, 0.0f, 0.0f);

  myColor3f (0.55f, 0.55f, 0.55f);
  glTranslatef (0.0f, fBaseH+fGridH+fR, fR+fB-fB2);
  gluDisk (quadratic, 0, fR, fEdges, 2);// Рисуем диск
  glTranslatef (0.0f, -(fBaseH+fGridH+fR), -fR-fB);

  glTranslatef (0.0f, 0.0f, -fZ+fRight+fR);

  glBegin(GL_TRIANGLES);
  glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-fX,   0.0f,   fZ-fRight+fB);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( fX,   0.0f,   fZ-fRight+fB);// Низ право
  glTexCoord2f (0.5f, 1.0f); glVertex3f ( 0.0f, fBaseH, fZ-fRight+fB);// Верх
  glEnd ();
 }
}

float cornAngle=0.0f;
void corner ()
{
 float thisH=0.5f, thisX=1.0f, thisZ=1.0f;

 myColor3f (0.75f, 0.75f, 0.5f);
 glBindTexture (GL_TEXTURE_2D, texture [15]);
 glBegin (GL_QUADS);

 // Передняя грань
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, 0.0f,   thisZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( thisX, 0.0f,   thisZ);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f ( thisX, thisH,  thisZ);// Верх право
 glTexCoord2f (0.0f, 0.5f); glVertex3f (-thisX, thisH,  thisZ);// Верх лево

 // Задняя грань
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, 0.0f,  -thisZ);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f (-thisX, thisH, -thisZ);// Верх право
 glTexCoord2f (0.0f, 0.5f); glVertex3f ( thisX, thisH, -thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( thisX, 0.0f,  -thisZ);// Низ лево

 myColor3f (1.0f, 1.0f, 1.0f);
 // Верхняя грань
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-thisX, thisH, -thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, thisH,  thisZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( thisX, thisH,  thisZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( thisX, thisH, -thisZ);// Верх право
 myColor3f (0.75f, 0.75f, 0.5f);

 // Правая грань
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( thisX, 0.0f,  -thisZ);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f ( thisX, thisH, -thisZ);// Верх право
 glTexCoord2f (0.0f, 0.5f); glVertex3f ( thisX, thisH,  thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( thisX, 0.0f,   thisZ);// Низ лево

 // Левая грань
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-thisX, 0.0f,   thisZ);// Низ право
 glTexCoord2f (1.0f, 0.5f); glVertex3f (-thisX, thisH,  thisZ);// Верх право
 glTexCoord2f (0.0f, 0.5f); glVertex3f (-thisX, thisH, -thisZ);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-thisX, 0.0f,  -thisZ);// Низ лево

 glEnd ();

 cornAngle+=1.0f*fpsTweak (); 

 glEnable (GL_LIGHTING);// Разрешить освещение

 myColor3f (0.85f, 0.85f, 0.85f);
 glBindTexture (GL_TEXTURE_2D, texture [15]);

 glRotatef (-90, 1.0f, 0.0f, 0.0f);
 glTranslatef (0.0f, 0.0f, 1.5f);
 //                основание, вершина, длина
 glRotatef (cornAngle, 0.0f, 0.0f, 1.0f);
 gluSphere (quadratic, 0.75f, 16, 16);// Рисуем сферу
 glRotatef (-cornAngle, 0.0f, 0.0f, 1.0f);
 glTranslatef (0.0f, 0.0f, -1.5f);
 glRotatef (90, 1.0f, 0.0f, 0.0f);

 glDisable (GL_LIGHTING);// Запрет освещения
}

void house ()
{
 int i, n;

 float houseH=3.0f, houseL=6.0f, houseW=4.0f, hBottomAdd=1.0f, hUpAdd=0.5f,
       houseRoofH=3.0f, houseRoofSide=1.5f;

 n=mapExt [mapBZ] [mapBX];
 if (n==2)
  glRotatef (-180.0f, 0.0f, 1.0f, 0.0f);

 glEnable (GL_LIGHTING);// Разрешить освещение

 myColor3f (1.0f, 1.0f, 1.0f);
 if (n==2)
  glBindTexture (GL_TEXTURE_2D, texture [23]);
 else
  glBindTexture (GL_TEXTURE_2D, texture [12]);
 glBegin(GL_QUADS);
 // Передняя грань
 glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL, 0.0f,   houseW);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( houseL, 0.0f,   houseW);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( houseL, houseH, houseW);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL, houseH, houseW);// Верх лево

 // Задняя грань
 glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL, 0.0f,   -houseW);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL, houseH, -houseW);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( houseL, houseH, -houseW);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( houseL, 0.0f,   -houseW);// Низ лево
 glEnd ();

 glBegin(GL_QUADS);
 // Правая грань
 glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
 glTexCoord2f (0.65f, 0.0f); glVertex3f (houseL, 0.0f,   -houseW);// Низ право
 glTexCoord2f (0.65f, 1.0f); glVertex3f (houseL, houseH, -houseW);// Верх право
 glTexCoord2f (0.0f, 1.0f);  glVertex3f (houseL, houseH,  houseW);// Верх лево
 glTexCoord2f (0.0f, 0.0f);  glVertex3f (houseL,  0.0f,   houseW);// Низ лево

 // Левая грань
 glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
 glTexCoord2f (0.35f, 0.0f); glVertex3f (-houseL, 0.0f,   -houseW);// Низ лево
 glTexCoord2f (1.0f, 0.0f);  glVertex3f (-houseL, 0.0f,    houseW);// Низ право
 glTexCoord2f (1.0f, 1.0f);  glVertex3f (-houseL, houseH,  houseW);// Верх право
 glTexCoord2f (0.35f, 1.0f); glVertex3f (-houseL, houseH, -houseW);// Верх лево
 glEnd ();

 glDisable (GL_LIGHTING);// Запрет освещения

 // Нижняя грань
 glBindTexture (GL_TEXTURE_2D, texture [20]);// 1
 myColor3f (0.35f, 0.35f, 0.35f);
 glBegin(GL_QUADS);
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-hBottomAdd, 0.0f, -houseW-hBottomAdd);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-hBottomAdd, 0.0f,  houseW+hBottomAdd);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( houseL+hBottomAdd, 0.0f,  houseW+hBottomAdd);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( houseL+hBottomAdd, 0.0f, -houseW-hBottomAdd);// Верх право
 glEnd ();

 // Верхняя грань
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 if (n==2)
  myColor3f (0.45f, 0.25f, 0.05f);
 else
  myColor3f (33.0f/255.0f, 24.0f/255.0f, 15.0f/255.0f);
 glBegin (GL_QUADS);
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-hUpAdd, houseH, -houseW-hUpAdd);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( houseL+hUpAdd, houseH, -houseW-hUpAdd);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( houseL+hUpAdd, houseH,  houseW+hUpAdd);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-hUpAdd, houseH,  houseW+hUpAdd);// Низ право
 glEnd ();

 myColor3f (0.5f, 0.5f, 0.5f);
 if (n==2)
  glBindTexture (GL_TEXTURE_2D, texture [10]);
 else
  glBindTexture (GL_TEXTURE_2D, texture [24]);
 glBegin (GL_QUADS);
 // Передняя часть крыши
 glTexCoord2f (0.0f, 0.0f);                                   glVertex3f (-houseL-hUpAdd,               houseH,            houseW+hUpAdd);// Низ лево
 glTexCoord2f (1.0f, 0.0f);                                   glVertex3f ( houseL+hUpAdd,               houseH,            houseW+hUpAdd);// Низ право
 glTexCoord2f (1.0f-(houseRoofSide)/(houseL+hUpAdd)/2, 1.0f); glVertex3f ( houseL+hUpAdd-houseRoofSide, houseH+houseRoofH, 0.0f);         // Верх право
 glTexCoord2f ((houseRoofSide)/(houseL+hUpAdd)/2, 1.0f);      glVertex3f (-houseL-hUpAdd+houseRoofSide, houseH+houseRoofH, 0.0f);         // Верх лево

 // Задняя часть крыши
 glTexCoord2f (1.0f, 0.0f);                                   glVertex3f (-houseL-hUpAdd,               houseH,            -houseW-hUpAdd);// Низ право
 glTexCoord2f (1.0f-(houseRoofSide)/(houseL+hUpAdd)/2, 1.0f); glVertex3f (-houseL-hUpAdd+houseRoofSide, houseH+houseRoofH,  0.0f);         // Верх право
 glTexCoord2f ((houseRoofSide)/(houseL+hUpAdd)/2, 1.0f);      glVertex3f ( houseL+hUpAdd-houseRoofSide, houseH+houseRoofH,  0.0f);         // Верх лево
 glTexCoord2f (0.0f, 0.0f);                                   glVertex3f ( houseL+hUpAdd,               houseH,            -houseW-hUpAdd);// Низ лево
 glEnd ();

 myColor3f (0.5f, 0.5f, 0.5f);
 if (n==2)
 {
  glBindTexture (GL_TEXTURE_2D, texture [10]);
  glBegin(GL_TRIANGLES);
  // Левая часть крыши
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-hUpAdd,               houseH,            -houseW-hUpAdd);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-hUpAdd,               houseH,             houseW+hUpAdd);// Низ право
  glTexCoord2f (0.5f, 1.0f); glVertex3f (-houseL-hUpAdd+houseRoofSide, houseH+houseRoofH,  0.0f);         // Верх

  // Правая часть крыши
  glTexCoord2f (1.0f, 0.0f); glVertex3f ( houseL+hUpAdd,               houseH,            -houseW-hUpAdd);// Низ право
  glTexCoord2f (0.5f, 1.0f); glVertex3f ( houseL+hUpAdd-houseRoofSide, houseH+houseRoofH,  0.0f);         // Верх
  glTexCoord2f (0.0f, 0.0f); glVertex3f ( houseL+hUpAdd,               houseH,             houseW+hUpAdd);// Низ лево
  glEnd ();
 }
 else
 {
  glBindTexture (GL_TEXTURE_2D, texture [24]);
  glBegin(GL_TRIANGLES);
  // Левая часть крыши
  glTexCoord2f (0.15f, 0.0f); glVertex3f (-houseL-hUpAdd,               houseH,            -houseW-hUpAdd);// Низ лево
  glTexCoord2f (0.85f, 0.0f); glVertex3f (-houseL-hUpAdd,               houseH,             houseW+hUpAdd);// Низ право
  glTexCoord2f (0.5f, 1.0f);  glVertex3f (-houseL-hUpAdd+houseRoofSide, houseH+houseRoofH,  0.0f);         // Верх

  // Правая часть крыши
  glTexCoord2f (0.85f, 0.0f); glVertex3f ( houseL+hUpAdd,               houseH,            -houseW-hUpAdd);// Низ право
  glTexCoord2f (0.5f, 1.0f);  glVertex3f ( houseL+hUpAdd-houseRoofSide, houseH+houseRoofH,  0.0f);         // Верх
  glTexCoord2f (0.15f, 0.0f); glVertex3f ( houseL+hUpAdd,               houseH,             houseW+hUpAdd);// Низ лево
  glEnd ();
 }

 // Дверь
 float doorH=2.8f, doorW=1.0f, doorT=0.1f;

 // Внешняя поверхность
 myColor3f (0.5f, 0.5f, 0.5f);
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 glBegin(GL_QUADS);
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT, 0.0f,  -doorW);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT, 0.0f,   doorW);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT, doorH,  doorW);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT, doorH, -doorW);// Верх лево
 glEnd ();

 myColor3f (0.45f, 0.25f, 0.05f);
 glBegin (GL_QUADS);
 // Правая боковина
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT, 0.0f,  doorW);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL,       0.0f,  doorW);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL,       doorH, doorW);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT, doorH, doorW);// Верх лево

 // Левая
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT, 0.0f,  -doorW);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT, doorH, -doorW);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL,       doorH, -doorW);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL,       0.0f,  -doorW);// Низ лево

 // Верхняя
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT, doorH, -doorW);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT, doorH,  doorW);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL,       doorH,  doorW);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL,       doorH, -doorW);// Верх право
 glEnd ();

 if (n==1)
 {
  // Замок
  float lockT=0.025f, lockY=doorH/2-0.15f;

  myColor3f (0.45f, 0.25f, 0.05f);
  glBegin(GL_QUADS);
  // Правая боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT-lockT, lockY-0.1f, doorW-0.25f);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT,       lockY-0.1f, doorW-0.25f);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT,       lockY+0.1f, doorW-0.25f);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT-lockT, lockY+0.1f, doorW-0.25f);// Верх лево

  // Левая
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT-lockT, lockY-0.1f, doorW-0.45f);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT-lockT, lockY+0.1f, doorW-0.45f);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT,       lockY+0.1f, doorW-0.45f);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT,       lockY-0.1f, doorW-0.45f);// Низ лево

  // Нижняя
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT-lockT, lockY-0.1f, doorW-0.45f);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f ( houseL-doorT,       lockY-0.1f, doorW-0.45f);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f ( houseL-doorT,       lockY-0.1f, doorW-0.25f);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT-lockT, lockY-0.1f, doorW-0.25f);// Низ право

  // Верхняя
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT-lockT, lockY+0.1f, doorW-0.45f);// Верх лево
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT-lockT, lockY+0.1f, doorW-0.25f);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT,       lockY+0.1f, doorW-0.25f);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT,       lockY+0.1f, doorW-0.45f);// Верх право
  glEnd ();

  // Внешняя поверхность
  myColor3f (1.0f, 1.0f, 1.0f);
  glBindTexture (GL_TEXTURE_2D, texture [13]);
  glBegin(GL_QUADS);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (-houseL-doorT-lockT, lockY-0.1f, doorW-0.45f);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (-houseL-doorT-lockT, lockY-0.1f, doorW-0.25f);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (-houseL-doorT-lockT, lockY+0.1f, doorW-0.25f);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-houseL-doorT-lockT, lockY+0.1f, doorW-0.45f);// Верх лево
  glEnd ();
 }

 // Окно
 float windowW=1.25f, windowH=0.75f, windowX=-2.5f, windowY=1.85f,
       windowT1=0.025f, windowT2=0.1f, windowT4=0.1f;

 for (i=0; i<2; i++)
 {
  if (i==1)
   windowX=2.5f;

  glEnable (GL_LIGHTING);// Разрешить освещение

  // Внешняя поверхность
  myColor3f (1.0f, 1.0f, 1.0f);
  glBindTexture (GL_TEXTURE_2D, texture [14]);
  glBegin(GL_QUADS);
  glNormal3f( 0.0f, 0.0f, 1.0f);     // Нормаль указывает на наблюдателя
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW, windowY-windowH, houseW+windowT1);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW, windowY-windowH, houseW+windowT1);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW, windowY+windowH, houseW+windowT1);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW, windowY+windowH, houseW+windowT1);// Верх лево
  glEnd ();

  glDisable (GL_LIGHTING);// Запрет освещения

  glBindTexture (GL_TEXTURE_2D, texture [10]);
  myColor3f (0.45f, 0.25f, 0.05f);
  glBegin(GL_QUADS);
  // Левая внутренняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW, windowY-windowH, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX-windowW, windowY-windowH, houseW+windowT1);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX-windowW, windowY+windowH, houseW+windowT1);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW, windowY+windowH, houseW+windowT2);// Верх лево

  // Правая внутренняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX+windowW, windowY-windowH, houseW+windowT1);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW, windowY-windowH, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW, windowY+windowH, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX+windowW, windowY+windowH, houseW+windowT1);// Верх лево

  // Верхняя внутренняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW, windowY+windowH, houseW+windowT1);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW, windowY+windowH, houseW+windowT1);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW, windowY+windowH, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW, windowY+windowH, houseW+windowT2);// Верх лево

  // Нижняя внутренняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW, windowY-windowH, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW, windowY-windowH, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW, windowY-windowH, houseW+windowT1);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW, windowY-windowH, houseW+windowT1);// Верх лево

  // Правая внешняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH-windowT4, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH-windowT4, houseW);         // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH+windowT4, houseW);         // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH+windowT4, houseW+windowT2);// Верх лево

  // Левая внешнняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH-windowT4, houseW);         // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH-windowT4, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH+windowT4, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH+windowT4, houseW);         // Верх лево

  // Верхняя внешняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH+windowT4, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH+windowT4, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH+windowT4, houseW);         // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH+windowT4, houseW);         // Верх лево

  // Нижняя внешнняя боковина
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH-windowT4, houseW);         // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH-windowT4, houseW);         // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH-windowT4, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH-windowT4, houseW+windowT2);// Верх лево
  glEnd ();

  myColor3f (1.0f, 1.0f, 1.0f);
  glBegin(GL_QUADS);
  // Передняя верхняя поверхность
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH,          houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH,          houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH+windowT4, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH+windowT4, houseW+windowT2);// Верх лево

  // Передняя нижняя поверхность
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH-windowT4, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH-windowT4, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH,          houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH,          houseW+windowT2);// Верх лево

  // Передняя левая поверхность
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX-windowW-windowT4, windowY-windowH, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX-windowW,          windowY-windowH, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX-windowW,          windowY+windowH, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX-windowW-windowT4, windowY+windowH, houseW+windowT2);// Верх лево

  // Передняя правая поверхность
  glTexCoord2f (0.0f, 0.0f); glVertex3f (windowX+windowW,          windowY-windowH, houseW+windowT2);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (windowX+windowW+windowT4, windowY-windowH, houseW+windowT2);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (windowX+windowW+windowT4, windowY+windowH, houseW+windowT2);// Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (windowX+windowW,          windowY+windowH, houseW+windowT2);// Верх лево
  glEnd ();
 }

 glEnable (GL_LIGHTING);// Разрешить освещение

 // Ручка
 if (n==2)
  glTranslatef (-houseL-doorT, doorH/2-0.1f, doorW-0.35f);
 else
  glTranslatef (-houseL-doorT, doorH/2+0.1f, doorW-0.35f);
 glRotatef (-90, 0.0f, 1.0f, 0.0f);

 glBindTexture (GL_TEXTURE_2D, texture [31]);
 myColor3f (0.45f, 0.25f, 0.05f);
 gluCylinder (quadratic, 0.05f, 0.1f, 0.15f, 16, 2);// Рисуем наш цилиндр
 glTranslatef (0.0f, 0.0f, 0.15f);
 myColor3f (0.65f, 0.45f, 0.25f);
 gluCylinder (quadratic, 0.1f, 0.07f, 0.025f, 16, 2);// Рисуем наш цилиндр
 glTranslatef (0.0f, 0.0f, 0.025f);
 glBindTexture (GL_TEXTURE_2D, texture [10]);
 myColor3f (1.0f, 1.0f, 1.0f);
 gluDisk (quadratic, 0.0f, 0.07f, 16, 2);// Рисуем диск
 glTranslatef (0.0f, 0.0f, -(0.15f+0.025f));

 glRotatef (90, 0.0f, 1.0f, 0.0f);
 glTranslatef (houseL+doorT+0.15f, -(doorH/2+0.1f), -(doorW-0.35f));

 glDisable (GL_LIGHTING);// Запрет освещения

 // Труба
 myColor3f (0.35f, 0.25f, 0.15f);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 glTranslatef (2.0f, 4.25f, -2.05f);
 glRotatef (-90, 1.0f, 0.0f, 0.0f);
 //                основание, вершина, длина
 gluCylinder (quadratic, 0.35f, 0.35f, 2.15f, 32, 1);// Рисуем наш цилиндр
 glRotatef (90, 1.0f, 0.0f, 0.0f);
}

int crystalTime=0;
float crystalC=0.0f, crystalD=-0.001f, crystalR=0.0f;
void crystalSnd ()
{
 int crystalVol=objSnd ();

 if (crystalVol>0 && clock ()-crystalTime>1500)
 {
  crystalTime=clock ();
  playSound ("crystal", crystalVol);
 }
}

void crystal ()
{
 int n;
 float columnL=0.45f, columnH=3.75f;

 if (!menuOn)
 {
  if (crystalC>1.5f)
  {
   crystalC=1.5f;
   crystalD*=-1;
  }
  else if (crystalC<=0.0f)
  {
   crystalC=0.0f;
   crystalD*=-1;
  }
  crystalC+=crystalD*fpsTweak ();
 }
 glBindTexture (GL_TEXTURE_2D, texture [0]);

 glBegin (GL_TRIANGLES);
 myColor3f (0.1f, 0.3f, 0.7f);                   glVertex3f (-columnL, 0.0f,    columnL);// Низ лево
 myColor3f (0.3f, 0.1f, 0.7f);                   glVertex3f ( columnL, 0.0f,    columnL);// Низ право
 myColor3f (1.0f-crystalC, 1.0f, 1.0f-crystalC); glVertex3f ( 0.0f,    columnH, 0.0f);   // Верх

 myColor3f (0.1f, 0.3f, 0.7f);                   glVertex3f ( columnL, 0.0f,    -columnL);// Низ лево
 myColor3f (0.3f, 0.1f, 0.7f);                   glVertex3f (-columnL, 0.0f,    -columnL);// Низ право
 myColor3f (1.0f-crystalC, 1.0f, 1.0f-crystalC); glVertex3f ( 0.0f,    columnH,  0.0f);   // Верх

 myColor3f (0.1f, 0.3f, 0.7f);                   glVertex3f (-columnL, 0.0f,    -columnL);// Низ лево
 myColor3f (0.3f, 0.1f, 0.7f);                   glVertex3f (-columnL, 0.0f,     columnL);// Низ право
 myColor3f (1.0f-crystalC, 1.0f, 1.0f-crystalC); glVertex3f ( 0.0f,    columnH,  0.0f);   // Верх

 myColor3f (0.1f, 0.3f, 0.7f);                   glVertex3f (columnL, 0.0f,    columnL);// Низ лево
 myColor3f (0.3f, 0.1f, 0.7f);                   glVertex3f (columnL, 0.0f,   -columnL);// Низ право
 myColor3f (1.0f-crystalC, 1.0f, 1.0f-crystalC); glVertex3f (0.0f,    columnH,  0.0f);  // Верх
 glEnd ();
}

void column ()
{
 int n;
 float columnL=0.35f, columnH=5.75f;

 glEnable (GL_LIGHTING);// Разрешить освещение

 myColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [8]);

 glBegin (GL_QUADS);
 // Передняя грань
 glNormal3f (0.0f, 0.0f, 1.0f);// Нормаль указывает на наблюдателя
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-columnL, 0.0f,    columnL);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( columnL, 0.0f,    columnL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( columnL, columnH, columnL);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-columnL, columnH, columnL);// Верх лево

 // Задняя грань
 glNormal3f (0.0f, 0.0f, -1.0f);// Нормаль указывает от наблюдателя
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-columnL, 0.0f,    -columnL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-columnL, columnH, -columnL);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( columnL, columnH, -columnL);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( columnL, 0.0f,    -columnL);// Низ лево

 // Правая грань
 glNormal3f (1.0f, 0.0f, 0.0f);// Нормаль указывает вправо
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( columnL, 0.0f,    -columnL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( columnL, columnH, -columnL);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f ( columnL, columnH,  columnL);// Верх лево
 glTexCoord2f (0.0f, 0.0f); glVertex3f ( columnL, 0.0f,     columnL);// Низ лево

 // Левая грань
 glNormal3f (-1.0f, 0.0f, 0.0f);// Нормаль указывает влево
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-columnL, 0.0f,    -columnL);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (-columnL, 0.0f,     columnL);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (-columnL, columnH,  columnL);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-columnL, columnH, -columnL);// Верх лево
 glEnd ();

 glDisable (GL_LIGHTING);// Запрет освещения
}

void columnCyl ()
{
 glEnable (GL_LIGHTING);// Разрешить освещение

 int thisEdges=32;

 myColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [15]);

 glRotatef (-90, 1.0f, 0.0f, 0.0f);
 //                основание, вершина, длина
 gluCylinder (quadratic, 0.55f, 0.55f, 5.75f, thisEdges, 1);// Рисуем наш цилиндр
 glRotatef (90, 1.0f, 0.0f, 0.0f);

 glDisable (GL_LIGHTING);// Запрет освещения
}

void sky ()
{
 glLoadIdentity ();// Сброс просмотра
 glTranslatef (0.0f, skyH, 0.0f);
 glRotatef (-angleX, 1.0f, 0.0f, 0.0f);

 // far border
 glColor3f (0.5f*gamma, 0.5f*gamma, 0.5f*gamma);
 glCallList (borderHighList);

 glRotatef (-theta, 0.0f, 1.0f, 0.0f);
 myColor3f (1.0f, 1.0f, 1.0f);
 glCallList (skyList);
}

void pointer ()
{
 int tMapX=0, tMapZ=0;
 float angleC=0;
 bool outMode=false;

// if (mapX<0 || mapX>mapQ-1 || mapZ<0 || mapZ>mapQ-1)
//  outMode=true;
// else
 if (!pointerOn)
  return;

 if ((mapZ-mapQ/2)==0 && mapX-mapQ/2==0)
  return;

 if (outMode && !(mapX<0 || mapX>=mapQ || mapZ<0 || mapZ>=mapQ))
  return;

// if ((mapZ==villageZ-2 || mapZ==villageZ-1) && mapX<0)
//  return;

 if (outMode)
 {
  if (mapX>=mapQ)
   tMapX=mapX-mapQ+1;
  else if (mapX<0)
   tMapX=mapX;

  if (mapZ>=mapQ)
   tMapZ=mapZ-mapQ+1;
  else if (mapZ<0)
   tMapZ=mapZ;

  if (tMapZ!=0 && tMapX!=0)
  {
   if (tMapZ>0)
    angleC=atan ((float(tMapX)*squareL*2+x)/-(float(tMapZ)*squareL*2+z))/rad-180-theta;
   else
    angleC=atan ((float(tMapX)*squareL*2+x)/-(float(tMapZ)*squareL*2+z))/rad-theta;
  }
  else if (tMapX==0)
  {
   if (tMapZ>0)
    angleC=-180-theta;
   else
    angleC=-theta;
  }
  else if (tMapZ==0)
  {
   if (tMapX>0)
    angleC=90-theta;
   else
    angleC=-90-theta;
  }
 }
 else
 {
  if ((mapZ-mapQ/2)!=0)
  {
   if ((mapZ-mapQ/2)>0)
    angleC=atan ((float(mapX-mapQ/2)*squareL*2+x)/-(float(mapZ-mapQ/2)*squareL*2+z))/rad-180-theta;
   else
    angleC=atan ((float(mapX-mapQ/2)*squareL*2+x)/-(float(mapZ-mapQ/2)*squareL*2+z))/rad-theta;
  }
  else if ((mapX-mapQ/2)>0)
   angleC=-90-180-theta;
  else
   angleC=90-180-theta;
 }

 glDisable (GL_DEPTH_TEST);// Выключаем тест глубины
 glLoadIdentity ();
 glRotatef (-angleX, 1.0f, 0.0f, 0.0f);
 glTranslatef (0.0f, -1.5f, -5.0f);
 glRotatef (-90, 1.0f, 0.0f, 0.0f);
 glRotatef (angleC, 0.0f, 0.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 glBegin (GL_TRIANGLES);
 myColor3f (0.4f, 0.4f, 0.7f);
 glVertex2f (-0.25f, -0.35f);// left
 myColor3f (0.4f, 0.4f, 0.7f);
 glVertex2f (0.25f, -0.35f);// right
 myColor3f (1.0f, 1.0f, 1.0f);
 glVertex2f (0.0f, 0.7f);// top
 glEnd ();
 glEnable (GL_DEPTH_TEST);
}

float fpsTweak ()
{
 if (!clockTweak)
  return 1.0f;
 else
  return clockD/15.0f;// 1 frame ms tweak
}

void fpsC ()
{
 // FPS
 paintC++;
 if (clock ()-timeS>=1000)
 {
  fps=paintC;
  paintC=0;
  timeS=clock ();
  if (fpsOn<10)
   fpsOn++;
 }

 clockTweak=false;
 if (clockL!=0)
  clockTweak=true;

 clockD=(float)clock ()-(float)clockL;
 clockL=clock ();
}

void statusBar ()
{
 if (fps>-1)
 {
  if (strlen (mb)!=0)// 1==5
  {
   glDisable (GL_DEPTH_TEST);// Выключаем тест глубины
   glBindTexture (GL_TEXTURE_2D, texture [0]);
   glLoadIdentity ();// Сброс просмотра
   glTranslatef (0.0f, 1.75f, -5.0f);
   glScalef (0.17f, 0.17f, 1.0f);
   glColor3f (1.0f, 1.0f, 1.0f);
//   glPrint ("test");// Печать текста GL на экран
   glPrint ("%s", mb);// Печать текста GL на экран
   glEnable (GL_DEPTH_TEST);// Включаем тест глубины
   return;
  }

  glDisable (GL_DEPTH_TEST);// Выключаем тест глубины

  glBindTexture (GL_TEXTURE_2D, texture [0]);

  glLoadIdentity ();// Сброс просмотра
  glTranslatef (0.01f, -0.01f, 0.0f);
  glTranslatef (0.0f, 1.75f, -5.0f);
  glScalef (0.17f, 0.17f, 0.0f);
  glColor3f (0.1f, 0.1f, 0.1f);
  glPrint ("FPS:%d X:%d Z:%d Очки:%d", fps, mapX-mapQ/2, (mapZ-mapQ/2), score);// Печать текста GL на экран

  glLoadIdentity ();// Сброс просмотра
  glTranslatef (0.0f, 1.75f, -5.0f);
  glScalef (0.17f, 0.17f, 0.0f);
  glColor3f (1.0f, 0.5f, 0.0f);
  glPrint ("FPS:%d X:%d Z:%d Очки:%d", fps, mapX-mapQ/2, (mapZ-mapQ/2), score);// Печать текста GL на экран

  glColor3f (1.0f, 1.0f, 1.0f);
  glPrint ("   :%d  :%d  :%d     :%d", fps, mapX-mapQ/2, (mapZ-mapQ/2), score);// Печать текста GL на экран

  glColor3f (1.0f, 1.0f, 0.0f);
  glPrint ("    %d   %d   %d     :%d", fps, mapX-mapQ/2, (mapZ-mapQ/2), score);// Печать текста GL на экран

  glEnable (GL_DEPTH_TEST);// Включаем тест глубины
 }
}

void hitEsc ()
{
 if (hitEscZ<=hitEscTill || fpsOn<4)
  return;

 hitEscZ-=0.05f*fpsTweak ();

 if (hitEscTill-hitEscZ>-4.5f && hitEscR>-90.0f)
  hitEscR-=1.0f*fpsTweak ();

 glDisable (GL_DEPTH_TEST);// Выключаем тест глубины

 glBindTexture (GL_TEXTURE_2D, texture [0]);

 myColor3f (0.0f, 0.0f, 0.0f);
 glLoadIdentity ();// Сброс просмотра
 // Позиционирование текста на экране
 glTranslatef (0.01f, -0.01f, 0.0f);
 glTranslatef (0.0f, -0.1f, hitEscZ);
 glRotatef (hitEscR, 1.0f, 0.0f, 0.0f);
 glScalef (0.57f, 0.57f, 1.0f);
 glPrint ("Esc - меню");// Печать текста GL на экран

 myColor3f (1.0f, 0.5f, 0.0f);
 glLoadIdentity ();// Сброс просмотра
 // Позиционирование текста на экране
 glTranslatef (0.0f, -0.1f, hitEscZ);
 glRotatef (hitEscR, 1.0f, 0.0f, 0.0f);
 glScalef (0.57f, 0.57f, 1.0f);
 glPrint ("Esc       ");// Печать текста GL на экран

 myColor3f (1.0f, 1.0f, 0.0f);
 glLoadIdentity ();// Сброс просмотра
 // Позиционирование текста на экране
 glTranslatef (0.0f, -0.1f, hitEscZ);
 glRotatef (hitEscR, 1.0f, 0.0f, 0.0f);
 glScalef (0.57f, 0.57f, 1.0f);
 glPrint ("      меню");// Печать текста GL на экран

 myColor3f (1.0f, 1.0f, 1.0f);
 glLoadIdentity ();// Сброс просмотра
 // Позиционирование текста на экране
 glTranslatef (0.0f, -0.1f, hitEscZ);
 glRotatef (hitEscR, 1.0f, 0.0f, 0.0f);
 glScalef (0.57f, 0.57f, 1.0f);
 glPrint ("    -     ");// Печать текста GL на экран

 glEnable (GL_DEPTH_TEST);// Включаем тест глубины
}

void menuOut ()
{
 int i, i2, c;

 // Blend the view
 glDisable (GL_DEPTH_TEST);// Выключаем тест глубины

 float blendX=1.825f*((float(cx)/float(cy))/(1600.0f/900.0f)), blendY=1.0f;
 glEnable (GL_BLEND);// Включаем смешивание
 glLoadIdentity ();  // Сброс просмотра
 glTranslatef (0.0f, 0.0f, -2.4f);
 glColor4f (1.0f, 1.0f, 1.0f, 1.0f);// Полная яркость, 100% альфа
 glBindTexture (GL_TEXTURE_2D, texture [6]);
 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-blendX, -blendY, 0.0f);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( blendX, -blendY, 0.0f);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( blendX,  blendY, 0.0f);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-blendX,  blendY, 0.0f);// Верх лево
 glEnd ();
 glDisable (GL_BLEND);// Выключаем смешивание

 glBindTexture (GL_TEXTURE_2D, texture [0]);

 glLoadIdentity ();// Сброс просмотра
 // Позиционирование текста на экране
 glTranslatef (0.36f, 0.65f, -3.5f);
 glRotatef (45, 0.0f, 1.0f, 0.0f);
 glRotatef (10, 0.0f, 0.0f, 1.0f);
 glScalef (1.0f, 1.0f, 1.0f);
 glColor3f (1.0f, 1.0f, 1.0f);
 glPrint ("Walker");// Печать текста GL на экран

 if (infoOn==0)
 {
  int menuA=45;
  char menu_txt [16];

  for (i=menuFrom; i<menuFrom+menuQ; i++)
  {
   glLoadIdentity ();// Сброс просмотра
   // Позиционирование текста на экране
   glTranslatef (0.0f, 0.0f-(i-menuFrom)*0.075f, -1.0f);

   if (!strcmp ("Звук", menuAr [i]))
    sprintf (menu_txt, "%s:%d%c", menuAr [i], soundVol/10, 17);
   else if (!strcmp ("Мелодия", menuAr [i]))
    sprintf (menu_txt, "%s:%d%c", menuAr [i], meloVol/10, 17);
   else if (!strcmp ("Время", menuAr [i]))
   {
    if (timeOfDay==1)
     sprintf (menu_txt, "%s:%s", menuAr [i], "утро");
    else if (timeOfDay==2)
     sprintf (menu_txt, "%s:%s", menuAr [i], "день");
    else if (timeOfDay==3)
     sprintf (menu_txt, "%s:%s", menuAr [i], "вечер");
    else if (timeOfDay==4)
     sprintf (menu_txt, "%s:%s", menuAr [i], "ночь");
    else if (timeOfDay==5)
     sprintf (menu_txt, "%s:%s", menuAr [i], "часы");
   }
   else if (!strcmp ("Походка", menuAr [i]))
    sprintf (menu_txt, "%s:%s", menuAr [i], walkIs ? "да" : "нет");
   else if (!strcmp ("Статус", menuAr [i]))
    sprintf (menu_txt, "%s:%s", menuAr [i], statusOn ? "да" : "нет");
   else if (!strcmp ("Видимость", menuAr [i]))
   {
    if (visMode==0)
     sprintf (menu_txt, "%s:%s%c", menuAr [i], "40", 17);
    else if (visMode==1)
     sprintf (menu_txt, "%s:%s%c", menuAr [i], "60", 17);
    else if (visMode==2)
     sprintf (menu_txt, "%s:%s%c", menuAr [i], "100", 17);
   }
   else if (!strcmp ("Сглаживать", menuAr [i]))
   {
    if (multisampleOn==0)
     sprintf (menu_txt, "%s:%s", menuAr [i], "нет");
    else if (multisampleOn==1)
     sprintf (menu_txt, "%s:%s", menuAr [i], "текст");
    else if (multisampleOn==2)
     sprintf (menu_txt, "%s:%s", menuAr [i], "всё");
   }
   else
    sprintf (menu_txt, "%s", menuAr [i]);
   if (menuSel==i)
   {
    menuR+=menuS*fpsTweak ();

    if (menuR<-menuA)
    {
     menuR=-menuA;
     menuS*=-1;
    }
    if (menuR>menuA)
    {
     menuR=menuA;
     menuS*=-1;
    }
    glRotatef (menuR, 0.0f, 1.0f, 0.0f);
   }

   glScalef (0.075f, 0.075f, 1.0f);
   if (menuSel==i)
    glColor3f (1.0f, 0.5f, 0.0f);
   else
    glColor3f (1.0f, 1.0f, 0.0f);
   if (subOn==1)
   {
    if (dmN==i)
     glColor3f (1.0f, 1.0f, 1.0f);
   }
   glPrint (menu_txt);// Печать текста GL на экран
  }

  if (menuFrom+menuQ<menuL)
  {
   glLoadIdentity ();
   glTranslatef (0.0f, -1.25f, -5.0f);
   glBindTexture (GL_TEXTURE_2D, texture [0]);
   glBegin (GL_TRIANGLES);
   glColor3f (1.0f, 0.5f, 0.0f);
   glVertex2f (0.0f, -0.1f);// top
   glColor3f (1.0f, 1.0f, 0.0f);
   glVertex2f (0.25f, 0.0f);// right
   glVertex2f (-0.25f, 0.0f);// left
   glEnd ();
  }
  if (menuFrom>0)
  {
   glLoadIdentity ();
   glTranslatef (0.0f, 0.28f, -5.0f);
   glBindTexture (GL_TEXTURE_2D, texture [0]);
   glBegin (GL_TRIANGLES);
   glColor3f (1.0f, 1.0f, 0.0f);
   glVertex2f (-0.25f, 0.0f);// left
   glVertex2f (0.25f, 0.0f);// right
   glColor3f (1.0f, 0.5f, 0.0f);
   glVertex2f (0.0f, 0.1f);// top
   glEnd ();
  }
 }
 else if (infoOn==1)
 {
  int keysQ=5;
  float r;

  char keysInfo [16] [32]={
"NumPad             ",
"         управление",
"     I             ",
"         статус    ",
"     W             ",
"         походка   ",
"     P             ",
"         указатель ",
"Ctrl+Q             ",
"         выход     "
  };

  glLoadIdentity ();// Сброс просмотра
  // Позиционирование текста на экране
  glTranslatef (0.0f, -0.0225f, -1.0f);
  glScalef (0.045f, 0.045f, 0.0f);

  for (i=0; i<keysQ; i++)
  {
   glColor3f (1.0f, 0.5f, 0.0f);
   glPrint (keysInfo [i*2]);// Печать текста GL на экран
   glColor3f (1.0f, 1.0f, 0.0f);
   glPrint (keysInfo [i*2+1]);// Печать текста GL на экран
   glColor3f (1.0f, 1.0f, 1.0f);
   glPrint ("       -           ");// Печать текста GL на экран

   if (i<keysQ-1)
    glTranslatef (0.0f, -1.0f, 0.0f);
  }
 }
 else if (infoOn==2)
 {
  int aboutQ=4;

  char aboutInfo [12] [64]={
"Программа пишется для освоения OpenGL.",
"Небольшая \"бродилка\" без лишних эффектов.",
"Управляется только с клавиатуры.",
"Должна работать на маломощных ПК."
  };

  glLoadIdentity ();// Сброс просмотра
  // Позиционирование текста на экране
  glTranslatef (0.0f, -0.035f, -1.0f);
  glScalef (0.035f, 0.035f, 0.0f);
  glColor3f (1.0f, 1.0f, 0.0f);

  for (i=0; i<aboutQ; i++)
  {
   glPrint (aboutInfo [i]);// Печать текста GL на экран

   if (i<aboutQ-1)
    glTranslatef (0.0f, -0.045f/0.035f, 0.0f);
  }
 }
 else if (infoOn==3)
 {
  int thanksQ=5, thanksQmx=5;
  infoPages=2;

  char thanksInfo [12] [64]={
"Помогли:",
"среда разработки wxDev C++",
"уроки по OpenGL от NeHe",
"GIMP, Paint.NET - с графикой",
"MuseScore, Audacity - звуком",
"http ://pmg.org.ru/nehe/index.html",
"https://royaltyfreeaudio.org      ",
"http ://boobooka.com/zvuki/       ",
"https://yandex.ru/images/         ",
"http ://junior3d.ru/texture.html  "
  };

  glLoadIdentity ();// Сброс просмотра
  // Позиционирование текста на экране
  glTranslatef (0.0f, -0.015, -1.0f);
  glScalef (0.045f, 0.045f, 0.0f);

  c=(infoPage-1)*thanksQmx;
  for (i=0; i<thanksQmx; i++)
  {
   if (c==0)
    glColor3f (1.0f, 0.5f, 0.0f);
   else
    glColor3f (1.0f, 1.0f, 0.0f);

   if (c>4)
   {
    glPrint (thanksInfo [c]);// Печать текста GL на экран    
    glColor3f (1.0f, 0.5f, 0.0f);
    char http [64];
    int httpL=strlen (thanksInfo [c]);
    memset (http, 0, 64);
    memset (http, 32, httpL);
    for (i2=0; i2<httpL; i2++)
     if (i2<8 || thanksInfo [c] [i2]=='/' || thanksInfo [c] [i2]=='.')
      http [i2]=thanksInfo [c] [i2];
    glPrint (http);// Печать текста GL на экран    
   }
   else
    glPrint (thanksInfo [c]);// Печать текста GL на экран
   c++;

   if (i<thanksQmx-1)
    glTranslatef (0.0f, -1.0f, 0.0f);
  }
 }
 else if (infoOn==4)
 {
  int storyQ=7, storyQmx=4;
  infoPages=2;

  char storyInfo [12] [96]={
"В одном из далёких миров, похожем на Землю,",
"среди бескрайних просторов затерялся небольшой",
"посёлок. В нём всего два дома: в одном живёте",
"вы, а другой ожидает новых поселенцев, которые",
"пока не спешат отправиться в этот всеми забытый",
"уголок Вселенной. Здешняя жизнь скучна и",
"однообразна... но этим она и хороша."
};

  glLoadIdentity ();// Сброс просмотра
  glTranslatef (0.0f, -0.035f, -1.0f);
  glScalef (0.035f, 0.035f, 0.0f);
  glColor3f (1.0f, 1.0f, 0.0f);

  c=(infoPage-1)*storyQmx;
  for (i=0; i<storyQmx; i++)
  {
   // Позиционирование текста на экране
   glPrint (storyInfo [c]);// Печать текста GL на экран

   if (i<storyQmx-1)
    glTranslatef (0.0f, -0.045f/0.035f, 0.0f);
   c++;
  }
 }

 glLoadIdentity ();// Сброс просмотра
 // Позиционирование текста на экране
 glTranslatef (0.0f, -0.038f, -0.1f);
 glScalef (0.004f, 0.004f, 1.0f);
 glColor3f (0.5f, 0.5f, 0.5f);
 glPrint ("Маркичев Д. 2017");// Печать текста GL на экран

 glEnable (GL_DEPTH_TEST);// Включаем тест глубины
}

void loading ()
{
 glPushMatrix ();
 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glLoadIdentity ();// Сброс просмотра
 glTranslatef (0.01f, -0.01f, 0.0f);
 glTranslatef (0.0f, -0.1f, -5.0f);
 glScalef (0.57f, 0.57f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 // Позиционирование текста на экране
 glColor3f (0.1f, 0.1f, 0.1f);
 glPrint ("Загрузка...");// Печать текста GL на экран

 glLoadIdentity ();// Сброс просмотра
 glTranslatef (0.0f, -0.1f, -5.0f);
 glScalef (0.57f, 0.57f, 1.0f);
 // Позиционирование текста на экране
 glColor3f (1.0f, 1.0f, 0.0f);
 glPrint ("Загрузка...");// Печать текста GL на экран

 glPopMatrix ();
 SwapBuffers (hDC);
// Sleep (1000);
}

void loadMap ()
{
 int i, xi, zi, tx, tz, treeC=0, treeBC=0, bushC=0;
 memset (mapExt, 0, mapQ*mapQ*sizeof (unsigned char));
 memset (mapH, 0, (mapQ+1)*(mapQ+1)*sizeof (unsigned char));

 // initialize random seed:
 srand (100);

 // grass
 for (zi=0; zi<mapQ+1; zi++)
  for (xi=0; xi<mapQ+1; xi++)
  {
   if ((zi>villageZ+20 || zi<villageZ-20 || xi>villageX+20 || xi<villageX-20)
   && !(zi>villageZ-3 && zi<=villageZ)
   && zi>1 && zi<mapQ-1 && xi>1 && xi<mapQ-1)
    mapH [zi] [xi]=rand ()%10;
  }

 for (zi=0; zi<mapQ; zi++)
 {
  for (xi=0; xi<mapQ; xi++)
   map [zi] [xi]=32;// ground
 }

 treeC=0;
 for (i=0; i<100; i++)
 {
  tx=rand ()%(mapQ-2)+1;
  tz=rand ()%(mapQ-2)+1;
  if (map [tz] [tx]==32 && map [tz] [tx+1]==32 && map [tz] [tx-1]==32
   && map [tz-1] [tx]==32 && map [tz-1] [tx+1]==32 && map [tz-1] [tx-1]==32
   && map [tz+1] [tx]==32 && map [tz+1] [tx+1]==32 && map [tz+1] [tx-1]==32)
  {
   if (rand ()%2==1)
    map [tz] [tx]=195;// tree
   else
    map [tz] [tx]=196;// treeB
   mapExt [tz] [tx]=treeC;
   treeC++;
   if (treeC==treeQ)
    treeC=0;
  }
 }

 for (i=0; i<treeQ; i++)
 {
  treeObj [i].angle=rand ()%7;
  treeObj [i].angleX=(rand ()%2==1 ? -1.0f : 1.0f)*float (rand ()%100)/100.0f;
  treeObj [i].angleZ=(rand ()%2==1 ? -1.0f : 1.0f)*float (rand ()%100)/100.0f;
  treeObj [i].cronaR=1.35f+float (rand ()%30)/100.0f;
  treeObj [i].cronaH=3.45f+float (rand ()%25)/100.0f;
  treeObj [i].cronaColorR=0.35f+float (rand ()%15)/100.0f;
  treeObj [i].cronaColorG=0.55f+float (rand ()%25)/100.0f;
  treeObj [i].cronaColorB=0.0f;
  treeObj [i].colorR=0.5f+float (rand ()%25)/100.0f;
  treeObj [i].colorG=0.45f+float (rand ()%15)/100.0f;
  treeObj [i].colorB=0.5f+float (rand ()%5)/100.0f;
 }

 for (i=0; i<treeBQ; i++)
 {
  treeObjB [i].angle=rand ()%7;
  treeObjB [i].angleX=(rand ()%2==1 ? -1.0f : 1.0f)*float (rand ()%100)/100.0f;
  treeObjB [i].angleZ=(rand ()%2==1 ? -1.0f : 1.0f)*float (rand ()%100)/100.0f;
  treeObjB [i].cronaColorR=0.25f+float (rand ()%25)/100.0f;
  treeObjB [i].cronaColorG=0.55f+float (rand ()%25)/100.0f;
  treeObjB [i].cronaColorB=0.0f;
  treeObjB [i].colorR=0.5f+float (rand ()%25)/100.0f;
  treeObjB [i].colorG=0.45f+float (rand ()%15)/100.0f;
  treeObjB [i].colorB=0.5f+float (rand ()%5)/100.0f;
 }

 map [villageZ-12] [villageX+12]=38;// bush

 for (i=0; i<750; i++)
 {
  tx=rand ()%(mapQ-2)+1;
  tz=rand ()%(mapQ-2)+1;
  if (map [tz] [tx]==32)
  {
   map [tz] [tx]=38;// bush
   mapExt [tz] [tx]=bushC;
   bushC++;
   if (bushC==bushQ)
    bushC=0;
  }
 }

 for (i=0; i<bushQ; i++)
 {
  bushObj [i].type=rand ()%2;
  bushObj [i].colorR=0.15f+float (rand ()%35)/100.0f;
  bushObj [i].colorG=0.45f+float (rand ()%25)/100.0f;
  bushObj [i].colorB=0.0f+float (rand ()%25)/100.0f;
 }

 for (zi=villageZ-20; zi<villageZ+21; zi++)
 {
  for (xi=villageX-20; xi<villageX+21; xi++)
   map [zi] [xi]=32;// land
 }

 map [villageZ-10] [villageX-10]=38;// bush
 mapExt [villageZ-10] [villageX-10]=bushC; bushC++; if (bushC==bushQ) bushC=0;
 map [villageZ-10+2] [villageX-10]=38;
 mapExt [villageZ-10+2] [villageX-10]=bushC; bushC++; if (bushC==bushQ) bushC=0;
 map [villageZ-10+1] [villageX-10-1]=38;
 mapExt [villageZ-10+1] [villageX-10-1]=bushC; bushC++; if (bushC==bushQ) bushC=0;
 map [villageZ-10+1] [villageX-10+1]=38;
 mapExt [villageZ-10+1] [villageX-10+1]=bushC; bushC++; if (bushC==bushQ) bushC=0;

 // living fence
 for (xi=villageX-19; xi<villageX+20; xi+=3)
 {
  map [villageZ-19] [xi]=38;// bush
  mapExt [villageZ-19] [xi]=bushC;
  bushC++;
  if (bushC==bushQ)
   bushC=0;
 }

 for (xi=villageX-19; xi<villageX+20; xi+=3)
 {
  map [villageZ+19] [xi]=38;
  mapExt [villageZ+19] [xi]=bushC;
  bushC++;
  if (bushC==bushQ)
   bushC=0;
 }

 for (zi=villageZ+19; zi>villageZ-20; zi-=3)
 {
  map [zi] [villageX-19]=38;
  mapExt [zi] [villageX-19]=bushC;
  bushC++;
  if (bushC==bushQ)
   bushC=0;
 }

 for (zi=villageZ-19; zi<villageZ+20; zi+=3)
 {
  map [zi] [villageX+19]=38;
  mapExt [zi] [villageX+19]=bushC;
  bushC++;
  if (bushC==bushQ)
   bushC=0;
 }

 // large road
 for (xi=0; xi<mapQ; xi++)// && villageX+48
 {
  map [villageZ-1] [xi]=34;
  map [villageZ-2] [xi]=34;
  mapExt [villageZ-1] [xi]=1;
  mapExt [villageZ-2] [xi]=2;
 }
 mapExt [villageZ-1] [villageX-9]=3;
 mapExt [villageZ-1] [villageX-7]=3;

 // crystals
 map [villageZ+5] [villageX-1]=175;
 map [villageZ+5] [villageX]=176;
 map [villageZ+5] [villageX+1]=175;
 map [villageZ-1+5] [villageX]=175;
 map [villageZ+1+5] [villageX]=175;

 // corners
 map [0] [0]=165;
 map [mapQ-1] [0]=165;
 map [0] [mapQ-1]=165;
 map [mapQ-1] [mapQ-1]=165;

 for (i=0; i<4; i++)// columns
 {
  map [villageZ+5+i*2] [villageX-9]=100;
  map [villageZ+5+i*2] [villageX-7]=100;
 }

 // cylindric columns
 map [villageZ-3] [villageX+16]=120;
 map [villageZ] [villageX+16]=120;

 for (zi=villageZ; zi<villageZ+12; zi++)
 {
  map [zi] [villageX-8]=34;// small road
  mapExt [zi] [villageX-8]=21;
 }
 map [villageZ-1] [villageX-8]=34;// road hub
 mapExt [villageZ-1] [villageX-8]=25;

 for (zi=villageZ+12; zi<villageZ+15; zi++)
 {
  map [zi] [villageX-8]=34;// sand road
  mapExt [zi] [villageX-8]=51;
 }
 for (xi=villageX-7; xi<villageX+7; xi++)
 {
  map [villageZ+14] [xi]=34;// sand road
  mapExt [villageZ+14] [xi]=52;
 }
 mapExt [villageZ+14] [villageX-8]=55;
 mapExt [villageZ+12] [villageX-8]=56;

 for (xi=villageX+7; xi<villageX+14; xi++)// house land
 {
  map [villageZ+12] [xi]=56;
  map [villageZ+13] [xi]=56;
  map [villageZ+14] [xi]=56;
  map [villageZ+15] [xi]=56;
  map [villageZ+16] [xi]=56;
 }
 map [villageZ+14] [villageX+10]=215;// house
 mapExt [villageZ+14] [villageX+10]=1;

 map [villageZ+16] [villageX+4]=185;// bench
 map [villageZ+16] [villageX+3]=57;
 map [villageZ+16] [villageX+5]=57;
 mapExt [villageZ+16] [villageX+3]=185;
 mapExt [villageZ+16] [villageX+5]=185;

 for (xi=villageX-13; xi<villageX-6; xi++)// house land
 {
  map [villageZ-16] [xi]=56;
  map [villageZ-15] [xi]=56;
  map [villageZ-14] [xi]=56;
  map [villageZ-13] [xi]=56;
  map [villageZ-12] [xi]=56;
 }
 map [villageZ-14] [villageX-10]=215;// house
 mapExt [villageZ-14] [villageX-10]=2;

 map [villageZ-16] [villageX-4]=185;// bench
 map [villageZ-16] [villageX-3]=57;
 map [villageZ-16] [villageX-5]=57;
 mapExt [villageZ-16] [villageX-3]=185;
 mapExt [villageZ-16] [villageX-5]=185;

 crateObj [0].q=2;
 crateObj [0].angle1=-15.0f;
 crateObj [0].angle2=25.0f;
 map [villageZ-15] [villageX-15]=237;// small crates
 mapExt [villageZ-15] [villageX-15]=0;

 crateObj [1].q=1;
 crateObj [1].angle1=0.0f;
 crateObj [1].angle2=0.0f;
 map [villageZ-13] [villageX-15]=237;// small crate
 mapExt [villageZ-13] [villageX-15]=1;

 // well
 map [villageZ-13] [villageX-2]=225;
 map [villageZ-13] [villageX-1]=57;
 map [villageZ-12] [villageX-2]=57;
 map [villageZ-12] [villageX-1]=57;

 barrelObj [0].angle=215.0f;
 barrelObj [0].x=0.0f;
 barrelObj [0].z=0.0f;
 map [villageZ-15] [villageX+1]=115;// barrel
 mapExt [villageZ-15] [villageX+1]=0;

 barrelObj [1].angle=10.0f;
 barrelObj [1].x=0.0f;
 barrelObj [1].z=0.0f;
 map [villageZ+15] [villageX+15]=115;// barrel
 mapExt [villageZ+15] [villageX+15]=1;

 barrelObj [2].angle=100.0f;
 barrelObj [2].x=0.15f;
 barrelObj [2].z=0.15f;
 map [villageZ+14] [villageX+15]=115;// barrel
 mapExt [villageZ+14] [villageX+15]=2;

 for (zi=villageZ-10; zi<villageZ-10+3; zi++)
  for (xi=villageX+3; xi<villageX+3+3; xi++)// cellar land
   map [zi] [xi]=57;
 map [villageZ-9] [villageX+4]=235;// cellar

 for (zi=villageZ-10; zi<villageZ-10+3; zi++)
  for (xi=villageX+12; xi<villageX+12+3; xi++)// crates land
   map [zi] [xi]=57;
 map [villageZ-9] [villageX+12+1]=236;// crates

 // hill
 map [villageZ-14] [villageX+8]=55;
 map [villageZ-14] [villageX+9]=55;
 map [villageZ-14] [villageX+10]=55;
 map [villageZ-13] [villageX+8]=55;
 map [villageZ-13] [villageX+9]=65;
 map [villageZ-13] [villageX+10]=55;
 map [villageZ-12] [villageX+8]=55;
 map [villageZ-12] [villageX+9]=55;
 map [villageZ-12] [villageX+10]=55;

 // hill
 map [villageZ+1] [villageX-12]=55;
 map [villageZ+1] [villageX-11]=55;
 map [villageZ+1] [villageX-10]=55;
 map [villageZ+2] [villageX-12]=55;
 map [villageZ+2] [villageX-11]=67;
 map [villageZ+2] [villageX-10]=55;
 map [villageZ+3] [villageX-12]=55;
 map [villageZ+3] [villageX-11]=55;
 map [villageZ+3] [villageX-10]=55;

 for (zi=villageZ+10; zi<villageZ+17; zi++)
 {
  for (xi=villageX-16; xi<villageX-9; xi++)
   map [zi] [xi]=55;// hill land
 }
 map [villageZ+13] [villageX-13]=63;// hill

 hillObj [0].hillZq=12;
 hillObj [0].hillXq=12;
 hillObj [0].hillCells=3;
 hillObj [0].hillHk=50.0f;
 hillObj [0].hillBottom=-0.035f;
 hillObj [1].hillZq=28;
 hillObj [1].hillXq=28;
 hillObj [1].hillCells=7;
 hillObj [1].hillHk=35.0f;
 hillObj [1].hillBottom=-0.035f;

 char hillAr [12+1] [12+1]={
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   1,   5,   4,   5,   4,   3,   5,   4,   5,   2,   1,   0,
    0,   4,   5,  10,  15,  10,   5,   5,   5,   5,   5,   4,   0,
    0,   5,   5,  15,  25,  20,  15,  10,  10,  10,  10,   3,   0,
    0,  10,  10,  25,  30,  35,  40,  30,  25,  20,  10,   5,   0,
    0,   5,  15,  30,  35,  55,  55,  50,  45,  35,  15,   5,   0,
    0,   5,  20,  35,  40,  50,  50,  30,  25,  20,  10,   3,   0,
    0,  10,  10,  25,  30,  35,  35,  20,  15,  15,   5,   5,   0,
    0,  15,  10,  15,  15,  25,  15,  15,  15,  15,  15,   5,   0,
    0,  10,   5,  10,  10,  20,  10,  10,  10,  10,  10,  10,   0,
    0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   3,   0,
    0,   1,   2,   3,   5,   5,   5,   4,   3,   2,   1,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
 };
 // hill obj
 for (zi=0; zi<hillObj [0].hillZq+1; zi++)
  for (xi=0; xi<hillObj [0].hillXq+1; xi++)
   hillObj [0].hillAr [zi] [xi]=hillAr [zi] [xi];

 // hill terrains
 for (zi=0; zi<12+1; zi++)// large hill
  for (xi=0; xi<12+1; xi++)
   mapH [villageZ-21+zi] [villageX-35+xi]=hillAr [zi] [xi];

 for (zi=0; zi<12+1; zi++)// large hill
  for (xi=0; xi<12+1; xi++)
   mapH [villageZ+4+zi] [villageX-39+xi]=hillAr [zi] [xi]*1.5;

 for (zi=0; zi<12+1; zi++)// long hill
  for (xi=0; xi<12+1; xi++)
  {
   mapH [villageZ-35+zi] [villageX+15+xi*2]=hillAr [zi] [xi];
   mapH [villageZ-35+zi] [villageX+15+xi*2+1]=hillAr [zi] [xi];
   if (zi>2 && zi<10 && xi>2 && xi<7)
    mapH [villageZ-35+zi] [villageX+15+xi*2+1]+=rand ()%10;
   else if (zi>2 && zi<10 && xi>7 && xi<10)
    mapH [villageZ-35+zi] [villageX+15+xi*2+1]-=rand ()%5;
  }

 // hill obj
 int r, r0;
 r0=sqrt (pow ((float)(hillObj [1].hillZq+1)/2.0f, 2)+pow ((float)(hillObj [1].hillXq+1)/2.0f, 2));
 for (zi=0; zi<hillObj [1].hillZq+1; zi++)
 {
  for (xi=0; xi<hillObj [1].hillXq+1; xi++)
  {
   r=sqrt (pow ((float)(hillObj [1].hillZq+1)/2.0f-(float)zi, 2)+pow ((float)(hillObj [1].hillXq+1)/2.0f-(float)xi, 2));
   if (xi==0 || xi==hillObj [1].hillXq || zi==0 || zi==hillObj [1].hillZq)
    hillObj [1].hillAr [zi] [xi]=0;
   else if (r>hillObj [1].hillZq/2-3)
    hillObj [1].hillAr [zi] [xi]=rand ()%(r0-r)-1;
   else
    hillObj [1].hillAr [zi] [xi]=(r0-r)*4-10+rand ()%5;
  }
 }

 for (xi=villageX-7; xi<villageX+7; xi++)
 {
  map [villageZ-5] [xi]=150;// wall
  mapExt [villageZ-5] [xi]=0;
 }
 map [villageZ-5] [villageX-8]=150;// wallL
 mapExt [villageZ-5] [villageX-8]=1;
 map [villageZ-5] [villageX+7]=150;// wallR
 mapExt [villageZ-5] [villageX+7]=2;
 mapExt [villageZ-5] [villageX-5]=5;// warning

 crateObj [2].q=1;
 crateObj [2].angle1=10.0f;
 crateObj [2].angle2=0.0f;
 map [villageZ-6] [villageX-5]=237;// small crate
 mapExt [villageZ-6] [villageX-5]=2;

 // fence
 for (zi=villageZ-14; zi<villageZ-4; zi++)
 {
  map [zi] [villageX+16]=160;
  mapExt [zi] [villageX+16]=0;
 }
 map [villageZ-5] [villageX+16]=160;
 mapExt [villageZ-5] [villageX+16]=1;
 map [villageZ-14] [villageX+16]=160;
 mapExt [villageZ-14] [villageX+16]=2;

 map [villageZ-5] [villageX-11]=195;// tree
 mapExt [villageZ-5] [villageX-11]=treeC; treeC++; if (treeC==treeQ) treeC=0;
 map [villageZ-5] [villageX-14]=195;// tree
 mapExt [villageZ-5] [villageX-14]=treeC; treeC++; if (treeC==treeQ) treeC=0;
 map [villageZ-16] [villageX+16]=195;// tree
 mapExt [villageZ-16] [villageX+16]=treeC; treeC++; if (treeC==treeQ) treeC=0;

 map [villageZ-21+5] [villageX-35+5]=196;// treeB
 mapExt [villageZ-21+5] [villageX-35+5]=treeBC; treeBC++; if (treeBC==treeBQ) treeBC=0;

 for (xi=villageX-6; xi<villageX+18; xi+=4)
 {
  map [villageZ+1] [xi]=195;// tree
  mapExt [villageZ+1] [xi]=treeC;
  treeC++;
  if (treeC==treeQ)
   treeC=0;
 }

 // initialize random seed:
 srand (time (NULL));
}

bool isMapped (int iZ=0, int iX=0)
{
 if (iX>=0 && iX<mapQ && iZ>=0 && iZ<mapQ)
  return true;
 else
  return false;
}

bool isEmpty (int iZ=0, int iX=0)
{
 if (map [iZ] [iX]==150)
 {
  if (hillRh>=1.0f)
   return true;
  else
   return false;
 }
 else if (map [iZ] [iX]==237)
 {
  if (crateObj [mapExt [iZ] [iX]].q==1)
   return true;
  else
   return false;
 }
 else if (map [iZ] [iX]==185 || (map [iZ] [iX]==57 && mapExt [iZ] [iX]==185))
  return true;
 else if (map [iZ] [iX]==0 || map [iZ] [iX]==56 || map [iZ] [iX]==57 || map [iZ] [iX]>=100)
  return false;
 else
  return true;
}

bool isStone (int iZ, int iX)
{
 if (map [iZ] [iX]==34 && mapExt [iZ] [iX]<50)
  return true;

 return false;
}

int leafsTime=0, leafsLastX=-1, leafsLastZ=-1;
void steps ()
{
 int psVol=100;
 if (hillRh0!=0.0f)
  psVol=55;

 if (keyUp)
 {
  walkUp=true;
  walkbiasangle+=10*fpsTweak ();
  if (walkbiasangle>360.0f)
   walkbiasangle-=360.0f;
  // Имитация походки человека
  walkbias=(float)sin(walkbiasangle*rad)*walkbiasK;
  if (walkbias<wbLast)
   wbD=-1;
  else
   wbD=1;

  if (wbLD==-1 && wbD==1)
  {
   if ((!isMapped (mapZ, mapX) || (!isStone (mapZ, mapX) && map [mapZ] [mapX]!=150))// && map [mapZ] [mapX]!=151 && map [mapZ] [mapX]!=152
    && !((mapZ==villageZ-2 || mapZ==villageZ-1) && (mapX<0 || mapX>mapQ-1)))
   {
    if (walk12==1)
    {
     walk12=2;
     playSound ("step_soft_r", psVol);
    }
    else
    {
     walk12=1;
     playSound ("step_soft_l", psVol);
    }
   }
   else// road
   {
    if (walk12==1)
    {
     walk12=2;
     playSound ("step_right", psVol);
    }
    else
    {
     walk12=1;
     playSound ("step_left", psVol);
    }
   }
  }
  wbLast=walkbias;
  wbLD=wbD;
 }
 else if (keyDown)
 {
  walkDown=true;
  walkbiasangle-=10*fpsTweak ();
  if (walkbiasangle<0.0f)
   walkbiasangle+=360.0f;

  // Имитация походки человека
  walkbias=(float)sin(walkbiasangle*rad)*walkbiasK;

  if (walkbias<wbLast)
   wbD=-1;
  else
   wbD=1;

  if (wbLD==-1 && wbD==1)
  {
   if ((!isMapped (mapZ, mapX) || (!isStone (mapZ, mapX) && map [mapZ] [mapX]!=150))// && map [mapZ] [mapX]!=151 && map [mapZ] [mapX]!=152
    && !((mapZ==villageZ-2 || mapZ==villageZ-1) && (mapX<0 || mapX>mapQ-1)))
   {
    if (walk12==1)
    {
     walk12=2;
     playSound ("back_soft_r", psVol);
    }
    else
    {
     walk12=1;
     playSound ("back_soft_l", psVol);
    }
   }
   else// road
   {
    if (walk12==1)
    {
     walk12=2;
     playSound ("back_r", psVol);
    }
    else
    {
     walk12=1;
     playSound ("back_l", psVol);
    }
   }
  }
  wbLast=walkbias;
  wbLD=wbD;
 }
 else
 {
  if (walkUp || walkDown)
  {
   walkUp=false;
   walkDown=false;

   if ((!isMapped (mapZ, mapX) || !isStone (mapZ, mapX)) && !((mapZ==villageZ-2 || mapZ==villageZ-1) && (mapX<0 || mapX>mapQ-1)))
    playSound ("still_soft", psVol);
   else
    playSound ("still", psVol);
  }
  walkbiasangle=90;
  // Имитация походки человека
  walkbias=(float)sin(walkbiasangle*rad)*walkbiasK;
  wbLD=1;
  walk12=1;
 }

 if (keyUp || keyDown)
 {
  if (isMapped (mapZ, mapX))
  {
   if (map [mapZ] [mapX]==38 && (clock ()-leafsTime>2500 || leafsLastX!=mapX || leafsLastZ!=mapZ))
   {
    char t [16];
    sprintf (t, "leafs%d", (rand ()%3+1));
    playSound (t);
    leafsTime=clock ();
    leafsLastX=mapX;
    leafsLastZ=mapZ;
   }
  }
 }
}

void go ()
{
 float tX=x, tZ=z;
 int tMapX=mapX, tMapZ=mapZ;
 bool noX=false, noZ=false;
 speedK=1.0f;

 if (borderUp)
  speedK/=1.5;
 else if ((mapZ==villageZ-2 || mapZ==villageZ-1) && (mapX<0 || mapX>mapQ-1))// road
  speedK*=1.5f;
 else if (!isMapped (mapZ, mapX))
  speedK/=1.0f;
 else if (map [mapZ] [mapX]==34)// road
 {
  if (!isStone (mapZ, mapX))
   speedK*=1.25f;
  else
   speedK*=1.5f;
 }
 else if (map [mapZ] [mapX]==38)// bush
  speedK/=1.25f;
 else if (hillRh0!=0.0f)// hill
 {
  if (hillUpDown!=0.0f)
   speedK*=hillUpDown;
  else
   speedK/=1.5f;
 }

 speedK*=1.5f;

 if (keyUp)
 {
  step=0.032f*fpsTweak ()*speedK;
  walkbiasK=walkbiasK0*speedK/1.5f;
 }
 else if (keyDown)
 {
  step=-0.024*fpsTweak ()*speedK;
  walkbiasK=walkbiasK0*speedK/2.0f;
 }
 else
 {
  step=0.0f;
  walkbiasK=walkbiasK0;
 }

 if (theta>=0.0f && theta<=90.0f)// top left
 {
  tX-=cos ((90-theta)*rad)*step;
  tZ+=sin ((90-theta)*rad)*step;
 }
 else if (theta<=0.0f && theta>=-90.0f)// top right
 {
  tX+=cos ((90+theta)*rad)*step;
  tZ+=sin ((90+theta)*rad)*step;
 }
 else if (theta>=90.0f && theta<=180.0f)// bottom left
 {
  tX-=cos ((theta-90)*rad)*step;
  tZ-=sin ((theta-90)*rad)*step;
 }
 else if (theta<=-90.0f && theta>=-180.0f)// bottom right
 {
  tX+=cos (-(90+theta)*rad)*step;
  tZ-=sin (-(90+theta)*rad)*step;
 }

 if (tX>squareL)
 {
  tX-=squareL*2;
  if (mapX<mapQ+squareS/2)
  {
   tMapX++;

   if (isMapped (mapZ, tMapX))
   {
    if (!isEmpty (mapZ, tMapX))
     noX=true;
   }
  }
 }
 else if (tX<-squareL)
 {
  tX+=squareL*2;
  if (mapX>-squareS/2-1)
  {
   tMapX--;

   if (isMapped (mapZ, tMapX))
   {
    if (!isEmpty (mapZ, tMapX))
     noX=true;
   }
  }
 }
 if (tZ>squareL)
 {
  tZ-=squareL*2;
  if (mapZ<mapQ+squareS/2)
  {
   tMapZ++;

   if (isMapped (tMapZ, mapX))
   {
    if (!isEmpty (tMapZ, mapX))
     noZ=true;
   }
  }
 }
 else if (tZ<-squareL)
 {
  tZ+=squareL*2;
  if (mapZ>-squareS/2-1)
  {
   tMapZ--;

   if (isMapped (tMapZ, mapX))
   {
    if (!isEmpty (tMapZ, mapX))
     noZ=true;
   }
  }
 }

 if (tMapX!=mapX && tMapZ!=mapZ && !noX && !noZ)
 {
  if (isMapped (tMapZ, tMapX))
  {
   if (!isEmpty (tMapZ, tMapX))
   {
    noX=true;
    noZ=true;
   }
  }
 }

 if (tMapX!=mapX || tMapZ!=mapZ)
 {
  if (!noX && !noZ)
  {
   score+=1;

   if (isMapped (tMapZ, tMapX))
   {
    if (map [tMapZ] [tMapX]==38)
     score-=25;
    else if (map [tMapZ] [tMapX]==34)
     score-=1;
    if (map [tMapZ] [tMapX]==36)
     score-=1;
   }
   else
    score-=1;
  }
  else
   score-=1;
 }

 if (!( (noX && (z==tZ || (abs (x*1000)==0 && abs (tX*1000)==0)) )
     || (noZ && (x==tX || (abs (x*1000)==0 && abs (tX*1000)==0))) ) )// abs, *1000?
  steps ();

 if (!noX)
 {
  x=tX;
  mapX=tMapX;
 }
 if (!noZ)
 {
  z=tZ;
  mapZ=tMapZ;
 }
}

void turn ()
{
 if (keyLeft && keyRight)
  return;

 float turnAngle=1.0f;

 if (keyRight)
 {
  if (keyRightC<150.0f)
   keyRightC+=fpsTweak ();

  theta-=(turnAngle+keyRightC/100.0f)*fpsTweak ();
  if (theta<-180.0f)
   theta+=360.0f;
 }

 if (keyLeft)
 {
  if (keyLeftC<150.0f)
   keyLeftC+=fpsTweak ();

  theta+=(turnAngle+keyLeftC/100.0f)*fpsTweak ();
  if (theta>180.0f)
   theta-=360.0f;
 }
}

void look ()
{
 if (keyLookUp && keyLookDown)
  return;

 float lookAngle=1.0f;

 if (keyLookOff)
 {
  if (angleX>0.0f)
  {
   angleX-=lookAngle*fpsTweak ();
   if (angleX<0.0f)
    angleX=0.0f;
  }
  else if (angleX<0.0f)
  {
   angleX+=lookAngle*fpsTweak ();
   if (angleX>0.0f)
    angleX=0.0f;
  }
 }
 else if (keyLookUp)
 {
  angleX+=lookAngle*fpsTweak ();
  if (angleX>angleXlimit)
   angleX=angleXlimit;
 }
 else if (keyLookDown)
 {
  angleX-=lookAngle*fpsTweak ();
  if (angleX<-angleXlimit)
   angleX=-angleXlimit;
 }
}

void saveConf()
{
 FILE *file;
 int i;
 char txt1 [1024], txt2 [1024], conf [1024];

 sprintf (txt1, "Sound:%d\r\nMelody:%d\r\nTime:%d\r\nWalk:%d\r\nStatus:%d\r\nPointer:%d\r\nMultisample:%d\r\nVisibility:%d\r\nResolution:%d\r\n",
                soundVol, meloVol, timeOfDay, walkIs ? 1 : 0, statusOn ? 1 : 0, pointerOn ? 1 : 0, multisampleOn, visMode, dmN);
 sprintf (txt2, "AngleY:%f\r\nAngleX:%f\r\nMapX:%d\r\nMapZ:%d\r\nX:%f\r\nZ:%f\r\nHeight:%f\r\n",
                theta, angleX, mapX, mapZ, x, z, hillRh);
 sprintf (conf, "%s\r\n%s", txt1, txt2);

 char path [_MAX_PATH];
 sprintf (path, "%s%s", AppDir, "data\\config.txt");

 file=fopen (path, "wb");
 if (file!=NULL)
 {
  fwrite (conf, 1, strlen (conf), file);
  fclose (file);
 }
}

void loadConf ()
{
 FILE *file;
 int i, i2, n=0, n2, fS, confMx=1024, parMx=32, parL;
 float tTheta=theta, tAngleX=angleX, tX=x, tZ=z;
 int tMapX=mapX, tMapZ=mapZ;
 char conf [1024], par [32], par0 [32], par1 [32];
 memset (conf, 0, confMx);

 char path [_MAX_PATH];
 sprintf (path, "%s%s", AppDir, "data\\config.txt");

 file=fopen (path, "rb");
 if (file!=NULL)
 {
  fseek (file, 0, SEEK_END);// seek to end of file
  fS=ftell (file);// get current file pointer
  fseek (file, 0, SEEK_SET);// seek to begin of file
  if (fS<confMx-2)
   fread (conf, 1, fS, file);
  else
   fread (conf, 1, confMx-2, file);
  fclose (file);
 }
 strcat (conf, "\n");

 for (i2=0; i2<strlen (conf); i2++)
 {
  if (conf [i2]!='\n' && conf [i2]!='\r')
   break;
 }
 n=i2;

 for (i=n; i<strlen (conf); i++)
 {
  if (conf [i]=='\n' || conf [i]=='\r')
  {
   memset (par, 0, parMx);
   for (i2=n; i2<i; i2++)
    par [i2-n]=conf [i2];

   for (i2=i+1; i2<strlen (conf); i2++)
   {
    if (conf [i2]!='\n' && conf [i2]!='\r')
     break;
   }
   n=i2;
   i=i2;

   parL=strlen (par);
   if (parL>parMx)
    parL=parMx;

   memset (par0, 0, parMx);
   memset (par1, 0, parMx);
   n2=0;
   for (i2=0; i2<parL; i2++)
   {
    if (par [i2]==':')
    {
     n2=i2;
     break;
    }
   }
   if (n2)
   {
    memcpy (par0, par, i2);
    for (i2=n2+1; i2<parL; i2++)
     par1 [i2-n2-1]=par [i2];
   }
   if (!strcmp (par0, "Sound"))
   {
    soundVol=atoi (par1);
    if (soundVol>1000)
     soundVol=1000;
    if (soundVol<0)
     soundVol=0;
    if (soundVol)
     soundOn=true;
    else
     soundOn=false;
   }
   else if (!strcmp (par0, "Melody"))
   {
    meloVol=atoi (par1);
    if (meloVol>1000)
     meloVol=1000;
    if (meloVol<0)
     meloVol=0;
    if (meloVol)
     meloIs=true;
    else
     meloIs=false;
   }
   else if (!strcmp (par0, "Time"))
   {
    timeOfDay=atoi (par1);
    if (timeOfDay>5)
     timeOfDay=5;
    if (timeOfDay<1)
     timeOfDay=1;
   }
   else if (!strcmp (par0, "Walk"))
   {
    if (!strcmp (par1, "1"))
     walkIs=true;
    else
     walkIs=false;
   }
   else if (!strcmp (par0, "Status"))
   {
    if (!strcmp (par1, "1"))
     statusOn=true;
    else
     statusOn=false;
   }
   else if (!strcmp (par0, "Pointer"))
   {
    if (!strcmp (par1, "1"))
     pointerOn=true;
    else
     pointerOn=false;
   }
   else if (!strcmp (par0, "Multisample"))
   {
    multisampleOn=atoi (par1);
    if (multisampleOn<0)
     multisampleOn=0;
    else if (multisampleOn>2)
     multisampleOn=2;
   }
   else if (!strcmp (par0, "Visibility"))
   {
    visMode=atoi (par1);
    if (visMode<0)
     visMode=0;
    else if (visMode>2)
     visMode=2;
   }
   else if (!strcmp (par0, "Resolution"))
   {
    dmN=atoi (par1);
    if (dmN<0 || dmN>dmC)
     dmN=0;
   }
   else if (!strcmp (par0, "AngleY"))
    tTheta=atof (par1);
   else if (!strcmp (par0, "AngleX"))
    tAngleX=atof (par1);
   else if (!strcmp (par0, "MapX"))
    tMapX=atoi (par1);
   else if (!strcmp (par0, "MapZ"))
    tMapZ=atoi (par1);
   else if (!strcmp (par0, "X"))
    tX=atof (par1);
   else if (!strcmp (par0, "Z"))
    tZ=atof (par1);
   else if (!strcmp (par0, "Height"))
    hillRh=atof (par1);
  }
 }

 if (tMapZ>=-squareS/2-1 && tMapX>=-squareS/2-1 && tMapZ<=mapQ+squareS/2 && tMapX<=mapQ+squareS/2
  && !(isMapped (tMapZ, tMapX) && !isEmpty (tMapZ, tMapX))
  && tX<=squareL && tX>=-squareL && tZ<=squareL && tZ>=-squareL
  && tAngleX<=angleXlimit && tAngleX>=-angleXlimit && tTheta<=180.0f && tTheta>=-180.0f)
 {
  mapX=tMapX;
  mapZ=tMapZ;
  x=tX;
  z=tZ;
  theta=tTheta;
  angleX=tAngleX;
 }
}

void myColor3f (float myColorR, float myColorG, float myColorB)
{
 glColor3f (myColorR*gammaR, myColorG*gammaG, myColorB*gammaB);
}

    /*
   char mb [32];
   sprintf (mb, "%d", wParam);
   MessageBox (hWnd, mb, "", MB_OK);
   */