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

/**************************
 * 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"// https://khronos.org/registry/OpenGL/api/GL/wglext.h

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

#include <gdiplus/gdiplus.h>

#include "resource.h"

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

float light_pos;
int light_d;
int state=0, stateCPU=0, dropCPU=0, goCPU=0, sel_x=-1, sel_y=-1, sel_x0=-1, sel_y0=-1;
int leap_x=0, leap_y=0;
char piece [2], draw_move [2];
float move_sx, move_sy, move_sa=0.07f, move_saB;
bool move1=false;

float cq=1.0f, ca=0.005f, cl=1.0f;

int leaps_c=-1, leaps_n=0;
int leaps_x [100];
int leaps_y [100];
int leaps_x1 [100];
int leaps_y1 [100];

char board3x [1000] [64];

int move_x1, move_y1, move_x2, move_y2;

int lang=0;// Ru, 1 - En
int sleepTime=50;
long stats_wins=0, stats_loses=0, stats_draws=0, stats_restart=0, stats_notfin=0, stats_moves=0;



int game_over=0;//1-player, 2-monk

bool castle_player_left=true;
bool castle_player_right=true;
bool castle_player_swap;
int castle_player_lr=0;

bool castle_monk_left=true;
bool castle_monk_right=true;
bool castle_monk_swap;
int castle_monk_lr=0;

bool castle_s_left=false;
bool castle_s_right=false;
int castle_s_lr=0;

bool side=false;



float bgAngle=0.0f;
float pLoad=150.0f, pLoad0=150.0f;
float loadAngleStep=1.0f;
float loadAngle=0.0f-pLoad*loadAngleStep;
float loadFarStep=0.1f;
float loadFar=-pLoad*loadFarStep;
  int pC=0;
  int sndVol=0, melVol=0;
  int qC=0, qCmx=4;
float rvSteps=255.0f/1.0f;
float rvAngle;
  int rvDir=1;
 bool checkOn=false;
float checkStep=1.5f;
float checkState;
 bool messAfter=false;


  int cx, cy;
  int posX=0, posY=0, posHL=1;
  int posXl=-1, posYl=-1;
  int mXar0 [10], mYar0 [10];
  int mXar1 [10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, mYar1 [10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  int mXar [10], mYar [10];
  int cCPU=100, cPlayer=100, cMove=0, drawMove=0, drawMoves=50;
 bool drawPieces=false;
  int button=0;
float colorCoordHL [4]={0.0f, 0.0f, 0.0f}, colorCoordX [4]={0.0f, 0.0f, 1.0f}, colorCoordY [4]={0.5f, 0.25f, 0.0f},
      colorCellHL2 [4]={0.0f, 0.75f, 0.0f}, colorCellHL1 [4]={0.5f, 0.25f, 1.0f}, colorCellHL0 [4]={1.0f, 0.0f, 0.0f},
      colorCellOff [4]={1.0f, 0.8f, 0.1f},
      colorPlayer [4]={1.0f, 1.0f, 1.0f}, colorCPU [4]={1.0f, 1.0f, 1.0f},
      colorPlayer50 [4]={1.0f, 1.0f, 1.0f}, colorCPU50 [4]={0.25f, 0.25f, 0.25f},
      colorPlayerStat [4]={1.0f, 1.0f, 1.0f}, colorCPUStat [4]={0.25f, 0.25f, 0.25f},
      colorVol [4]={0.95f, 0.8f, 0.1f}, colorExitT [4]={0.85f, 0.0f, 0.0f},
      colorOff [4]={0.85f, 0.85f, 0.85f}, colorOn [4]={0.0f, 1.0f, 0.0f},
      colorExitB [4]={1.0, 0.0f, 0.0f}, colorRestB [4]={1.0f, 0.85f, 0.15f},
      colorTxt [4]={1.0f, 1.0f, 1.0f}, colorTxtB [4]={0.5f, 0.5f, 0.5f}, colorH [4]={1.0f, 0.5f, 0.0f},
      colorShadow [4]={0.1f, 0.1f, 0.1f};
  char txt [16];

float resultAngle;
 bool resultOff;

  int fpsOn=0;
 bool clockTweak=false;
 long clockL=0;
float clockD=0.0f;

 bool noRest=false, blur_on=false, loaded=false;
 bool moreFPS=true;
 bool bQuit=false;
 bool quitCPU=false;
  int infOn=0;

 bool ctrl_key=false, keyLockEsc=false, keyLockEnter=false;
 int fontS, fps=-1, paintC=0, timeS=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 [256];
GLuint base; // База списка отображения для фонта
GLuint PixelFormat;

COLORREF bGround=RGB (55, 56, 84);
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

const unsigned int TIMER_MEL=5, TIMER_QUIT=10, TIMER_MELON=15;
COLORREF pixel=RGB (0, 0, 0);
TRACKMOUSEEVENT tme;
POINT mypoint;
HCURSOR curArrow, curWait, curNew, curOff;
static HANDLE gThreadCPU=NULL;
DWORD wThreadCPU;
DWORD WINAPI threadCPU (LPVOID);
WNDCLASS wc;
HWND hWnd;
HINSTANCE gThisInstance; int gFunsterStil;
HDC hDC;
HGLRC hRC;        
MSG msg;
PAINTSTRUCT PaintStruct;

ULONG_PTR gdiplusToken;
Gdiplus::Graphics * gDC;
Gdiplus::Image * imagesH;

char mb [64];

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

// board
char init_d [64];

// from log
//char init_p [65]={""};

//board
char init_p [64]={
'd','c','b','e','f','b','c','d',
'a','a','a','a','a','a','a','a',
'0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0',
'1','1','1','1','1','1','1','1',
'4','3','2','5','6','2','3','4'
};

 void paint ();
 void mouseMove ();
 void mouseClick ();
  int getPos (int x, int y);
 void cellInfo ();
 void windowUp ();
 void moveCPU ();
 void playerMove ();
 void flip_side ();
 bool flip_board (char d [64]);
 bool check_pick (int x, int y);
  int whose (char t);
 void Restart ();

 void statusBar ();
 void fpsC ();
float fpsTweak ();
 void saveConf ();
 void loadConf ();
 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 BuildLists ();
 void getScr ();
 void screenSet ();
 void screenUp ();
 void keysOff ();
 void loading ();


 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;

 Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
 GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, NULL);

 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 ();
 loadConf ();
 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 (hInstance, MAKEINTRESOURCE(ID_CUR));
 curArrow=LoadCursor (hInstance, MAKEINTRESOURCE(ID_CUR));
 curWait=LoadCursor (hInstance, MAKEINTRESOURCE(ID_CUW));
 curNew=LoadCursor (hInstance, MAKEINTRESOURCE(ID_NEW));
 curOff=LoadCursor (hInstance, MAKEINTRESOURCE(ID_OFF));
 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
   0,           // Program decides the position
   0,           // where the window ends up on the screen
   cx+1,        // The programs width
   cy+1,        // 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);
 }

 ShowWindow (hWnd, iCmdShow);
 SetForegroundWindow (hWnd);// Слегка повысим приоритет
 SetFocus (hWnd);// Установить фокус клавиатуры на наше окно
 InitGL ();

 playSound ("board", 0, 1);

 tme.cbSize=sizeof(tme);
 tme.dwFlags=TME_HOVER;
 tme.hwndTrack=hWnd;// hanlde of window you want the mouse over message for.
 tme.dwHoverTime=HOVER_DEFAULT;

 TrackMouseEvent(&tme);

 gThreadCPU=CreateThread (NULL, 0, threadCPU, (void *)"threadCPU", 0, &wThreadCPU);

 memcpy (init_d, init_p, 64);

 if (side)
  flip_side ();

 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)
    paint ();
  }

  Sleep ((audioOnce ? 12 : 10)*(moreFPS ? 1 : 3));
 }

 saveConf ();
 meloClose ();

 Gdiplus::GdiplusShutdown (gdiplusToken);

 quitCPU=true;
 for (int i=0; i<10 && quitCPU; i++)
  Sleep (10);
 CloseHandle (gThreadCPU);

 // 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
    windowUp ();

   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
      windowUp ();

     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_LBUTTONUP:
   mouseClick ();
   break;

  case WM_MOUSEMOVE:
   mouseMove ();
   break;


  case WM_TIMER:
   switch (wParam)
   {
    case TIMER_MELON:
     KillTimer (hWnd, TIMER_MELON);
     meloVol=melVol*250;
     break;
    case TIMER_MEL:
     KillTimer (hWnd, TIMER_MEL);
     meloInit ();
     break;
    case TIMER_QUIT:
     qC++;
     if (qC==qCmx)
     {
      KillTimer (hWnd, TIMER_QUIT);
      bQuit=true;
     }
     break;
   }
   break;

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

    case VK_ESCAPE:
     if (keyLockEsc)
      break;

     keyLockEsc=true;

     if (infOn)
     {
      infOn=0;
      playSound ("shake");
      mouseMove ();
     }
     break;

    case VK_RIGHT:
      infOn=0;
     if (posX<7)
     {
      posX++;
      cellInfo ();
     }
     break;

    case VK_LEFT:
      infOn=0;
     if (posX>0)
     {
      posX--;
      cellInfo ();
     }
     break;

    case VK_NEXT:
      infOn=0;
     if (posX<7 && posY<7)
     {
      posX++;
      posY++;
      cellInfo ();
     }
     break;

    case VK_PRIOR:
      infOn=0;
     if (posX<7 && posY>0)
     {
      posX++;
      posY--;
      cellInfo ();
     }
     break;

    case VK_UP:
      infOn=0;
     if (posY>0)
     {
      posY--;
      cellInfo ();
     }
     break;

    case VK_DOWN:
      infOn=0;
     if (posY<7)
     {
      posY++;
      cellInfo ();
     }
     break;

    case VK_HOME:
      infOn=0;
     if (posX>0 && posY>0)
     {
      posX--;
      posY--;
      cellInfo ();
     }
     break;

    case VK_END:
     infOn=0;
     if (posX>0 && posY<7)
     {
      posX--;
      posY++;
      cellInfo ();
     }
     break;

    case VK_CONTROL:
     ctrl_key=true;
     break;
   }

   if (wParam==VK_RETURN || wParam==VK_SPACE || wParam==VK_CLEAR)
   {
    if (keyLockEnter)
     break;

    infOn=0;
    playerMove ();
    keyLockEnter=true;
   }
   return 0;

  case WM_KEYUP:

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

    case VK_CONTROL:
     ctrl_key=false;
     break;
   }

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

   return 0;

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

DWORD WINAPI threadCPU (LPVOID)
{
 // initialize random seed:
 srand (time (NULL));

 while (!quitCPU)
 {
  if (state==3 && !stateCPU)
  {
   state=4;
   moveCPU ();
  }

  Sleep (10);
 }

 quitCPU=false;
}

int conf_side=-1;

void Restart ()
{
 if (cMove>0)
 {
  stateCPU=1;
  if (goCPU)
   dropCPU=1;

  move1=false;
  sel_x0=-1;
  sel_y0=-1;
  sel_x=-1;
  sel_y=-1;
  conf_side=-1;

  castle_player_left=true;
  castle_player_right=true;
  castle_player_lr=0;

  castle_monk_left=true;
  castle_monk_right=true;
  castle_monk_lr=0;

  if (state>=10)
  {
   if (game_over==3)
   {
   }
   else if (game_over==1)
    side=0;
   else if (game_over==2)
    side=1;
  }
  game_over=0;

  if (state<10)
   stats_restart++;
  state=0;
  memcpy (init_d, init_p, 64);
  if (side)
   flip_side ();
  cPlayer=100;
  cCPU=100;
  cMove=0;
  drawMove=0;
  infOn=0;
  playSound ("board");
  if (side)
   state=3;

  stateCPU=0;
 }
 else
  playSound ("break");
}

void keysOff ()
{
 ctrl_key=false;
 keyLockEsc=false;
 keyLockEnter=false;
}

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;
}

void windowUp ()
{
 SetWindowPos (hWnd, HWND_TOP, 0, 0, cx+1, cy+1, SWP_NOMOVE);// ?
}

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

void screenUp ()
{
 noRest=true;

 windowUp ();

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

 SetForegroundWindow (hWnd);// Слегка повысим приоритет
 SetFocus (hWnd);// Установить фокус клавиатуры на наше окно

 InitGL ();

 pC=0;

 noRest=false;
}

void InitGL ()
{
 SetCursor (curWait);

 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
 glDisable (GL_DEPTH_TEST);// Disables Depth Testing
 glDepthFunc (GL_LEQUAL);  // The Type Of Depth Testing To Do

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

// if (PixelFormat!=0)
//  glEnable (GL_MULTISAMPLE_ARB);

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

 int i;
 for (i=0; i<9; i++)
  mXar0 [i]=cx/2-(float)cy*4.5f/9.0f+cy*i/9;
 for (i=0; i<9; i++)
  mYar0 [i]=cy*(i+1)/9;

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

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

 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=dmBs;//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)
{
 wglMakeCurrent (NULL, NULL);
 wglDeleteContext (hRC);
 ReleaseDC (hWnd, hDC);
}

int shape [65536];

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

 int ave, inc, alf;

 char texs [25] [32]={"blank.gif", "bar.jpg", "bord.gif",
                      "figs256.gif", "bg.jpg",
                      "tooltip.jpg", "sky.jpg",
                      "", "lits.jpg"
                     };

 char texd [16]={"data\\textures"};
 char txt [_MAX_PATH];
 int i2, xi, yi, cl, ri;

 for (i2=0; i2<9; i2++)
 {
  if (strlen (texs [i2])==0)
  {
  }
  else if (i2==1 || i2==2 || i2==3 || i2==8)// обработка символов
  {
   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
    {
     if (i2==1)
     {
      lWidthPixels=256;
      lHeightPixels=256;
      lWidth2=gWidth;
      lHeight2=gHeight;
     }
     else if (i2==2)
     {
      lWidthPixels=64;
      lHeightPixels=64;
      lWidth2=gWidth*60/256;
      lHeight2=gHeight*60/256;
     }
     else if (i2==3)
     {
      lWidthPixels=256;
      lHeightPixels=256;
      lWidth2=gWidth;
      lHeight2=gHeight;
     }
     else if (i2==8)
     {
      lWidthPixels=128;
      lHeightPixels=128;
      lWidth2=gWidth/2;
      lHeight2=gHeight/2;
     }

     // создать временный растр
     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);// загрузить описатель временного растра
                                       // в описатель временного контекста устройства 

      int xi2=0, yi2=0, rows=14, i3from=32, i3to=256, i3, i3x;
      if (i2==1)
      {
       i3from=0;
       i3to=10;
       rows=1;
      }
      else if (i2==2)
      {
       i3from=0;
       i3to=5;
       rows=1;
      }
      else if (i2==3)
      {
       i3from=0;
       i3to=12;
       rows=2;
      }
      for (i3=i3from; i3<i3to; i3++)
      {
       if (!(i2==8 && i3>126 && i3<161))
       {
        i3x=i3;
        if (i2==1)
        {
         if (xi2==0)
          i3x=2;
         else if (xi2==2)
          i3x=16;
         else if (xi2==3)
          i3x=17;
         else if (xi2==4)
          i3x=10;
         else if (xi2==5)
          i3x=11;
         else if (xi2==6)
          i3x=14;
         else if (xi2==7)
          i3x=12;
         else if (xi2==8)
          i3x=9;
         else if (xi2==9)
          i3x=1;
        }
        else if (i2==2)
        {
         if (xi2==0)
          i3x=5;
         else if (xi2==1)
          i3x=3;
         else if (xi2==2)
          i3x=4;
         else if (xi2==3)
          i3x=6;
         else if (xi2==4)
          i3x=7;
        }
        else if (i2==3)
        {
         if (yi2==0)
         {
          if (xi2==0)
           i3x=20;
          else if (xi2==1)
           i3x=21;
          else if (xi2==2)
           i3x=22;
          else if (xi2==3)
           i3x=23;
          else if (xi2==4)
           i3x=24;
          else if (xi2==5)
           i3x=25;
         }
         else
         {
          if (xi2==0)
           i3x=26;
          else if (xi2==1)
           i3x=27;
          else if (xi2==2)
           i3x=28;
          else if (xi2==3)
           i3x=29;
          else if (xi2==4)
           i3x=30;
          else if (xi2==5)
           i3x=31;
         }
        }

        // отрисовка IPicture в растр
        pPicture->Render (hdcTemp, 0, 0, lWidthPixels, lHeightPixels,
                      int(lWidth2*xi2), int(lHeight2*(rows-yi2)), int(lWidth2), int(-lHeight2), 0);

        long i, n=lWidthPixels*lHeightPixels;
        // преобразовать из BGR в RGB формат и устанавливаем значение Alpha

        if (i2==2)
        {
         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
         }
        }
        else if (i2==1 && xi2==0)
        {
         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
         }
        }
        else if (i2==1 && xi2==1)
        {
         memset (shape, 0, 256*256);

         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]<50 && pPixel [1]<50 && pPixel [2]>150)
           shape [i]=0;
          else
           shape [i]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
         }
        }
        else if (i2==1 && xi2==9)
        {
         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]=shape [i];           // установить значение alpha
         }
        }
        else if (i2==1)
        {
         for (i=0; i<n; i++) // Цикл по всем пикселям
         {
          BYTE* pPixel=(BYTE*)(&pBits[i]);// берем текущий пиксель
          BYTE  temp=pPixel [0];          // сохраняем первый цвет в переменной Temp (Синий)
          pPixel [0]=pPixel [2]/1.4f;     // ставим  Красный на место (в первую позицию)
          pPixel [1]=pPixel [1]/1.4f;
          pPixel [2]=temp/1.4f;           // ставим значение Temp в третий параметр (3rd)
          pPixel [3]=shape [i];           // установить значение alpha
         }
        }
        else if (i2==8)
        {
         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]<25 && pPixel [1]<25 && pPixel [2]>55)// убираем фон
          {
           pPixel [0]=0;
           pPixel [1]=0;
           pPixel [2]=0;
           pPixel [3]=0;
          }
          else
          {
           // Меняем цвет на серый, убирая случайные цветные пиксели
           pPixel [0]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
           pPixel [1]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
           pPixel [2]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
           // Добавляем к градиенту прозрачность, на основе цвета
           pPixel [3]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
          }
         }
        }
        else if (i2==3)
        {
         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

          if (pPixel [2]>250 && pPixel [0]<25 && pPixel [1]<5)
          {
           pPixel [0]=0;
           pPixel [1]=0;
           pPixel [2]=0;
           pPixel [3]=0;                  // установить значение alpha =0
          }
          else
          {
           ave=(pPixel [0]+pPixel [1]+pPixel [2])/3;

           if (pPixel [2]>ave+15)
           {
            alf=255-pPixel [2]*1.5f;
            if (alf<0)
             alf=0;
            pPixel [3]=alf;
           }

           pPixel [0]=ave;
           pPixel [1]=ave;
           pPixel [2]=ave;
          }
         }
        }
        else if (i2==8)
        {
         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]<25 && pPixel [1]<25 && pPixel [2]>55)// убираем фон
          {
           pPixel [0]=0;
           pPixel [1]=0;
           pPixel [2]=0;
           pPixel [3]=0;
          }
          else
          {
           // Меняем цвет на серый, убирая случайные цветные пиксели
           pPixel [0]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
           pPixel [1]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
           pPixel [2]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
           // Добавляем к градиенту прозрачность, на основе цвета
           pPixel [3]=(pPixel [0]+pPixel [1]+pPixel [2])/3;
          }
         }
        }

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

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

        if (i2==2)
        {
         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_LINEAR);//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);

        xi2++;
        if ((i2==8 && xi2>=rows) || (i2==3 && xi2>5))
        {
         xi2=0;
         yi2++;
        }
       }
      }

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

      pPicture->Release();    //уменьшает счетчик IPicture
     }
    }
   }
  }
  else
  {
   int i2x=i2;
   if (i2==3)
    i2x=8;
   else if (i2==4)
    i2x=13;
   else if (i2==5)
    i2x=15;
   else if (i2==6)
    i2x=18;

   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), 2048);
     pPicture->get_Height (&lHeight);// получить высоту изображения
     lHeightPixels=MulDiv (lHeight, GetDeviceCaps (hdcTemp, LOGPIXELSY), 2048);
     if (i2==0)
     {
      gWidth=lWidth;
      gHeight=lHeight;
     }

     // преобразовать изображение к ближайшей степени двойки
     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

      if (i2x==8)
      {
       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]=shape [i];           // установить значение alpha
       }
      }
      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 [i2x]);//  создаем текстуру texid

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

      // (измените для нужного вам типа фильтрации)
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//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, dmBs,//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;
}

// Функция для печати текстурного шрифта;
// нет параметров, вместо - глобальные переменные
float literaScale=0.25f, literaX=0.0f, literaY=0.0f, literaZ=-2.4325f;
char literaText [256]="";
void glPrintLitera ()
{
 glEnable (GL_BLEND);

 for (int i=0; i<strlen (literaText); i++)
 {
  int t=literaText [i];
  if (t<0)
   t+=256;
  if (!((t>126 && t<161) || (t>-1 && t<=32)))
  {
   glBindTexture (GL_TEXTURE_2D, texture [t]);
   glBegin (GL_QUADS);
   glTexCoord2f (0.0f, 0.0f); glVertex3f (-literaScale/2.0f+literaX+i*literaScale/1.85f,
                                          -literaScale/2.0f+literaY, literaZ);// Низ лево
   glTexCoord2f (1.0f, 0.0f); glVertex3f ( literaScale/2.0f+literaX+i*literaScale/1.85f,
                                          -literaScale/2.0f+literaY, literaZ);// Низ право
   glTexCoord2f (1.0f, 1.0f); glVertex3f ( literaScale/2.0f+literaX+i*literaScale/1.85f,
                                           literaScale/2.0f+literaY, literaZ);// Верх право
   glTexCoord2f (0.0f, 1.0f); glVertex3f (-literaScale/2.0f+literaX+i*literaScale/1.85f,
                                           literaScale/2.0f+literaY, literaZ);// Верх лево
   glEnd ();
  }
 }

 glDisable (GL_BLEND);
}

GLuint bgList, brdList, infList;

float brdX=1.0f, brdY=1.0f, brdZ=-2.4325f;
float brdS=2.0f;
float brdL=-brdS*5.5f/9.0f, brdR=brdL+brdS;
float brdT=brdS/2.0f, brdB=-brdS/2.0f;

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

 bgList=glGenLists (5);// создаем списки

 float bgQ=sqrt (pow (cx, 2)+pow (cy, 2))/(float)cx;
 float bgX=1.825f*((float(cx)/float(cy))/(1600.0f/900.0f))*bgQ, bgY=bgX, bgZ=0.0f;

 glNewList (bgList, GL_COMPILE);// Новый откомпилированный список отображения
 glBindTexture (GL_TEXTURE_2D, texture [18]);
 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 0.0f); glVertex3f (-bgX, -bgY, bgZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f ( bgX, -bgY, bgZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f ( bgX,  bgY, bgZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (-bgX,  bgY, bgZ);// Верх лево
 glEnd ();
 glEndList ();// Закончили создание списка

 brdList=bgList+1;
 glNewList (brdList, GL_COMPILE);
 glBindTexture (GL_TEXTURE_2D, texture [0]);
 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL, brdB, brdZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (brdR, brdB, brdZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (brdR, brdT, brdZ);// Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL, brdT, brdZ);// Верх лево
 glEnd ();
 glEndList ();// Закончили создание списка

 infList=brdList+1;
 glNewList (infList, GL_COMPILE);
 glBindTexture (GL_TEXTURE_2D, texture [13]);
 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL, brdB, brdZ);// Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (brdR, brdB, brdZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (brdR, brdT, brdZ);// Верх право +0.00135f
 glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL, brdT, brdZ);// Верх лево +0.001f
 glEnd ();
 glEndList ();// Закончили создание списка
}

COLORREF ig1=RGB (170, 170, 170), ig2=RGB (185, 185, 185), iw=RGB (240, 240, 240);
bool isGray (COLORREF px)
{
 if (px>ig1 && px<ig2)
  return true;
 return false;
}

bool isWhite (COLORREF px)
{
 if (px>iw)
  return true;
 return false;
}

//transfers from 2-dimension coordinates to string position
int get_p (int x, int y)
{
 int p;
 if (x>0 && x<9 && y>0 && y<9)
  p=(y-1)*8+x-1;
 else
  p=65;

 return p;
}


int try_dn [2500];

char try_d [2500] [64];
 int try_leap_x [2500], try_leap_y [2500];
char try_d2 [50000] [64];
char try_d3 [500000] [64];

int try_p2 [50000];
int try_p3 [500000];

int try_b [2500];
int try_b2 [50000];
int try_b3 [500000];

int try_b_s2 [2500];
int try_b_s3 [50000];
int try_b_s4 [500000];

int try_i, try_i2, try_i3, try_i4, try_ix, try_ix2, try_ix3;
int try_s, try_pt, try_n=0;

bool xy_check (int x, int y)
{
 if (x>0 && x<9 && y>0 && y<9)
  return true;
 else
  return false;
}

int n_ar [16]={1, -2, -1, -2, 1, 2, -1, 2, 2, -1, -2, -1, 2, 1, -2, 1};

bool check_check (char d [64])
{
 int i=0, x, y, x2, y2;
 char t;

 for (y2=1; y2<9; y2++)
 {
  for (x2=1; x2<9; x2++)
  {
   if (d [i]=='6')
   {
    x=x2;
    y=y2;
   }
   i++;
  }
 }

 i=0;
 for (x2=x+1; x2<9; x2++)
 {
  i++;
  t=d [get_p (x2, y)];
  if (t!='0')
  {
   if (t=='d' || t=='e' || (i==1 && t=='f'))
    return true;
   else
    break;
  }
 }

 i=0;
 for (x2=x-1; x2>0; x2--)
 {
  i++;
  t=d [get_p (x2, y)];
  if (t!='0')
  {
   if (t=='d' || t=='e' || (i==1 && t=='f'))
    return true;
   else
    break;
  }
 }

 i=0;
 for (y2=y+1; y2<9; y2++)
 {
  i++;
  t=d [get_p (x, y2)];
  if (t!='0')
  {
   if (t=='d' || t=='e' || (i==1 && t=='f'))
    return true;
   else
    break;
  }
 }

 i=0;
 for (y2=y-1; y2>0; y2--)
 {
  i++;
  t=d [get_p (x, y2)];
  if (t!='0')
  {
   if (t=='d' || t=='e' || (i==1 && t=='f'))
    return true;
   else
    break;
  }
 }

 i=0;
 for (x2=x+1; x2<9 && y+i<8; x2++)
 {
  i++;
  t=d [get_p (x2, y+i)];
  if (t!='0')
  {
   if (t=='b' || t=='e' || (i==1 && t=='f'))
    return true;
   else
    break;
  }
 }

 i=0;
 for (x2=x-1; x2>0 && y+i<8; x2--)
 {
  i++;
  t=d [get_p (x2, y+i)];
  if (t!='0')
  {
   if (t=='b' || t=='e' || (i==1 && t=='f'))
    return true;
   else
    break;
  }
 }

 i=0;
 for (x2=x+1; x2<9 && y+i>1; x2++)
 {
  i--;
  t=d [get_p (x2, y+i)];
  if (t!='0')
  {
   if (t=='b' || t=='e' || (i==-1 && (t=='a' || t=='f')))
    return true;
   else
    break;
  }
 }

 i=0;
 for (x2=x-1; x2>0 && y+i>1; x2--)
 {
  i--;
  t=d [get_p (x2, y+i)];
  if (t!='0')
  {
   if (t=='b' || t=='e' || (i==-1 && (t=='a' || t=='f')))
    return true;
   else
    break;
  }
 }

 for (i=0; i<16; i=i+2)
 {
  x2=x+n_ar [i];
  y2=y+n_ar [i+1];
  if (xy_check (x2, y2)==true)
  {
   t=d [get_p (x2, y2)];
   if (t=='c')
    return true;
  }
 }

 return false;
}

bool took;
int take_ball (char v)
{
 took=true;

 if (v=='a')
  return 6;
 else if (v=='b')
  return 24;
 else if (v=='c')
  return 21;
 else if (v=='d')
  return 30;
 else if (v=='e')
  return 57;
 else if (v=='f')
  return 1;
}

bool board3repeat ()
{
 int i, i2, match=0;

 for (i=0; i<cMove-1; i++)
 {
  if (strncmp (board3x [i], init_d, 64)==0)
   match++;
 }
 if (match>1)
 {
  game_over=3;
  stats_draws++;
  resultAngle=90.0f;
  resultOff=false;
  checkState=0.0f;
  messAfter=false;
  state=10;

  return true;
 }

 memcpy (board3x [cMove-1], init_d, 64);

 return false;
}

void powers ()
{
 char p_fb [10]="abcde", p_fw [10]="12345";
 int i, i2, q=8, p_all=12;
 int p_rb=p_all, p_rw=p_all;

 drawPieces=true;

 for (i=0; i<5; i++)
 {
  if (i>0 && i<4)
   q=2;
  else if (i>3)
   q=1;
  p_all+=q*take_ball (p_fb [i]);
 }

 for (i2=0; i2<64; i2++)
 {
  for (i=0; i<5; i++)
  {
   if (init_d [i2]==p_fb [i])
    p_rb+=take_ball (p_fb [i]);
   else if (init_d [i2]==p_fw [i])
    p_rw+=take_ball (p_fb [i]);

   if (init_d [i2]==p_fb [0] || init_d [i2]==p_fw [0])
    drawPieces=false;
  }
 }

 if (!side)
 {
  cPlayer=p_rw*100/p_all;
  cCPU=p_rb*100/p_all;
 }
 else
 {
  cPlayer=p_rb*100/p_all;
  cCPU=p_rw*100/p_all;
 }

 if (!(drawPieces && p_rw<=36 && p_rb<=36))
  drawPieces=false;
}

bool r_move;
int do_move (char d [64], int x1, int y1, int x2, int y2, int take)
{
 took=false;
 r_move=false;
 int try_leap_x_t=0, try_leap_y_t=0;

 if (xy_check (x2, y2)==true)
 {
  int p1=get_p (x1, y1);
  int p2=get_p (x2, y2);
  char x=d [p1];
  char v=d [p2];
  int r=0;
  bool leap_on=false;

  if (v!='1' && v!='2' && v!='3' && v!='4' && v!='5' && v!='6')
  {
   if ((v=='0' && take==0))
   {
    r=1;
    r_move=true;

    if ((y2-y1)==-2 || (y2-y1)==2)
    {
     r+=2;//pawn +2
     try_leap_x_t=x2;
     try_leap_y_t=y2;
    }
    else
     r+=1;

    if (y1==6)
    {
     if (castle_s_lr==2)
     {
      if (x1==2)
       r-=2;
     }
     else if (castle_s_lr==1)
     {
      if (x1==7)
       r-=2;
     }
    }
    else if (y1==7)
    {
     if (x1==4 || x1==5)
      r+=1;
     else if (castle_s_left || castle_s_right)
     {
      if (castle_s_left)
      {
       if (x1==1 || x1==2 || x1==3)
       {
        if (y2==5)
         r-=3;
        else
         r-=2;
       }
      }
      if (castle_s_right)
      {
       if (x1==6 || x1==7 || x1==8)
       {
        if (y2==5)
         r-=3;
        else
         r-=2;
       }
      }
     }
     else if (castle_s_lr==2)
     {
      if (x1==2 && y2==6)
       r+=1;
      else if (x1==1 || x1==2 || x1==3)
      {
       if (y2==5)
        r-=3;
       else
        r-=2;
      }
     }
     else if (castle_s_lr==1)
     {
      if (x1==7 && y2==6)
       r+=1;
      else if (x1==6 || x1==7 || x1==8)
      {
       if (y2==5)
        r-=3;
       else
        r-=2;
      }
     }
    }
   }
   else if (take==1)
   {
    if (v!='0')
    {
     r=take_ball (v)-1;//pawn take
     r_move=true;
    }
    else if (x2==9-leap_x && y1==9-leap_y && try_s==0)
    {
     leap_on=true;
     r=take_ball ('a')-2;//pawn leap take
     r_move=true;
    }
    else if (x2==9-try_leap_x [try_pt] && y1==9-try_leap_y [try_pt] && try_s==2)
    {
     leap_on=true;
     r=take_ball ('a')-2;//pawn leap take
     r_move=true;
    }
   }
   else if (take==2)
   {
    if (v=='0')
    {
     r=1;
     r_move=true;
    }
    else
    {
     r=take_ball (v);
     r_move=true;
    }
    if (x=='3')
    {
     if ((x1==2 && y1==8 && castle_s_left==true) || (x1==7 && y1==8 && castle_s_right==true))
      r+=2;
     else if ((x2==2 && y2==8 && y1!=8 && castle_s_left==true) || (x2==7 && y2==8 && y1!=8 && castle_s_right==true))
      r-=1;
    }
    if (x=='2')
    {
     if ((x1==3 && y1==8 && castle_s_left==true) || (x1==6 && y1==8 && castle_s_right==true))
      r+=2;
     else if ((x2==3 && y2==8 && y1!=8 && castle_s_left==true) || (x2==6 && y2==8 && y1!=8 && castle_s_right==true))
      r-=1;
    }
   }
   else if (take==3)//castle test
   {
    if (v=='0')
    {
     r=1;
     r_move=true;
    }
   }
   else if (take==4 || take==5 || take==6 || take==7)//castle make
   {
    if (v=='0')
    {
     r=1;
     r_move=true;
    }
   }
  }

  if (r_move)
  {
   char d2 [64];
   memcpy (d2, d, 64);
   d2 [p2]=d2 [p1];
   d2 [p1]='0';

   if (take==0 || take==1)
   {
    if (y2==1)
    {
     d2 [p2]='5';
     r+=51+(4-try_s);// no always 2-nd move
    }
    else if (leap_on==true)
    {
     if (try_s==0)
      d2 [get_p (9-leap_x, 9-leap_y)]='0';
     else if (try_s==2)
      d2 [get_p (9-try_leap_x [try_pt], 9-try_leap_y [try_pt])]='0';
    }
   }
   else if (take==3)
   {
   }
   else if (take==4)
   {
    int p3=get_p (8, y1);
    int p4=get_p (6, y2);
    d2 [p4]=d2 [p3];
    d2 [p3]='0';
    r=4;
   }
   else if (take==5)
   {
    int p3=get_p (1, y1);
    int p4=get_p (4, y2);
    d2 [p4]=d2 [p3];
    d2 [p3]='0';
    r=5;
   }
   else if (take==6)
   {
    int p3=get_p (1, y1);
    int p4=get_p (3, y2);
    d2 [p4]=d2 [p3];
    d2 [p3]='0';
    r=4;
   }
   else if (take==7)
   {
    int p3=get_p (8, y1);
    int p4=get_p (5, y2);
    d2 [p4]=d2 [p3];
    d2 [p3]='0';
    r=5;
   }
   if (x=='6' && take<3)
   {
    if (castle_s_right==true)
     r-=2;
    if (castle_s_left==true)
     r-=2;
   }
   if (x=='4' && take<3)
   {
    if (x1==8 && castle_s_right==true)
     r-=2;
    if (x1==1 && castle_s_left==true)
     r-=2;
   }

   if (take!=3 && took)
   {
    // prefer early move (when losing)
    int try_add=1;
    if (cCPU<cPlayer && try_s>0)
     try_add=try_s;
    if (took)
     r+=(4-try_add);
   }

   if (check_check (d2)==false)
   {
    if (take!=3)
    {
     if (try_s==0)
     {
      memcpy (try_d [try_i], d2, 64);
      try_b [try_i]=r;
      try_leap_x [try_i]=try_leap_x_t;
      try_leap_y [try_i]=try_leap_y_t;
      try_i++;

      if (try_i>try_ix)
       try_ix=try_i;
     }
     else if (try_s==2)
     {
      memcpy (try_d2 [try_i2], d2, 64);
      try_p2 [try_i2]=try_pt;
      try_b2 [try_i2]=r;
      try_i2++;

      if (try_i2>try_ix2)
       try_ix2=try_i2;
     }
     else if (try_s==3)
     {
      memcpy (try_d3 [try_i3], d2, 64);
      try_p3 [try_i3]=try_pt;
      try_b3 [try_i3]=r;
      try_i3++;

      if (try_i3>try_ix3)
       try_ix3=try_i3;
     }
     else if (try_s==4)
     {
      if (try_b_s4 [try_pt]<r)
       try_b_s4 [try_pt]=r;
     }
    }

    return r;
   }
   else if (take==3)
   {
    r_move=false;
    return 0;
   }
   else
    return r;
  }
  else
  {
   r_move=false;
   return 0;
  }
 }
 else
 {
  r_move=false;
  return 0;
 }
}

bool try_move (char d [64], int x1, int y1)
{
 char f=d [get_p (x1, y1)];
 int x2, y2, i, i2, r;
 if (f=='1')//pawn
 {
  do_move (d, x1, y1, x1, y1-1, 0);
  if (r_move && y1==7)
   do_move (d, x1, y1, x1, y1-2, 0);

  do_move (d, x1, y1, x1-1, y1-1, 1);
  do_move (d, x1, y1, x1+1, y1-1, 1);
 }
 if (f=='2' || f=='5' || f=='6')//monk, queen & king
 {
  i2=0;
  for (i=x1+1; i<9; i++)
  {
   i2++;

   do_move (d, x1, y1, i, y1+i2, 2);
   if (!r_move || took || f=='6')
    break;
  }
  i2=0;
  for (i=x1+1; i<9; i++)
  {
   i2--;

   do_move (d, x1, y1, i, y1+i2, 2);
   if (!r_move || took || f=='6')
    break;
  }
  i2=0;
  for (i=x1-1; i>0; i--)
  {
   i2++;

   do_move (d, x1, y1, i, y1+i2, 2);
   if (!r_move || took || f=='6')
    break;
  }
  i2=0;
  for (i=x1-1; i>0; i--)
  {
   i2--;

   do_move (d, x1, y1, i, y1+i2, 2);
   if (!r_move || took || f=='6')
    break;
  }
 }
 else if (f=='3')//kNight
 {
  for (i=0; i<16; i=i+2)
   do_move (d, x1, y1, x1+n_ar [i], y1+n_ar [i+1], 2);
 }
 if (f=='4' || f=='5' || f=='6')//rook, queen & king
 {
  for (i=x1+1; i<9; i++)
  {
   do_move (d, x1, y1, i, y1, 2);
   if (!r_move || took || f=='6')
    break;
  }
  for (i=x1-1; i>0; i--)
  {
   do_move (d, x1, y1, i, y1, 2);
   if (!r_move || took || f=='6')
    break;
  }
  for (i=y1+1; i<9; i++)
  {
   do_move (d, x1, y1, x1, i, 2);
   if (!r_move || took || f=='6')
    break;
  }
  for (i=y1-1; i>0; i--)
  {
   do_move (d, x1, y1, x1, i, 2);
   if (!r_move || took || f=='6')
    break;
  }
 }
 if (f=='6')//king's castle
 {
  if (x1==5)
  {
   if (castle_s_right==true)
   {
    if (check_check (d)==false)
    {
     do_move (d, x1, y1, x1+1, y1, 3);
     if (r_move)
      do_move (d, x1, y1, x1+2, y1, 4);
    }
   }
   if (castle_s_left==true)
   {
    if (check_check (d)==false)
    {
     do_move (d, x1, y1, x1-1, y1, 3);
     if (r_move)
     {
      do_move (d, 1, y1, 2, y1, 3);
      if (r_move)
       do_move (d, x1, y1, x1-2, y1, 5);
     }
    }
   }
  }
  else if (x1==4)
  {
   if (castle_s_left==true)
   {
    if (check_check (d)==false)
    {
     do_move (d, x1, y1, x1-1, y1, 3);
     if (r_move)
      do_move (d, x1, y1, x1-2, y1, 6);
    }
   }
   if (castle_s_right==true)
   {
    if (check_check (d)==false)
    {
     do_move (d, x1, y1, x1+1, y1, 3);
     if (r_move)
     {
      do_move (d, 8, y1, 7, y1, 3);
      if (r_move)
       do_move (d, x1, y1, x1+2, y1, 7);
     }
    }
   }
  }
 }

 return true;
}

bool check_any (char d [64], int tx, int ty)
{
 try_i=0;
 try_s=0;
 try_move (d, tx, ty);
 if (try_i>0)
  return true;

 return false;
}

bool check_move (int tx, int ty)
{
 try_i=0;
 try_s=0;
 sel_x=sel_x0+1;
 sel_y=sel_y0+1;

 castle_s_left=castle_player_left;
 castle_s_right=castle_player_right;
 castle_s_lr=castle_player_lr;

 try_move (init_d, sel_x, sel_y);
 int i;
 char d2 [64];
 memcpy (d2, init_d, 64);
 d2 [get_p (tx, ty)]=d2 [get_p (sel_x, sel_y)];
 d2 [get_p (sel_x, sel_y)]='0';
 if (ty==1 && d2 [get_p (tx, ty)]=='1')
  d2 [get_p (tx, ty)]='5';
 if (d2 [get_p (tx, ty)]=='1' && init_d [get_p (tx, ty)]=='0' && d2 [get_p (tx, ty+1)]=='a')
  d2 [get_p (tx, ty+1)]='0';

 if (d2 [get_p (tx, ty)]=='6')
 {
  if (!side)
  {
   if (sel_x==5 && castle_player_right==true && tx==7 && sel_y==8)
   {
    d2 [get_p (6, 8)]=d2 [get_p (8, 8)];
    d2 [get_p (8, 8)]='0';
   }
   else if (sel_x==5 && castle_player_left==true && tx==3 && sel_y==8)
   {
    d2 [get_p (4, 8)]=d2 [get_p (1, 8)];
    d2 [get_p (1, 8)]='0';
   }
  }
  else
  {
   if (sel_x==4 && castle_player_right==true && tx==6 && sel_y==8)
   {
    d2 [get_p (5, 8)]=d2 [get_p (8, 8)];
    d2 [get_p (8, 8)]='0';
   }
   else if (sel_x==4 && castle_player_left==true && tx==2 && sel_y==8)
   {
    d2 [get_p (3, 8)]=d2 [get_p (1, 8)];
    d2 [get_p (1, 8)]='0';
   }
  }
 }

 for (i=0; i<try_i; i++)
 {
  if (strncmp (try_d [i], d2, 64)==0)
   return true;
 }

 return false;
}

void flip_side ()
{
 int i;
 char d2 [64];

 memcpy (d2, init_d, 64);

 for (i=0; i<64; i++)
 {
  if (d2 [i]=='0')
   init_d [63-i]='0';

  else if (d2 [i]=='1')
   init_d [63-i]='a';
  else if (d2 [i]=='2')
   init_d [63-i]='b';
  else if (d2 [i]=='3')
   init_d [63-i]='c';
  else if (d2 [i]=='4')
   init_d [63-i]='d';
  else if (d2 [i]=='5')
   init_d [63-i]='e';
  else if (d2 [i]=='6')
   init_d [63-i]='f';

  else if (d2 [i]=='a')
   init_d [63-i]='1';
  else if (d2 [i]=='b')
   init_d [63-i]='2';
  else if (d2 [i]=='c')
   init_d [63-i]='3';
  else if (d2 [i]=='d')
   init_d [63-i]='4';
  else if (d2 [i]=='e')
   init_d [63-i]='5';
  else if (d2 [i]=='f')
   init_d [63-i]='6';
 }
}

bool flip_board (char d [64])
{
 int i;
 char d2 [64];

 memcpy (d2, d, 64);

 for (i=0; i<64; i++)
 {
  if (d2 [i]=='0')
   d [63-i]='0';

  else if (d2 [i]=='1')
   d [63-i]='a';
  else if (d2 [i]=='2')
   d [63-i]='b';
  else if (d2 [i]=='3')
   d [63-i]='c';
  else if (d2 [i]=='4')
   d [63-i]='d';
  else if (d2 [i]=='5')
   d [63-i]='e';
  else if (d2 [i]=='6')
   d [63-i]='f';

  else if (d2 [i]=='a')
   d [63-i]='1';
  else if (d2 [i]=='b')
   d [63-i]='2';
  else if (d2 [i]=='c')
   d [63-i]='3';
  else if (d2 [i]=='d')
   d [63-i]='4';
  else if (d2 [i]=='e')
   d [63-i]='5';
  else if (d2 [i]=='f')
   d [63-i]='6';
 }
}

char move_f;

void moveCPU ()
{
 goCPU=1;

 char d [64], d2 [64], d3 [64], d4 [64];
 int x, y, i, x2, y2, i2, try_c1, try_c0, x3, y3, i3;
 char t, f;
 int try_i2_t, try_i3_t;

 memcpy (d, init_d, 64);

 flip_board (d);

 i=0;
 try_i=0;
 try_s=0;

 castle_s_left=castle_monk_right;
 castle_s_right=castle_monk_left;
 castle_s_lr=castle_monk_lr;

 for (y=1; y<9; y++)
 {
  for (x=1; x<9; x++)
  {
   t=d [i];
   if (t=='1' || t=='2' || t=='3' || t=='4' || t=='5' || t=='6')
    try_move (d, x, y);

   i++;
  }
 }

 if (try_i>0)
 {
  try_i2=0;
  try_s=2;

  castle_s_left=castle_player_left;
  castle_s_right=castle_player_right;
  castle_s_lr=castle_player_lr;

  for (i3=0; i3<try_i; i3++)
  {
   memcpy (d2, try_d [i3], 64);
   flip_board (d2);

   i=0;
   try_pt=i3;
   try_i2_t=try_i2;
   for (y=1; y<9; y++)
   {
    for (x=1; x<9; x++)
    {
     t=d2 [i];
     if (t=='1' || t=='2' || t=='3' || t=='4' || t=='5' || t=='6')
      try_move (d2, x, y);
     i++;
    }
   }

   if (try_i2==try_i2_t)
   {
    if (check_check (d2))
     try_b [i3]+=1200;//player out of moves = checkmate
    else
     try_b [i3]-=100;//player out of moves = stalemate

    try_b_s2 [i3]=0;
   }
  }

  try_i3=0;
  try_s=3;

  castle_s_left=false;//castle_monk_left;
  castle_s_right=false;//castle_monk_right;
  castle_s_lr=0;//castle_monk_lr;

  for (i3=0; i3<try_i2; i3++)
  {
   memcpy (d2, try_d2 [i3], 64);
   flip_board (d2);

   i=0;
   try_pt=i3;
   try_i3_t=try_i3;
   for (y=1; y<9; y++)
   {
    for (x=1; x<9; x++)
    {
     t=d2 [i];
     if (t=='1' || t=='2' || t=='3' || t=='4' || t=='5' || t=='6')
      try_move (d2, x, y);
     i++;
    }
   }

   if (try_i3==try_i3_t)
   {
    if (check_check (d2))
     try_b2 [i3]+=1200;//monk out of moves = checkmate
    else
     try_b2 [i3]-=100;//monk out of moves = stalemate

    try_b_s3 [i3]=0;
   }
  }

  try_s=4;

  castle_s_left=false;//castle_player_left;
  castle_s_right=false;//castle_player_right;
  castle_s_lr=0;//castle_player_lr;

  int i3_1,i3_2,i3_3,i3_4;
  i3_1=(int)(try_i3/5);
  i3_2=(int)(try_i3/5*2);
  i3_3=(int)(try_i3/5*3);
  i3_4=(int)(try_i3/5*4);
  for (i3=0; i3<try_i3; i3++)
  {
   try_b_s3 [try_p3 [i3]]=-150;
   try_b_s4 [i3]=-1050;
  }
  for (i3=0; i3<try_i3; i3++)
  {
   memcpy (d2, try_d3 [i3], 64);
   flip_board (d2);

   i=0;
   try_pt=i3;
   for (y=1; y<9; y++)
   {
    for (x=1; x<9; x++)
    {
     t=d2 [i];
     if (t=='1' || t=='2' || t=='3' || t=='4' || t=='5' || t=='6')
      try_move (d2, x, y);
     i++;
    }
   }

   if (i3==i3_1)
    Sleep (sleepTime);
   else if (i3==i3_2)
    Sleep (sleepTime);
   else if (i3==i3_3)
    Sleep (sleepTime);
   else if (i3==i3_4)
    Sleep (sleepTime);
  }

  Sleep (sleepTime);

  int try_t=0;
  for (i=0; i<try_i3; i++)
  {
   try_t=try_b3 [i]-try_b_s4 [i];

   if (try_b_s3 [try_p3 [i]]<try_t)
    try_b_s3 [try_p3 [i]]=try_t;
  }

  Sleep (sleepTime);

  for (i=0; i<try_i2; i++)
   try_b_s2 [try_p2 [i]]=-150;
  for (i=0; i<try_i2; i++)
  {
   try_t=try_b2 [i]-try_b_s3 [i];

   if (try_b_s2 [try_p2 [i]]<try_t)
    try_b_s2 [try_p2 [i]]=try_t;
  }

  Sleep (sleepTime);

  try_n=0;
  int try_max=-100000;
  for (i=0; i<try_i; i++)
  {
   try_t=try_b [i]-try_b_s2 [i];

   if (try_max<try_t)
    try_max=try_t;
  }

  int try_nc=0;
  for (i=0; i<try_i; i++)
  {
   try_t=try_b [i]-try_b_s2 [i];

   if (try_max==try_t)
   {
    try_dn [try_nc]=i;
    try_nc++;
   }
  }
  int try_rn=rand ()%try_nc;
  try_n=try_dn [try_rn];
  
//  sprintf (mb, "%d", try_nc);

  Sleep (sleepTime);

  flip_board (try_d [try_n]);

  int castle_p1;
  int castle_p2;
  int castle_p3;
  if (!side)
  {
   castle_p1=get_p (5, 1);
   castle_p2=get_p (7, 1);
   castle_p3=get_p (3, 1);
  }
  else
  {
   castle_p1=get_p (4, 1);
   castle_p2=get_p (6, 1);
   castle_p3=get_p (2, 1);
  }

  if (init_d [castle_p1]!=try_d [try_n] [castle_p1] && init_d [castle_p1]=='f' && init_d [castle_p2]!=try_d [try_n] [castle_p2] && !side)
  {
   move_x1=5;
   move_y1=1;
   move_x2=7;
   move_y2=1;
   move_f='f';
  }
  else if (init_d [castle_p1]!=try_d [try_n] [castle_p1] && init_d [castle_p1]=='f' && init_d [castle_p3]!=try_d [try_n] [castle_p3] && !side)
  {
   move_x1=5;
   move_y1=1;
   move_x2=3;
   move_y2=1;
   move_f='f';
  }
  else if (init_d [castle_p1]!=try_d [try_n] [castle_p1] && init_d [castle_p1]=='f' && init_d [castle_p2]!=try_d [try_n] [castle_p2] && side)
  {
   move_x1=4;
   move_y1=1;
   move_x2=6;
   move_y2=1;
   move_f='f';
  }
  else if (init_d [castle_p1]!=try_d [try_n] [castle_p1] && init_d [castle_p1]=='f' && init_d [castle_p3]!=try_d [try_n] [castle_p3] && side)
  {
   move_x1=4;
   move_y1=1;
   move_x2=2;
   move_y2=1;
   move_f='f';
  }
  else
  {
   i=0;
   for (y2=1; y2<9; y2++)
   {
    for (x2=1; x2<9; x2++)
    {
     if (init_d [i]!=try_d [try_n] [i])
     {
      if (try_d [try_n] [i]=='0' && !(x2==leap_x && y2==leap_y))
      {
       move_x1=x2;
       move_y1=y2;
      }
      else
      {
       move_x2=x2;
       move_y2=y2;
       move_f=try_d [try_n] [i];
      }
     }
     i++;
    }
   }
  }

  Sleep (sleepTime);

  if (try_max>1000)
   game_over=2;
  else
  {
   bool more_moves=false;
   i=0;

   for (y2=1; y2<9; y2++)
   {
    for (x2=1; x2<9; x2++)
    {
     if (whose (try_d [try_n] [i])==1)
     {
      if (check_any (try_d [try_n], x2, y2))
       more_moves=true;
     }

     i++;
    }
   }
   if (!more_moves)
    game_over=3;
  }
 }
 else
 {
  memcpy (d2, init_d, 64);
  flip_board (d2);
  if (check_check (d2))
  {
   game_over=1;
   stats_wins++;
   conf_side=0;
  }
  else
  {
   game_over=3;
   stats_draws++;
  }
  resultAngle=90.0f;
  resultOff=false;
  checkState=0.0f;
  messAfter=false;
  state=10;
 }



 if (state!=10)
 {
  move1=true;
  sel_x0=move_x1-1;
  sel_y0=move_y1-1;
  sel_x=move_x2-1;
  sel_y=move_y2-1;

  piece [0]=init_d [getPos (sel_x0, sel_y0)];
  draw_move [0]=piece [0];
  leap_x=0;
  leap_y=0;
  if (piece [0]=='a' && abs (move_y2-move_y1)==2)
  {
   leap_x=9-move_x2;
   leap_y=9-move_y2;
  }
  move_sx=(float)sel_x0;
  move_sy=(float)sel_y0;
  leaps_c=-1;
  leaps_n=0;

  if (piece [0]=='c')
  {
   leaps_c=1;
   if (abs (sel_x-sel_x0)>abs (sel_y-sel_y0))
   {
    leaps_x1 [0]=sel_x;
    leaps_y1 [0]=sel_y0;
    leaps_x1 [1]=sel_x;
    leaps_y1 [1]=sel_y;
   }
   else
   {
    leaps_x1 [0]=sel_x0;
    leaps_y1 [0]=sel_y;
    leaps_x1 [1]=sel_x;
    leaps_y1 [1]=sel_y;
   }
  }

  if (dropCPU)
  {
   dropCPU=0;

   move1=false;
   sel_x0=-1;
   sel_y0=-1;
   sel_x=-1;
   sel_y=-1;
  }
  else
  {
/*
   // log last board
   FILE *file;
   char path [_MAX_PATH], log [65];
   sprintf (path, "%s%s", AppDir, "data\\log.txt");
   file=fopen (path, "wb");
   if (file!=NULL)
   {
    memset (log, 0, 65);
    memcpy (log, try_d [try_n], 64);
    fwrite (log, 1, strlen (log), file);
    fclose (file);
   }
*/

   state=5;
  }
 }

 goCPU=0;
}


int whose (char t)
{
 if (t=='1' || t=='2' || t=='3' || t=='4' || t=='5' || t=='6')
  return 1;
 else if (t=='a' || t=='b' || t=='c' || t=='d' || t=='e' || t=='f')
  return 2;
 else
  return 0;
}

int totx (char t)
{
 int i;

 char toar1 [16]="123456abcdef";
 char toar2 [16]="abcdef123456";
 int txar [16]={20, 22, 21, 23, 24, 25,
                26, 28, 27, 29, 30, 31};

 for (i=0; i<12; i++)
 {
  if (!side && toar1 [i]==t)
   return txar [i];
  else if (side && toar2 [i]==t)
   return txar [i];
 }
}



void paint ()
{
 if (pC<10 && !(pLoad>0.0f))
  pC++;

 // OpenGL animation code goes here
 glPushMatrix ();
 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 // glEnable (GL_MULTISAMPLE_ARB);


 // Фон
 glLoadIdentity ();  // Сброс просмотра
 glTranslatef (0.0f, 0.0f, -2.4f);
 glRotatef (-bgAngle, 0.0f, 0.0f, 1.0f);

 bgAngle+=0.05f*fpsTweak ();
 if (bgAngle>180.0f)
  bgAngle-=360.0f;

 if (game_over==1)
  cq=1.0f;
 else if (game_over==2)
  cq=0.0f;
 else if (side)
 {
  if (cPlayer>0)
   cq=(float)cCPU/(float)cPlayer;
  else
   cq=(float)cCPU;
 }
 else
 {
  if (cCPU>0)
   cq=(float)cPlayer/(float)cCPU;
  else
   cq=(float)cPlayer;
 }
 if (cq>1.0f)
  cq=1.0f;
 if ((cq>cl && cq-cl>ca*fpsTweak ()) || (cq<cl && cl-cq>ca*fpsTweak ()))
 {
  cq=cl+(cq-cl)*ca*fpsTweak ();
  cl=cq;
 }
 glColor3f (0.5f*cq+0.5f, 0.5f*cq+0.5f, 0.5f*cq+0.5f);

 glCallList (bgList);


// glDisable (GL_MULTISAMPLE_ARB);


 // Доска
 glLoadIdentity ();  // Сброс просмотра


 // Intro
 if (pLoad>0.0f)
 {
  pLoad-=1.0f*fpsTweak ()*3;
  glTranslatef (0.0f, 0.0f, loadFar);
  glRotatef (-loadAngle, 0.0f, 0.0f, 1.0f);
  loadFar+=loadFarStep*fpsTweak ()*3;
  loadAngle+=loadAngleStep*fpsTweak ()*3;
  SetCursor (curWait);
  glEnable (GL_BLEND);
 }

 glColor3f (1.0f, 1.0f, 1.0f);
 glCallList (brdList);


 // Тёмные клетки
 glColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [2]);

 float brdCell=brdS/9.0f;
 float brdL2=brdL+brdS/9.0f, brdT2=brdT-brdS/9.0f;
 int xi, yi, c=0;
 for (yi=0; yi<8; yi++)
 {
  c++;

  for (xi=0; xi<8; xi++)
  {
   c++;
   if (c%2)
   {
    glBegin (GL_QUADS);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xi*brdCell, brdT2-(yi+1)*brdCell, brdZ);    // Низ лево
    glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xi+1)*brdCell, brdT2-(yi+1)*brdCell, brdZ);// Низ право
    glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xi+1)*brdCell, brdT2-yi*brdCell, brdZ);    // Верх право
    glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xi*brdCell, brdT2-yi*brdCell, brdZ);        // Верх лево
    glEnd ();
   }
  }
 }


 // Угол доски
 glColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [5]);
 glBegin (GL_QUADS);
 glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL, brdT-brdCell, brdZ);        // Низ лево
 glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL+brdCell, brdT-brdCell, brdZ);// Низ право
 glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL+brdCell, brdT, brdZ);        // Верх право
 glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL, brdT, brdZ);                // Верх лево
 glEnd ();


 // Верхний край доски
 glColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [4]);
 for (xi=0; xi<8; xi++)
 {
  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xi*brdCell, brdT-brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xi+1)*brdCell, brdT-brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xi+1)*brdCell, brdT, brdZ);        // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xi*brdCell, brdT, brdZ);            // Верх лево
  glEnd ();
 }


 // Левый
 glColor3f (1.0f, 1.0f, 1.0f);
 glBindTexture (GL_TEXTURE_2D, texture [3]);
 for (yi=0; yi<8; yi++)
 {
  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL, brdT2-(yi+1)*brdCell, brdZ);        // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL+brdCell, brdT2-(yi+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL+brdCell, brdT2-yi*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL, brdT2-yi*brdCell, brdZ);            // Верх лево
  glEnd ();
 }


 // Уточнение координат клеток
 if (pC==2)
 {
  int xs, ys=cy/2, xi2, yi2, c=0, i;
  bool chk;

  xs=mXar0 [0]-(mXar0 [1]-mXar0 [0])/2;

  for (xi=xs; xi<cx; xi++)
  {
   pixel=GetPixel (hDC, xi, ys);

   if ((isGray (pixel) && (c+1)%2) || (isWhite (pixel) && !((c+1)%2)))
   {
    chk=true;
    for (xi2=0; xi2<5; xi2++)
    {
     pixel=GetPixel (hDC, xi+xi2+1, ys);
     if ((!isGray (pixel) && (c+1)%2) || (!isWhite (pixel) && !((c+1)%2)))
      chk=false;
    }
    if (chk)
    {
     mXar1 [c]=xi;
     c++;
     if (c==8)
      break;      
    }
   }
  }

  if (c==8)
  {
   ys=cy/2+(mYar0 [1]-mYar0 [0]);
   for (i=xi+10; i<cx; i++)
   {
    pixel=GetPixel (hDC, i, ys);
    if (!isGray (pixel))
    {
     mXar1 [c]=i;
     break;
    }
   }
  }

  int mx=0, mxd;
  for (i=0; i<9; i++)
  {
   mxd=abs (mXar1 [i]-mXar0 [i]);
   if (mxd>mx)
    mx=mxd;
  }
  if (mx<25)
  {
   for (i=0; i<9; i++)
    mXar [i]=mXar1 [i];
  }
  else
  {
   for (i=0; i<9; i++)
    mXar [i]=mXar0 [i];
  }

  ys=mYar0 [0]-(mYar0 [1]-mYar0 [0])/2; xs=mXar [0]+(mXar [1]-mXar [0])/2; c=0;

  for (yi=ys; yi<cy; yi++)
  {
   pixel=GetPixel (hDC, xs, yi);

   if ((isGray (pixel) && !((c+1)%2)) || (isWhite (pixel) && (c+1)%2))
   {
    chk=true;
    for (yi2=0; yi2<5; yi2++)
    {
     pixel=GetPixel (hDC, xs, yi+yi2+1);
     if ((!isGray (pixel) && !((c+1)%2)) || (!isWhite (pixel) && (c+1)%2))
      chk=false;
    }
    if (chk)
    {
     mYar1 [c]=yi;
     c++;
     if (c==8)
      break;  
    }
   }
  }

  if (c==8)
  {
   mYar1 [c]=cy;

   for (i=yi+10; i<cy+10; i++)
   {
    pixel=GetPixel (hDC, xs, i);
    if (!isGray (pixel))
    {
     mYar1 [c]=i;
     break;
    }
   }
  }

  for (i=0; i<9; i++)
  {
   mxd=abs (mYar1 [i]-mYar0 [i]);
   if (mxd>mx)
    mx=mxd;
  }
  if (mx<25)
  {
   for (i=0; i<9; i++)
    mYar [i]=mYar1 [i];
  }
  else
  {
   for (i=0; i<9; i++)
    mYar [i]=mYar0 [i];
  }
//  moreFPS=false;

  mouseMove ();
  SetTimer (hWnd, TIMER_MEL, 1000, NULL);
  playSound ("board");

  if (side)
  {
   state=3;//0
   SetCursor (curWait);
  }
  else
   SetCursor (curArrow);
 }


 if (pC>1)
 {
  // Выделение клетки
  if (state>1)
   glColor3f (colorCellOff [0], colorCellOff [1], colorCellOff [2]);
  else if (posHL==1)
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  else if (posHL==2)
   glColor3f (colorCellHL2 [0], colorCellHL2 [1], colorCellHL2 [2]);
  else
   glColor3f (colorCellHL0 [0], colorCellHL0 [1], colorCellHL0 [2]);

  glBindTexture (GL_TEXTURE_2D, texture [0]);
  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+posX*brdCell, brdT2-(posY+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(posX+1)*brdCell, brdT2-(posY+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(posX+1)*brdCell, brdT2-posY*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+posX*brdCell, brdT2-posY*brdCell, brdZ);        // Верх лево
  glEnd ();


  // Выделение Y-координаты
  glColor3f (1.0f, 1.0f, 1.0f);
  glBindTexture (GL_TEXTURE_2D, texture [6]);
  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL, brdT2-(posY+1)*brdCell, brdZ);        // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL+brdCell, brdT2-(posY+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL+brdCell, brdT2-posY*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL, brdT2-posY*brdCell, brdZ);            // Верх лево
  glEnd ();


  // X
  glColor3f (1.0f, 1.0f, 1.0f);
  glBindTexture (GL_TEXTURE_2D, texture [7]);
  glBegin (GL_QUADS);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+posX*brdCell, brdT-brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(posX+1)*brdCell, brdT-brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(posX+1)*brdCell, brdT, brdZ);        // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+posX*brdCell, brdT, brdZ);            // Верх лево
  glEnd ();


  // Наименование координат
  char literaL [10]={'8', '7', '6', '5', '4', '3', '2', '1'};
  char literaT [10]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
  glBindTexture (GL_TEXTURE_2D, texture [0]);

  literaY=brdT-brdCell/2.0f; literaZ=brdZ;
  literaScale=0.07f;
  for (xi=0; xi<8; xi++)
  {
   if (xi==posX)
    glColor3f (colorCoordHL [0], colorCoordHL [1], colorCoordHL [2]);
   else
    glColor3f (colorCoordX [0], colorCoordX [1], colorCoordX [2]);

   literaX=brdL2+brdCell/2.0f+brdCell*xi; 
   if (side)
    sprintf (literaText, "%c", literaT [7-xi]);
   else
    sprintf (literaText, "%c", literaT [xi]);
   glPrintLitera ();// Печать текста GL на экран
  }

  literaX=brdL+brdCell/2.0f;
  for (yi=0; yi<8; yi++)
  {
   if (yi==posY)
    glColor3f (colorCoordHL [0], colorCoordHL [1], colorCoordHL [2]);
   else
    glColor3f (colorCoordY [0], colorCoordY [1], colorCoordY [2]);

   literaY=brdT2-brdCell/2.0f-brdCell*yi; 
   if (side)
    sprintf (literaText, "%c", literaL [7-yi]);
   else
    sprintf (literaText, "%c", literaL [yi]);
   glPrintLitera ();// Печать текста GL на экран
  }


  // Фишки
  if (state==1)
  {
   rvAngle-=(float)rvDir*360.0f/rvSteps*fpsTweak ();
   if (rvAngle<-30.0f)
   {
    rvAngle=-30.0f;
    rvDir*=-1;
   }
   else if (rvAngle>30.0f)
   {
    rvAngle=30.0f;
    rvDir*=-1;
   }
  }

  glLoadIdentity ();// Сброс просмотра

  glEnable (GL_BLEND);

  int xi, yi, c=0;

  for (yi=0; yi<8; yi++)
  {
   for (xi=0; xi<8; xi++)
   {
    if (whose (init_d [c])!=0 && !(xi==sel_x0 && yi==sel_y0 && state!=0))
    {
     glBindTexture (GL_TEXTURE_2D, texture [totx (init_d [c])]);
     glBegin (GL_QUADS);

     if ((whose (init_d [c])==1 && !side) || (whose (init_d [c])==2 && side))
      glColor3f (colorPlayer [0], colorPlayer [1], colorPlayer [2]);
     else if ((whose (init_d [c])==2 && !side) || (whose (init_d [c])==1 && side))
      glColor3f (colorCPU [0], colorCPU [1], colorCPU [2]);

     glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xi*brdCell, brdT2-(yi+1)*brdCell, brdZ);    // Низ лево
     glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xi+1)*brdCell, brdT2-(yi+1)*brdCell, brdZ);// Низ право
     glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xi+1)*brdCell, brdT2-yi*brdCell, brdZ);    // Верх право
     glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xi*brdCell, brdT2-yi*brdCell, brdZ);        // Верх лево

     glEnd ();
    }
    c++;
   }
  }

  // Статистика
  float xr=8.1f, yr=-1.0f;
  glLoadIdentity ();// Сброс просмотра
  glTranslatef (brdL2+(xr+1)*brdCell-brdCell/2.0f, brdT2-(yr+1)*brdCell+brdCell/2.0f, brdZ);

  glBindTexture (GL_TEXTURE_2D, texture [1]);
  if (!side)
   glColor3f (colorCPU50 [0], colorCPU50 [1], colorCPU50 [2]);
  else
   glColor3f (colorPlayer50 [0], colorPlayer50 [1], colorPlayer50 [2]);

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

  yr=0.0f;
  glLoadIdentity ();// Сброс просмотра
  glTranslatef (brdL2+(xr+1)*brdCell-brdCell/2.0f, brdT2-(yr+1)*brdCell+brdCell/2.0f, brdZ);

  glBindTexture (GL_TEXTURE_2D, texture [1]);
  if (!side)
   glColor3f (colorPlayer50 [0], colorPlayer50 [1], colorPlayer50 [2]);
  else
   glColor3f (colorCPU50 [0], colorCPU50 [1], colorCPU50 [2]);

  glBegin (GL_QUADS);

  glTexCoord2f (0.0f, 0.0f); glVertex3f (-brdCell/(2.0f), -brdCell/2.0f, 0.0f);// Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdCell/(2.0f), -brdCell/2.0f, 0.0f); // Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdCell/(2.0f), brdCell/2.0f, 0.0f);  // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (-brdCell/(2.0f), brdCell/2.0f, 0.0f); // Верх лево

  glEnd ();


  // Кнопки
  glLoadIdentity ();// Сброс просмотра

  xr=8.1f, yr=1.0f;
  glBindTexture (GL_TEXTURE_2D, texture [16]);
  glBegin (GL_QUADS);
  if (button!=1)
  {
   if (cMove>0)
   {
    if (state==12)
     glColor3f (colorOn [0], colorOn [1], colorOn [2]);
    else
     glColor3f (colorRestB [0], colorRestB [1], colorRestB [2]);
   }
   else
    glColor3f (colorOff [0], colorOff [1], colorOff [2]);
  }
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  xr=8.1f, yr=2.0f;
  glBindTexture (GL_TEXTURE_2D, texture [17]);
  glBegin (GL_QUADS);
  if (button!=2)
   glColor3f (colorRestB [0], colorRestB [1], colorRestB [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  xr=8.1f, yr=3.0f;
  glBindTexture (GL_TEXTURE_2D, texture [10]);
  glBegin (GL_QUADS);
  if (button!=3)
   glColor3f (colorRestB [0], colorRestB [1], colorRestB [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  xr=8.1f, yr=4.0f;
  glBindTexture (GL_TEXTURE_2D, texture [11]);
  glBegin (GL_QUADS);
  if (button!=4)
   glColor3f (colorRestB [0], colorRestB [1], colorRestB [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  xr=8.1f, yr=5.0f;
  glBindTexture (GL_TEXTURE_2D, texture [14]);
  glBegin (GL_QUADS);
  if (button!=5)
   glColor3f (colorRestB [0], colorRestB [1], colorRestB [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  xr=8.1f, yr=6.0f;
  glBindTexture (GL_TEXTURE_2D, texture [12]);
  glBegin (GL_QUADS);
  if (button!=6)
   glColor3f (colorRestB [0], colorRestB [1], colorRestB [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  xr=8.1f, yr=7.0f;
  glBindTexture (GL_TEXTURE_2D, texture [9]);
  glBegin (GL_QUADS);
  if (button!=7)
   glColor3f (colorExitB [0], colorExitB [1], colorExitB [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
  glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
  glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+1)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
  glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
  glEnd ();

  glDisable (GL_BLEND);


  // Количество ходов
  glBindTexture (GL_TEXTURE_2D, texture [0]);
  xr=8.8f; yr=-1.0f;

  literaY=brdT2-brdCell/2.0f-brdCell*yr; 
  literaX=brdL2+brdCell/2.0f+brdCell*xr;
  literaScale=0.12f;
  if (!side)
  {
   glColor3f (colorCPUStat [0], colorCPUStat [1], colorCPUStat [2]);
   sprintf (literaText, "%d", cCPU);
  }
  else
  {
   glColor3f (colorPlayerStat [0], colorPlayerStat [1], colorPlayerStat [2]);
   sprintf (literaText, "%d", cPlayer);
  }
  glPrintLitera ();// Печать текста GL на экран

  yr=0.0f;

  literaY=brdT2-brdCell/2.0f-brdCell*yr; 
  literaX=brdL2+brdCell/2.0f+brdCell*xr;
  if (!side)
  {
   glColor3f (colorPlayerStat [0], colorPlayerStat [1], colorPlayerStat [2]);
   sprintf (literaText, "%d", cPlayer);
  }
  else
  {
   glColor3f (colorCPUStat [0], colorCPUStat [1], colorCPUStat [2]);
   sprintf (literaText, "%d", cCPU);
  }
  glPrintLitera ();// Печать текста GL на экран

  // Язык
  yr=2.0f;

  literaY=brdT2-brdCell/2.0f-brdCell*yr; 
  literaX=brdL2+brdCell/2.0f+brdCell*xr;
  if (lang==0)
   sprintf (literaText, "Ru");
  else if (lang==1)
   sprintf (literaText, "En");
  if (button!=2)
   glColor3f (colorVol [0], colorVol [1], colorVol [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glPrintLitera ();// Печать текста GL на экран

  // Громкость
  yr=3.0f;

  literaY=brdT2-brdCell/2.0f-brdCell*yr;
  literaX=brdL2+brdCell/2.0f+brdCell*xr;
  sprintf (literaText, "%d", sndVol*25);
  if (button!=3)
   glColor3f (colorVol [0], colorVol [1], colorVol [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glPrintLitera ();// Печать текста GL на экран

  yr=4.0f;

  literaY=brdT2-brdCell/2.0f-brdCell*yr;
  literaX=brdL2+brdCell/2.0f+brdCell*xr;
  sprintf (literaText, "%d", melVol*25);
  if (button!=4)
   glColor3f (colorVol [0], colorVol [1], colorVol [2]);
  else
   glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
  glPrintLitera ();// Печать текста GL на экран


  // Таймер выхода
  if (qC!=0)
  {
   yr=7.0f;

   literaY=brdT2-brdCell/2.0f-brdCell*yr;
   literaX=brdL2+brdCell/2.0f+brdCell*xr;
   sprintf (literaText, "%d", qCmx-qC);
   if (button!=7)
    glColor3f (colorExitT [0], colorExitT [1], colorExitT [2]);
   else
    glColor3f (colorCellHL1 [0], colorCellHL1 [1], colorCellHL1 [2]);
   glPrintLitera ();// Печать текста GL на экран
  }


  // Реверсная фишка
  if (state==1)
  {
   xr=sel_x0;
   yr=sel_y0;
   glLoadIdentity ();// Сброс просмотра
   glEnable (GL_BLEND);
   glTranslatef (brdL2+(xr+1)*brdCell-brdCell/2.0f, brdT2-(yr+1)*brdCell+brdCell/2.0f, brdZ);
   glRotatef (rvAngle, 0.0f, 0.0f, 1.0f);
   glBindTexture (GL_TEXTURE_2D, texture [totx (piece [0])]);
   glBegin (GL_QUADS);

   if ((whose (piece [0])==1 && !side) || (whose (piece [0])==2 && side))
    glColor3f (colorPlayer [0], colorPlayer [1], colorPlayer [2]);
   else if ((whose (piece [0])==2 && !side) || (whose (piece [0])==1 && side))
    glColor3f (colorCPU [0], colorCPU [1], colorCPU [2]);

   glTexCoord2f (0.0f, 0.0f); glVertex3f (-brdCell/(2.0f), -brdCell/2.0f, 0.0f);// Низ лево
   glTexCoord2f (1.0f, 0.0f); glVertex3f (brdCell/(2.0f), -brdCell/2.0f, 0.0f); // Низ право
   glTexCoord2f (1.0f, 1.0f); glVertex3f (brdCell/(2.0f), brdCell/2.0f, 0.0f);  // Верх право
   glTexCoord2f (0.0f, 1.0f); glVertex3f (-brdCell/(2.0f), brdCell/2.0f, 0.0f); // Верх лево
   glEnd ();
   glDisable (GL_BLEND);
  }
  else if (state==2 || state==5)
  {
   int sel_x1, sel_y1, sel_x10, sel_y10;

   if (leaps_c>-1)
   {
    sel_x1=(float)leaps_x1 [leaps_n];
    sel_y1=(float)leaps_y1 [leaps_n];
    if (leaps_c>0 && leaps_n>0)
    {
     sel_x10=(float)leaps_x1 [leaps_n-1];
     sel_y10=(float)leaps_y1 [leaps_n-1];
    }
    else
    {
     sel_x10=(float)sel_x0;
     sel_y10=(float)sel_y0;
    }
   }
   else
   {
    sel_x1=(float)sel_x;
    sel_y1=(float)sel_y;
    sel_x10=(float)sel_x0;
    sel_y10=(float)sel_y0;
   }

   move_saB=0.0f;//(float(abs (sel_x1-sel_x10))-1.0f)*move_sa*fpsTweak ()/5.0f;
   if (sel_x1>sel_x10)
   {
    move_sx+=move_sa*fpsTweak ()+move_saB;
    if (move_sx>=(float)sel_x1)
     move_sx=(float)sel_x1;
   }
   else
   {
    move_sx-=move_sa*fpsTweak ()+move_saB;
    if (move_sx<=(float)sel_x1)
     move_sx=(float)sel_x1;
   }
   if (sel_y1>sel_y10)
   {
    move_sy+=move_sa*fpsTweak ()+move_saB;
    if (move_sy>=(float)sel_y1)
     move_sy=(float)sel_y1;
   }
   else
   {
    move_sy-=move_sa*fpsTweak ()+move_saB;
    if (move_sy<=(float)sel_y1)
     move_sy=(float)sel_y1;
   }
   if (move_sx==(float)sel_x1 && move_sy==(float)sel_y1)
   {
    char t [16], t_snd [16]="";
    if (leaps_c>0)
    {
     if (leaps_n==leaps_c)
      sprintf (t_snd, "move%d", (rand ()%5+1));
    }
    else
    {
     if (abs(sel_x1-sel_x10)<2 && abs(sel_y1-sel_y10)<2)
      sprintf (t_snd, "dash");
     else
      sprintf (t_snd, "move%d", (rand ()%5+1));
    }

    if (leaps_n<leaps_c)
    {
     leaps_n++;

     if (t_snd [0])
      playSound (t_snd);
    }
    else
    {
     // no castle

     if (sel_y==0 && sel_x==0)
      castle_monk_left=false;
     else if (sel_y==0 && sel_x==7)
      castle_monk_right=false;
     else if (sel_y==7 && sel_x==0)
      castle_player_left=false;
     else if (sel_y==7 && sel_x==7)
      castle_player_right=false;

     if (sel_y0==0 && sel_x0==0)
      castle_monk_left=false;
     else if (sel_y0==0 && sel_x0==7)
      castle_monk_right=false;
     else if (sel_y0==7 && sel_x0==0)
      castle_player_left=false;
     else if (sel_y0==7 && sel_x0==7)
      castle_player_right=false;

     if (piece [0]=='6')
     {
      castle_player_left=false;
      castle_player_right=false;
     }
     if (piece [0]=='f')
     {
      castle_monk_left=false;
      castle_monk_right=false;
     }
     if (piece [0]=='6' && abs (sel_x-sel_x0)==2)
     {
      if (sel_x>sel_x0)// reverse
       castle_player_lr=1;
      else
       castle_player_lr=2;

      castle_player_left=false;
      castle_player_right=false;
     }
     else if (piece [0]=='f' && abs (sel_x-sel_x0)==2)// double
     {
      if (sel_x>sel_x0)
       castle_monk_lr=2;
      else
       castle_monk_lr=1;

      castle_monk_left=false;
      castle_monk_right=false;
     }

     if ((piece [0]=='1' || piece [0]=='a') && sel_x!=sel_x0 && init_d [getPos (sel_x, sel_y)]=='0')// take leap pawn
      init_d [getPos (sel_x, sel_y+(piece [0]=='1' ? 1 : -1))]='0';

     if (init_d [getPos (sel_x, sel_y)]!='0')
      drawMove=-1;

     init_d [getPos (sel_x, sel_y)]=piece [0];

     if (state==2 && sel_y1==0 && piece [0]=='1')
     {
      init_d [getPos (sel_x1, sel_y1)]='5';
      sprintf (t, "rev");
      playSound (t);
      sprintf (t, "rev2");
      playSound (t);
     }
     else if (state==5 && sel_y1==7 && piece [0]=='a')
     {
      init_d [getPos (sel_x1, sel_y1)]='e';
      sprintf (t, "rev");
      playSound (t);
      sprintf (t, "revB");
      playSound (t);
     }
     else if (t_snd [0])
      playSound (t_snd);
      
     if (!(sel_x0==sel_x && sel_y0==sel_y))
      init_d [getPos (sel_x0, sel_y0)]='0';

     if ((piece [0]=='6' || piece [0]=='f') && abs (sel_x-sel_x0)==2)
     {
      if (piece [0]!='f')
       piece [0]='4';
      else
       piece [0]='d';
      draw_move [0]=piece [0];
      if (sel_x>sel_x0)
      {
       sel_x0=7;
       sel_x=sel_x-1;
      }
      else
      {
       sel_x0=0;
       sel_x=sel_x+1;
      }
      move_sx=(float)sel_x0;
      move_sy=(float)sel_y0;
     }
     else if (state==2)
     {
      cMove++;
      drawMove++;
      if (draw_move [0]=='1')
       drawMove=0;

      powers ();

      if (drawMove>=drawMoves || drawPieces)
      {
       game_over=3;
       stats_draws++;
       resultAngle=90.0f;
       resultOff=false;
       checkState=0.0f;
       messAfter=false;
       state=10;
      }
      else if (!board3repeat ())
       state=7;

     }
     else if (state==5)
     {
      cMove++;
      drawMove++;
      if (draw_move [0]=='a')
       drawMove=0;
      stats_moves++;
      SetCursor (curArrow);

      powers ();

      if (game_over==0)
      {
       if (drawMove>=drawMoves || drawPieces)
       {
        game_over=3;
        stats_draws++;
        resultAngle=90.0f;
        resultOff=false;
        checkState=0.0f;
        messAfter=false;
        state=10;
       }
       else if (!board3repeat ())
       {
        if (check_check (init_d))
        {
         checkOn=true;
         checkState=255.0f;
         playSound ("check");
        }

        state=0;
       }
      }
      else
      {
       if (game_over==2)
       {
        stats_loses++;
        conf_side=1;
       }
       else
        stats_draws++;
       resultAngle=90.0f;
       resultOff=false;
       checkState=0.0f;
       messAfter=false;
       state=10;
      }

      cellInfo ();
     }
    }
   }

   xr=move_sx;
   yr=move_sy;
   glLoadIdentity ();// Сброс просмотра
   glEnable (GL_BLEND);
   glTranslatef (brdL2+(xr+1)*brdCell-brdCell/2.0f, brdT2-(yr+1)*brdCell+brdCell/2.0f, brdZ);
   glBindTexture (GL_TEXTURE_2D, texture [totx (piece [0])]);

   glBegin (GL_QUADS);
   if (state==2 || state==3 || state==7)
   {
    if (!side)
     glColor3f (colorPlayer [0], colorPlayer [1], colorPlayer [2]);
    else
     glColor3f (colorCPU [0], colorCPU [1], colorCPU [2]);
   }
   else if (state==5 || state==0)
   {
    if (!side)
     glColor3f (colorCPU [0], colorCPU [1], colorCPU [2]);
    else
     glColor3f (colorPlayer [0], colorPlayer [1], colorPlayer [2]);
   }
   glTexCoord2f (0.0f, 0.0f); glVertex3f (-brdCell/(2.0f), -brdCell/2.0f, 0.0f);// Низ лево
   glTexCoord2f (1.0f, 0.0f); glVertex3f (brdCell/(2.0f), -brdCell/2.0f, 0.0f); // Низ право
   glTexCoord2f (1.0f, 1.0f); glVertex3f (brdCell/(2.0f), brdCell/2.0f, 0.0f);  // Верх право
   glTexCoord2f (0.0f, 1.0f); glVertex3f (-brdCell/(2.0f), brdCell/2.0f, 0.0f); // Верх лево
   glEnd ();
   glDisable (GL_BLEND);
  }

  if (checkOn && state<10)
  {
   checkState-=checkStep*fpsTweak ();
   if (checkState<0.0f)
    checkOn=false;
   else
   {
    glLoadIdentity ();// Сброс просмотра

    if (lang==0)
    {
     literaX=-0.34f;
     sprintf (txt, "Шах!");
    }
    else
    {
     literaX=-0.516f;
     sprintf (txt, "Check!");
    }

    literaY=-0.082f;
    literaScale=0.32f;
    sprintf (literaText, "%s", txt);
    glColor4f (colorVol [0], colorVol [1], colorVol [2], checkState/255.0f);
    glPrintLitera ();// Печать текста GL на экран
   }
  }

  if (state==10 || state==12)
  {
   glLoadIdentity ();// Сброс просмотра
   glEnable (GL_BLEND);
   glColor4f(1.0f, 1.0f, 1.0f, 0.0f+(90.0f-resultAngle)*0.65f/90.0f);
   glCallList (infList);
   glDisable (GL_BLEND);

   if (game_over==3)
   {
    if (lang==0)
    {
     literaX=-0.57f;
     sprintf (txt, "Ничья");
    }
    else
    {
     literaX=-0.486f;
     sprintf (txt, "Draw");
    }
   }
   else if (game_over==1)
   {
    if (lang==0)
    {
     literaX=-0.734f;
     sprintf (txt, "Выигрыш");
    }
    else
    {
     literaX=-0.384f;
     sprintf (txt, "Win");
    }
   }
   else
   {
    if (lang==0)
    {
     literaX=-0.834f;
     sprintf (txt, "Проигрыш");
    }
    else
    {
     literaX=-0.477f;
     sprintf (txt, "Lose");
    }
   }

   if (resultAngle>0.0f)
    resultAngle-=fpsTweak ();
   else if (!resultOff)
   {
    resultAngle=0.0f;
    resultOff=true;

    char speech1 [8], speech2 [8], speech [16];

    if (lang==0)
     sprintf (speech1, "ru_");
    else
     sprintf (speech1, "en_");

    if (game_over==1)
     sprintf (speech2, "win");
    else if (game_over==2)
     sprintf (speech2, "lose");
    else
     sprintf (speech2, "draw");

    sprintf (speech, "%s%s", speech1, speech2);
    playSound (speech);

    SetCursor (curNew);

    light_pos=0.65f;
    light_d=1;
 
    state=12;
   }

   literaY=-0.082f;
   literaScale=0.32f;
   sprintf (literaText, "%s", txt);

   if (messAfter)
   {
    GLfloat LightDiffuse []={colorH [0]*1.5f, colorH [1]*1.5f, colorH [2]*0.5f, light_pos*1.5f};// Значения диффузного света
    GLfloat LightPosition []={light_pos, light_pos, -light_pos, 1.0f};// Позиция света
    light_pos+=light_d*0.01f*fpsTweak ();
    if (light_pos>1.0f)
    {
     light_d=-1;
     light_pos=1.0f;
    }
    else if (light_pos<0.0f)
    {
     light_d=1;
     light_pos=0.0f;
    }
    glLightfv (GL_LIGHT1, GL_DIFFUSE, LightDiffuse);  // Установка Диффузного Света
    glLightfv (GL_LIGHT1, GL_POSITION, LightPosition);// Позиция света
    glEnable (GL_LIGHT1); // Разрешение источника света номер один
    glEnable (GL_LIGHTING);// Разрешить освещение

    glColor4f (colorH [0], colorH [1], colorH [2], 1.0f);
    glPrintLitera ();// Печать текста GL на экран
    glDisable (GL_LIGHTING);// Запрет освещения
   }
   else
   {
    checkState+=checkStep*fpsTweak ();
    if (checkState>255.0f)
    {
     checkState=255.0f;
     messAfter=true;
    }
    glColor4f (colorH [0], colorH [1], colorH [2], checkState/255.0f);
    glPrintLitera ();// Печать текста GL на экран
   }
  }


  if (button)
  {
   if (button==1)
   {
    yr=1.0f;
    if (lang==0)
     sprintf (txt, "     сначала");
    else
     sprintf (txt, "     restart");
   }
   else if (button==2)
   {
    yr=2.0f;
    if (lang==0)
     sprintf (txt, "        язык");
    else
     sprintf (txt, "    language");
   }
   else if (button==3)
   {
    yr=3.0f;
    if (lang==0)
     sprintf (txt, "        звук");
    else
     sprintf (txt, "       sound");
   }
   else if (button==4)
   {
    yr=4.0f;
    if (lang==0)
     sprintf (txt, "     мелодия");
    else
     sprintf (txt, "      melody");
   }
   else if (button==5)
   {
    yr=5.0f;
    if (lang==0)
     sprintf (txt, "  достижения");
    else
     sprintf (txt, "achievements");
   }
   else if (button==6)
   {
    yr=6.0f;
    if (lang==0)
     sprintf (txt, " о программе");
    else
     sprintf (txt, "       about");
   }
   else if (button==7)
   {
    yr=7.0f;
    if (lang==0)
     sprintf (txt, "       выход");
    else
     sprintf (txt, "       quit");
   }

   xr=4.0f;
   glLoadIdentity ();// Сброс просмотра
   glEnable (GL_BLEND);
   glColor4f(1.0, 1.0, 1.0, 0.85f);
   glBindTexture (GL_TEXTURE_2D, texture [15]);
   glBegin (GL_QUADS);
   glTexCoord2f (0.0f, 0.0f); glVertex3f (brdL2+xr*brdCell, brdT2-(yr+1)*brdCell, brdZ);    // Низ лево
   glTexCoord2f (1.0f, 0.0f); glVertex3f (brdL2+(xr+4)*brdCell, brdT2-(yr+1)*brdCell, brdZ);// Низ право
   glTexCoord2f (1.0f, 1.0f); glVertex3f (brdL2+(xr+4)*brdCell, brdT2-yr*brdCell, brdZ);    // Верх право
   glTexCoord2f (0.0f, 1.0f); glVertex3f (brdL2+xr*brdCell, brdT2-yr*brdCell, brdZ);        // Верх лево
   glEnd ();
   glDisable (GL_BLEND);

   literaY=brdT2-brdCell/2.0f+0.0095f-brdCell*yr;
   literaX=brdL2+brdCell/2.0f+brdCell*xr;
   literaScale=0.12f;
   sprintf (literaText, "%s", txt);
   glColor3f (colorCellHL1 [0]/1.5f, colorCellHL1 [1]/1.5f, colorCellHL1 [2]/1.5f);
   glPrintLitera ();// Печать текста GL на экран
  }


  if (infOn)
  {
   glLoadIdentity ();// Сброс просмотра
   glEnable (GL_BLEND);
   glColor4f(1.0f, 1.0f, 1.0f, 0.9f);
   glCallList (infList);
   glDisable (GL_BLEND);

   literaScale=0.32f;
   literaY=0.55f;
   if (infOn==1)
   {
    if (lang==0)
    {
     literaX=-0.454f;
     sprintf (literaText, "Monk");
    }
    else
    {
     literaX=-0.434f;
     sprintf (literaText, "Monk");
    }
   }
   else
   {
    if (lang==0)
    {
     literaX=-0.554f;
     sprintf (literaText, "Итоги");
    }
    else
    {
     literaX=-0.734f;
     sprintf (literaText, "Summary");
    }
   }

   glColor3f (colorH [0], colorH [1], colorH [2]);
   glPrintLitera ();// Печать текста GL на экран

   yr=1.75f;

   char infTxt [10] [100];
   if (infOn==1)
   {
    xr=-0.25f;

    if (lang==0)
    {
     char infTxt1 [10] [100]={" Оффлайн версия игрового бота с шахматного",
                              "сервера e2-e4.org. Просчитывает 4 полухода.",
                              "Ходы делаются кликами на фигуры и клетки.",
                              "Если ход возможен, клетка подсвечивается",
                              "зелёным фоном. В правом верхнем углу доски",
                              "отображается сила фигур в процентах.",
                              "Программа распространяется бесплатно.",
                              "Удачной игры!"
                             };
     memcpy (infTxt, infTxt1, 1000);
    }
    else
    {
     char infTxt1 [10] [100]={" Offline version of a game bot from",
                              "e2-e4.org/en/ chess server. Thinks on 4",
                              "moves. Moves are made by clicking on pieces",
                              "and cells. If the move is possible, the",
                              "cell is highlighted with a green color. At",
                              "upper right corner of the board is power",
                              "of pieces in percentage. This program is",
                              "freeware. Lucky playing!"
                             };
     memcpy (infTxt, infTxt1, 1000);
    }
   }
   else
   {
    xr=-0.15f;

    if (lang==0)
    {
     char infTxt1 [10] [100]={"            Партий:",
                              "          Выиграно:",                 
                              "         Проиграно:",
                              "            Вничью:",
                              "    Начато сначала:",
                              "        Недоиграно:",
                              "          Доиграно:",
                              "             Ходов:"
                             };
     memcpy (infTxt, infTxt1, 1000);
    }
    else
    {
     char infTxt1 [10] [100]={"             Total:",
                              "              Wins:",                 
                              "             Loses:",
                              "             Draws:",
                              "         Restarted:",
                              "      Not finished:",
                              "          Finished:",
                              "             Moves:"
                             };
     memcpy (infTxt, infTxt1, 1000);
    }
   }

   glColor3f (colorTxt [0], colorTxt [1], colorTxt [2]);

   for (yi=0; yi<8; yi++)
   {
    literaY=brdT2-brdCell/2.0f-brdCell*(yr+yi*0.5f)-0.0225f;
    literaX=brdL2+brdCell/2.0f+brdCell*xr-0.0025f;
    literaScale=0.07f;
    sprintf (literaText, "%s", infTxt [yi]);
    glPrintLitera ();// Печать текста GL на экран
   }

   if (infOn==2)
   {
    xr=3.25f; yr=1.76f;
    long stats_total=stats_wins+stats_loses+stats_draws+stats_restart+stats_notfin;
    long stats_fin=stats_wins+stats_loses+stats_draws;
    long stats [10]={stats_total, stats_wins, stats_loses, stats_draws, stats_restart, stats_notfin, stats_fin, stats_moves};

    glColor3f (colorVol [0], colorVol [1], colorVol [2]);

    for (yi=0; yi<8; yi++)
    {
     literaY=brdT2-brdCell/2.0f-brdCell*(yr+yi*0.5f)-0.0225f;
     literaX=brdL2+brdCell/2.0f+brdCell*xr-0.0025f;
     literaScale=0.07f;
     sprintf (literaText, "%d", stats [yi]);
     glPrintLitera ();// Печать текста GL на экран
    }
    glColor3f (colorTxt [0], colorTxt [1], colorTxt [2]);
   }

   xr=-0.25f; yr=1.75f;

   if (infOn==1)
   {
    literaY=brdT2-brdCell/2.0f-brdCell*(yr+9*0.5f)-0.0025f;
    literaX=brdL2+brdCell/2.0f+brdCell*xr-0.0025f;
    if (lang==0)
     sprintf (literaText, "                    Маркичев Д. 2020-2022");
    else
     sprintf (literaText, "                  D. Markichev, 2020-2022");
    glColor3f (colorTxtB [0], colorTxtB [1], colorTxtB [2]);
    glPrintLitera ();// Печать текста GL на экран
   }
  }
 }

 fpsC ();
// sprintf (mb, "ok");
// statusBar ();

 glPopMatrix ();
 SwapBuffers (hDC);

 if (state==7)
  state=3;
}

void mouseMove ()
{
 int xi, yi;

 if (blur_on)
  return;

 GetCursorPos (&mypoint);

 if (infOn && mypoint.x>=mXar [0]-(mXar [1]-mXar [0]) && mypoint.x<mXar [8] && mypoint.y>=mYar [0]-(mYar [1]-mYar [0]) && mypoint.y<mYar [8])
 {
  button=0;
  SetCursor (curOff);
  return;
 }

 int field=0, fldX=posX, fldY=posY;
 for (xi=0; xi<9; xi++)
 {
  if (mypoint.x>=mXar [xi] && mypoint.x<mXar [xi+1])
  {
   posX=xi;
   field++;

   break;
  }
 }

 for (yi=0; yi<9; yi++)
 {
  if (mypoint.y>=mYar [yi] && mypoint.y<mYar [yi+1])
  {
   posY=yi;
   field++;
   break;
  }
 }

 if (field<2)
 {
  posX=fldX;
  posY=fldY;
 }

 cellInfo ();

 int bL=button;
 button=0;
 float ri, qi=float(mXar [8]-mXar [7])/25.0f;

 if ((mypoint.x>(mXar [8]+(mXar [8]-mXar [7])/10) && mypoint.x<(mXar [8]+(mXar [8]-mXar [7])*11/10)))
 {
  if (mypoint.y>=mYar [7] && mypoint.y<mYar [8])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [7]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=7;
  }
  if (mypoint.y>=mYar [6] && mypoint.y<mYar [7])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [6]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=6;
  }
  if (mypoint.y>=mYar [5] && mypoint.y<mYar [6])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [5]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=5;
  }
  if (mypoint.y>=mYar [4] && mypoint.y<mYar [5])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [4]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=4;
  }
  if (mypoint.y>=mYar [3] && mypoint.y<mYar [4])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [3]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=3;
  }
  if (mypoint.y>=mYar [2] && mypoint.y<mYar [3])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [2]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=2;
  }
  if (mypoint.y>=mYar [1] && mypoint.y<mYar [2])
  {
   xi=abs ((float)mypoint.x-((float)mXar [8]+float(mXar [8]-mXar [7])*6.0f/10.0f));
   yi=abs ((float)mypoint.y-((float)mYar [1]+float(mYar [8]-mYar [7])*39.0f/40.0f/2.0f));
   ri=sqrt (pow (xi, 2)+pow (yi, 2));
   if (ri<float(mXar [8]-mXar [7])/2.0f-qi)
    button=1;
  }
 }

 if (bL!=button && button!=0)
  playSound ("select");

 if (button!=0)
  SetCursor (curArrow);
 else if (state==10)
  SetCursor (curWait);
 else if (state==12)
  SetCursor (curNew);
 else if (state!=0 && state!=1 && !button)
  SetCursor (curWait);
}

void mouseClick ()
{
 GetCursorPos (&mypoint);

 if (infOn && mypoint.x>=mXar [0]-(mXar [1]-mXar [0]) && mypoint.x<mXar [8] && mypoint.y>=mYar [0]-(mYar [1]-mYar [0]) && mypoint.y<mYar [8])
 {
  infOn=0;
  playSound ("shake");
  mouseMove ();
  return;
 }

 if (!button)
  playerMove ();
 else if (button==1)
  Restart ();
 else if (button==2)
 {
  if (lang==0)
   lang=1;
  else
   lang=0;

  playSound ("turn_on");
 }
 else if (button==3)
 {
  sndVol++;
  if (sndVol>4)
   sndVol=0;

  soundVol=sndVol*250;
  if (sndVol!=0)
  {
   if (sndVol==1)
    soundOn=true;
   playSound ("turn_on");
  }
  else
  {
   soundOn=false;
   playSound ("turn_off", 100, 25);
  }
 }
 else if (button==4)
 {
  melVol++;
  if (melVol>4)
   melVol=0;

  if (melVol==0)
  {
   meloTurnOff=true;
   playSound ("turn_off");
  }
  else if (melVol==1)
   meloTurnOn=true;

  if (melVol>0)
   playSound ("turn_on");

  meloVol=0;
  SetTimer (hWnd, TIMER_MELON, 1000, NULL);
 }
 else if (button==5)
 {
  if (infOn!=2)
  {
   infOn=2;
   playSound ("shake");
  }
  else
  {
   infOn=0;
   playSound ("shake");
  }
 }
 else if (button==6)
 {
  if (infOn!=1)
  {
   infOn=1;
   playSound ("shake");
  }
  else
  {
   infOn=0;
   playSound ("shake");
  }
 }
 else if (button==7)
 {
  if (qC==0)
  {
   qC=1;
   playSound ("turn_on");
   SetTimer (hWnd, TIMER_QUIT, 1000, NULL);
  }
  else
  {
   KillTimer (hWnd, TIMER_QUIT);
   qC=0;
   playSound ("turn_off");
  }
 }
}

int getPos (int x, int y)
{
 int p;

 if (x>-1 && x<8 && y>-1 && y<8)
  p=y*8+x;
 else
  p=0;

 return p;
}

void playerMove ()
{
 if (state>=10)
  Restart ();
 else
 {
  if (state!=0 && state!=1)
  {
   SetCursor (curWait);
   return;
  }

  if (state==0)
  {
   if (posHL==0)
    playSound ("break");

   else if (whose (init_d [getPos (posXl, posYl)])==1)
   {
    sel_x0=posXl;
    sel_y0=posYl;
    piece [0]=init_d [getPos (sel_x0, sel_y0)];
    draw_move [0]=piece [0];
    state=1;

    playSound ("ready");
   }
  }
  else if (state==1)
  {
   if (whose (init_d [getPos (posXl, posYl)])==1)
   {
    if (sel_x0==posXl && sel_y0==posYl)
    {
     state=0;
     playSound ("drop");
    }
    else
    {
     if (posHL==0)
      playSound ("break");
     else
     {
      sel_x0=posXl;
      sel_y0=posYl;
      piece [0]=init_d [getPos (sel_x0, sel_y0)];
      draw_move [0]=piece [0];
      playSound ("ready");
     }
    }
   }
   else if (whose (init_d [getPos (posXl, posYl)])!=1)
   {
    if (check_move (posXl+1, posYl+1))
    {
     move1=true;
     sel_x=posXl;
     sel_y=posYl;
     piece [0]=init_d [getPos (sel_x0, sel_y0)];
     draw_move [0]=piece [0];
     move_sx=(float)sel_x0;
     move_sy=(float)sel_y0;
     leaps_c=-1;
     leaps_n=0;

     leap_x=0;
     leap_y=0;
     if (piece [0]=='1' && abs (sel_y-sel_y0)==2)
     {
      leap_x=sel_x+1;
      leap_y=sel_y+1;
     }

     if (piece [0]=='3')
     {
      leaps_c=1;
      if (abs (sel_x-sel_x0)>abs (sel_y-sel_y0))
      {
       leaps_x1 [0]=sel_x;
       leaps_y1 [0]=sel_y0;
       leaps_x1 [1]=sel_x;
       leaps_y1 [1]=sel_y;
      }
      else
      {
       leaps_x1 [0]=sel_x0;
       leaps_y1 [0]=sel_y;
       leaps_x1 [1]=sel_x;
       leaps_y1 [1]=sel_y;
      }
     }

     stateCPU=0;
     dropCPU=0;
     state=2;
     SetCursor (curWait);
    }
    else
     playSound ("break");
   }
   else if (init_d [getPos (posXl, posYl)]=='a' || init_d [getPos (posXl, posYl)]=='b')
    playSound ("break");
  }
 }
}



void cellInfo ()
{
 int r;
 int tx=posX+1;
 int ty=posY+1;

 posXl=posX;
 posYl=posY;
 posHL=0;

 if (state==0)
 {
  if (whose (init_d [getPos (posXl, posYl)])==1 && check_any (init_d, tx, ty))
   posHL=1;
 }
 else if (state==1)
 {
  if (whose (init_d [getPos (posXl, posYl)])==1 && check_any (init_d, tx, ty))
   posHL=1;
  else if (whose (init_d [getPos (posXl, posYl)])!=1 && check_move (tx, ty))
   posHL=2;
 }
}


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)
 {
  glLoadIdentity ();// Сброс просмотра

  literaY=0.75f;
  literaX=-0.75f;
  literaScale=0.17f;
  glColor3f (1.0f, 0.5f, 0.0f);

  if (strlen (mb)!=0)
  {
   sprintf (literaText, "%s", mb);
   glPrintLitera ();// Печать текста GL на экран

   return;
  }

  sprintf (literaText, "FPS:%d X:%d Y:%d", fps, posX, posY);
  glPrintLitera ();// Печать текста GL на экран
 }
}

void loading ()
{
 bool fileIs=true;
 char url [_MAX_PATH];
 int px, py, dx, dy, bx, by, off=55;

 sprintf (url, "%s\\data\\textures\\sky.jpg", AppDir);

 FILE * file;
 file=fopen (url, "r");
 if (file==NULL)
  fileIs=false;
 fclose (file);

 if (fileIs==true)
 {
  WCHAR ts [256];
  MultiByteToWideChar (CP_ACP, 0, url, -1, ts, 256);
  imagesH=new Gdiplus::Image (ts, true);
  px=imagesH->GetWidth ();
  if (px>0)
  {
   py=px;
   if (cx>cy)
   {
    off=(sqrt (pow (cx, 2)+pow (cy, 2))-cx)*120/100;
    dx=px*cx/(cx+off);
    dy=py*dx/px*cy/cx;
    bx=(px-dx)/2;
    by=(py-dy)/2;
   }
   else
   {
    off=(sqrt (pow (cx, 2)+pow (cy, 2))-cy)*120/100;
    dy=py*cy/(cy+off);
    dx=px*dy/py*cx/cy;
    by=(py-dy)/2;
    bx=(px-dx)/2;
   }
   hDC=GetDC (hWnd);
   gDC=new Gdiplus::Graphics (hDC);
   gDC->SetPageUnit(Gdiplus::UnitPixel);
   gDC->SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
   gDC->SetCompositingQuality(Gdiplus::CompositingQualityAssumeLinear);
   gDC->SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);
   gDC->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
   gDC->SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);

   Gdiplus::RectF bounds(0, 0, cx, cy);
   Gdiplus::ImageAttributes attr;
   attr.SetWrapMode(Gdiplus::WrapModeTile);

   gDC->DrawImage (imagesH, bounds, bx, by, dx, dy, Gdiplus::UnitPixel, &attr);

   DeleteObject (&attr);
   DeleteObject (&bounds);

   ReleaseDC (hWnd, hDC);

   delete imagesH;
  }
 }
}

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

 if (move1 && state<10)
  stats_notfin++;

 if (conf_side!=-1)
  side=conf_side;

 sprintf (conf1, "Sound:%d\r\nMelody:%d\r\nLanguage:%d\r\nSide:%d\r\n",
                  sndVol, melVol, lang, side);
 sprintf (conf2, "Wins:%d\r\nLoses:%d\r\nDraws:%d\r\nRestarted:%d\r\nNotFinished:%d\r\nMoves:%d\r\n",
                  stats_wins, stats_loses, stats_draws, stats_restart, stats_notfin, stats_moves);
 sprintf (conf, "%s\r\n%s", conf1, conf2);
 char path [_MAX_PATH];
 sprintf (path, "%s%s", AppDir, "data\\save.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;
 char conf [1024], par [32], par0 [32], par1 [32];
 memset (conf, 0, confMx);

 char path [_MAX_PATH];
 sprintf (path, "%s%s", AppDir, "data\\save.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"))
   {
    sndVol=atoi (par1);
    soundVol=sndVol*250;
    if (soundVol>1000)
     soundVol=1000;
    if (soundVol<0)
     soundVol=0;
    if (soundVol)
     soundOn=true;
    else
     soundOn=false;
   }
   else if (!strcmp (par0, "Melody"))
   {
    melVol=atoi (par1);
    meloVol=melVol*250;
    if (meloVol>1000)
     meloVol=1000;
    if (meloVol<0)
     meloVol=0;
    if (meloVol)
     meloIs=true;
    else
     meloIs=false;
   }
   else if (!strcmp (par0, "Language"))
   {
    lang=atoi (par1);
    if (lang!=0 && lang!=1)
     lang=0;
   }
   else if (!strcmp (par0, "Side"))
   {
    side=atoi (par1);
    if (side!=0 && side!=1)
     side=0;
   }
   else if (!strcmp (par0, "Wins"))
   {
    stats_wins=atoi (par1);
    if (stats_wins<0)
     stats_wins=0;
   }
   else if (!strcmp (par0, "Loses"))
   {
    stats_loses=atoi (par1);
    if (stats_loses<0)
     stats_loses=0;
   }
   else if (!strcmp (par0, "Draws"))
   {
    stats_draws=atoi (par1);
    if (stats_draws<0)
     stats_draws=0;
   }
   else if (!strcmp (par0, "Restarted"))
   {
    stats_restart=atoi (par1);
    if (stats_restart<0)
     stats_restart=0;
   }
   else if (!strcmp (par0, "NotFinished"))
   {
    stats_notfin=atoi (par1);
    if (stats_notfin<0)
     stats_notfin=0;
   }
   else if (!strcmp (par0, "Moves"))
   {
    stats_moves=atoi (par1);
    if (stats_moves<0)
     stats_moves=0;
   }
  }
 }
}