#include <windows.h>
#include <stdio.h>
#include <ctime>

#include <wingdi.h>
// -lmsimg32

#include <gdiplus/gdiplus.h>
// #pragma comment (lib, "gdiplus.lib")
// -lgdiplus

#include "resource.h"

// Make the class name into a global variable
char szClassName []="WindowsApp";
char title []=" Corners";


void movesQ (); void newGame (bool); void sndMoves ();
int movesQW=0, movesQB=0;
bool side=false, exitx=false, lastMove=false, ng_on=false, gg_on=false, speechless=false, infoSless=false;
int new_gameC, new_gameN=10;
int wp=0, wpl=0;
int rounds=0, wins=0, loses=0, draws=0;
char messMP [256];
COLORREF bGround=RGB (0, 0, 0);

// Declare Windows procedure
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

HWND hwnd, hwndB;// This is the handle for our window
MSG messages;// Here messages to the application are saved
WNDCLASSEX wincl;// Data structure for the windowclass
RECT Rect;

bool loaded=false, moved=false;
float xSize0=540, ySize0=540;
float xSizeLast=xSize0, ySizeLast=ySize0;
float xSize=xSize0, ySize=ySize0;
int xAdd=6, yAdd=25;
int xLeft=0, yTop=0;
int cellSize0=60, cellSizeMin=20, cellSizeMax=250;
int cellSize=cellSize0, mxCellSize;
int mxLparX=0, mxLparY=0;
bool maxSize=false;
bool viewFulloff=false;
bool sizing=false;
bool noPaint=false, resPaint=false;
int gLpar;
bool ctrl_key=false;

const unsigned int TIMER_PAINT=2, TIMER_MOVE=5, TIMER_NG=10, TIMER_EXIT=15, TIMER_RES=25;
int infoS;
int paintOn=0;

int confL=64;
char confPath [_MAX_PATH], AppDir [_MAX_PATH];

COLORREF gBgXY0=RGB (128, 128, 128);
COLORREF gBgXY1=RGB (204, 204, 204);
COLORREF gColor0=RGB (0, 0, 0);
COLORREF gColor1=RGB (255, 255, 255);
COLORREF gColor2=RGB (178, 178, 178);
HPEN gPenXY0=CreatePen (PS_SOLID, 1, gBgXY0);
HBRUSH gBrushXY0=CreateSolidBrush (gBgXY0);
HPEN gPenXY1=CreatePen (PS_SOLID, 1, gBgXY1);
HBRUSH gBrushXY1=CreateSolidBrush (gBgXY1);
HPEN gPen0=CreatePen (PS_SOLID, 1, gColor0);
HBRUSH gBrush0=CreateSolidBrush (gColor0);
HPEN gPen1=CreatePen (PS_SOLID, 1, gColor1);
HBRUSH gBrush1=CreateSolidBrush (gColor1);
HPEN gPen2=CreatePen (PS_SOLID, 1, gColor2);
HBRUSH gBrush2=CreateSolidBrush (gColor2);

int sFont=cellSize/3.5;

HFONT hFont=CreateFont (sFont, 0, 0, 0, FW_EXTRABOLD, false, false, false, DEFAULT_CHARSET, false, false, 5, false, "Courier New");// Arial Verdana Courier Times New Roman MS Sans 
HFONT hFontMess=CreateFont (cellSize/2, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, 5, false, "Courier New");// CLEARTYPE_QUALITY
HFONT hFontMessB=CreateFont (cellSize/1.5, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, 5, false, "Courier New");
HFONT hFontCap=CreateFont (cellSize, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, 4, false, "Courier New");// ANTIALIASED_QUALITY


ULONG_PTR gdiplusToken; 
HINSTANCE gThisInstance;
int gFunsterStil;
bool viewFull=false;
int xoffVF, yoffVF, xLeftVF, yTopVF, xSizeVF, ySizeVF, cellSizeVF;



bool noRest=false;
bool keyClick=false;
bool keyLockF=false;

bool turn=true;
bool game_over=false;
int checkmate_x=0, checkmate_y=0;
int stalemate_x1=0, stalemate_y1=0;
int stalemate_x2=0, stalemate_y2=0;

bool square_white=false, square_black=false;

TRACKMOUSEEVENT tme;
POINT mypoint;
HDC hDC, hCompatibleDC;
PAINTSTRUCT PaintStruct;
HANDLE bg, squareLeftTop, squareRightDown;
BITMAP Bitmap;
static BLENDFUNCTION bfn, bfnSquares;

bool show_imagesL=false;
bool show_image_on=false;

int xoff=3,yoff=22;

int sx=(LONG)::GetSystemMetrics (SM_CXFULLSCREEN);
int sy=(LONG)::GetSystemMetrics (SM_CYFULLSCREEN);
int cx=(LONG)::GetSystemMetrics (SM_CXSCREEN);
int cy=(LONG)::GetSystemMetrics (SM_CYSCREEN);
int wLeft=(int)((sx-(xSize+xAdd))/2);
int wTop=(int)((sy-(ySize+xAdd))/2);

int xy [2],p;

int gx=8,gy=8,lx=8,ly=8;
bool xy_sel_on=false;
int sel_x=0,sel_y=0,sel_x0=0,sel_y0=0;
int leap_x,leap_y;

bool blur_on=false;

bool info_on=false;

int leaps_c=-1;
int leaps_x [100];
int leaps_y [100];

int move_x1, move_y1, move_x2, move_y2;
char move_f;

bool move_hi=false;
bool paint_lt=false, paint_rb=false;

// board
char init_d [64]={
'a','a','a','0','0','0','0','0',
'a','a','a','0','0','0','0','0',
'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','1','1','1',
'0','0','0','0','0','1','1','1',
'0','0','0','0','0','1','1','1'
};

/*
char init_d [64]={
'1','1','1','0','0','0','0','0',
'1','1','1','0','0','0','0','0',
'1','0','1','1','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','a','a','a',
'0','0','0','0','0','a','a','a',
'0','0','0','0','a','0','a','a'
};
*/

char init_p [64]={
'a','a','a','0','0','0','0','0',
'a','a','a','0','0','0','0','0',
'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','1','1','1',
'0','0','0','0','0','1','1','1',
'0','0','0','0','0','1','1','1'
};



#include "wave.h"



void fontChk ()
{
 if (sFont!=int (cellSize/3.5))
 {
  DeleteObject (hFont);
  sFont=cellSize/3.5;
  hFont=CreateFont (sFont, 0, 0, 0, FW_EXTRABOLD, false, false, false, DEFAULT_CHARSET, false, false, 5, false, "Courier New");
  hFontMess=CreateFont (cellSize/2, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, 5, false, "Courier New");
  hFontMessB=CreateFont (cellSize/1.5, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, 5, false, "Courier New");
  hFontCap=CreateFont (cellSize, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, 4, false, "Courier New");
 }
}


// 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 char2num (char c2n, int x, int y)
{
 bool white=false;
 if((y%2&&x%2)||(!(y%2)&&!(x%2)))
  white=true;
 if (c2n=='0')
 {
  if (white==true)
   return 9;
  else
   return 10;
 }
 else if (c2n=='1')
 {
  if (white==true)
   return 5;
  else
   return 6;
 }
 else if (c2n=='a')
 {
  if (white==true)
   return 7;
  else
   return 8;
 }
}


Gdiplus::Image * imagesH [32];
Gdiplus::Image * imageH;

void show_image (int image, int x, int y)
{
 using namespace Gdiplus;

 hDC=GetDC (hwnd);

 if (image>50 && image<56)
 {
  if (wp!=wpl)
  {
   DeleteObject (imageH);

   char t [_MAX_PATH];
   WCHAR ts [_MAX_PATH];
   char imageF [30];
   if (image==51)
    sprintf (imageF, "wallpaper1.jpg");
   else if (image==52)
    sprintf (imageF, "wallpaper2.jpg");
   else if (image==53)
    sprintf (imageF, "wallpaper3.jpg");
   else if (image==54)
    sprintf (imageF, "wallpaper4.jpg");
   else if (image==55)
    sprintf (imageF, "wallpaper5.jpg");

   memset (t, 0, 32);
   sprintf (t, "%s%s%s", AppDir, "data\\images\\", imageF);
   MultiByteToWideChar (CP_ACP, 0, t, -1, ts, _MAX_PATH);
   imageH=new Image (ts, true);
  }

  Graphics * gDC;
  gDC=new Graphics (hDC);
  gDC->SetPageUnit (UnitPixel);
  gDC->SetCompositingMode (CompositingModeSourceCopy);
  gDC->SetCompositingQuality (CompositingQualityAssumeLinear);
  gDC->SetPixelOffsetMode (PixelOffsetModeHighQuality);
  gDC->SetSmoothingMode (SmoothingModeAntiAlias);
  gDC->SetInterpolationMode (InterpolationModeHighQualityBicubic);

  int wpx=imageH->GetWidth (), wpy=imageH->GetHeight (), wpx0, wpy0, wpxoff=0, wpyoff=0;

  wpx0=wpx;
  wpy0=wpy;

  if (xSize+4>wpx || ySize+4>wpy)
  {
   if (xSize+4-wpx>ySize+4-wpy)
   {
    wpy*=float ((xSize+4)/wpx);
    wpx=xSize+4;
   }
   else
   {
    wpx*=float ((ySize+4)/wpy);
    wpy=ySize+4;
   }
  }
  if (xSize+4<wpx)
   wpxoff=(wpx-xSize-4)/2;
  if (ySize+4<wpy)
   wpyoff=(wpy-ySize-4)/2;

  RectF bounds(-wpxoff-2, -wpyoff-2, xSize+4+wpxoff, ySize+4+wpyoff);
  ImageAttributes attr;
  attr.SetWrapMode(WrapModeTileFlipXY);
  gDC->DrawImage (imageH, bounds, 0, 0, wpx0, wpy0, UnitPixel, &attr);

  DeleteObject (&attr);
  DeleteObject (&bounds);
  delete gDC;

  ReleaseDC (hwnd, hDC);

  return;
 }


 if (show_imagesL==false)
 {
  bfn.BlendOp=AC_SRC_OVER;
  bfn.BlendFlags=0;
  bfn.SourceConstantAlpha=210;
  bfn.AlphaFormat=0;// AC_SRC_ALPHA;

  bfnSquares.BlendOp=AC_SRC_OVER;
  bfnSquares.BlendFlags=0;
  bfnSquares.SourceConstantAlpha=175;
  bfnSquares.AlphaFormat=0;

  bg=(HBITMAP)LoadImage (NULL,"data\\images\\bg.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

  squareLeftTop=(HBITMAP)LoadImage (NULL, "data\\images\\slt.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  squareRightDown=(HBITMAP)LoadImage (NULL, "data\\images\\srd.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

  show_imagesL=true;
 }


 if (image==9 || image==10)
 {
  if (image==9)
  {
   SelectObject (hDC, gPen1);
   SelectObject (hDC, gBrush1);
  }
  else
  {
   SelectObject (hDC, gPen2);
   SelectObject (hDC, gBrush2);
  }
  Rectangle (hDC, xLeft+x*cellSize, yTop+y*cellSize, xLeft+(x+1)*cellSize, yTop+(y+1)*cellSize);

  ReleaseDC (hwnd, hDC);

  return;
 }


 if(show_image_on==false)
 {
  int i;
  char t [_MAX_PATH];
  WCHAR ts [_MAX_PATH];;
  char imagesF [30] [24]={
   "logo.gif", "wait0.gif", "wait1.gif", "wait2.gif", "wait3.gif",
   "wfw.gif", "wfb.gif", "bfw.gif", "bfb.gif", "", "", "border.gif", "bordertop.gif", "bordlight.gif", "bordlighttop.gif"
  };

  for (i=0; i<15; i++)
  {
   if (imagesF [i] [0]!=' ')
   {
    memset (t, 0, 32);
    sprintf (t, "%s%s%s", AppDir, "data\\images\\", imagesF [i]);
    MultiByteToWideChar (CP_ACP, 0, t, -1, ts, _MAX_PATH);
    imagesH [i]=new Image (ts, true);
   }
  }

  show_image_on=true;
 }

 Graphics * gDC=new Graphics (hDC);
 gDC->SetPageUnit (UnitPixel);
 gDC->SetCompositingMode (CompositingModeSourceCopy);
 gDC->SetCompositingQuality (CompositingQualityAssumeLinear);// CompositingQualityDefault
 gDC->SetPixelOffsetMode (PixelOffsetModeHighQuality);// PixelOffsetModeDefault
 gDC->SetSmoothingMode (SmoothingModeAntiAlias);
 gDC->SetInterpolationMode (InterpolationModeHighQualityBicubic);// InterpolationModeNearestNeighbor

 if (side)
 {
  if (image==5)
   image=7;
  else if (image==6)
   image=8;
  else if (image==7)
   image=5;
  else if (image==8)
   image=6;
 }


 RectF bounds(xLeft+x*cellSize, yTop+y*cellSize, cellSize, cellSize);
 ImageAttributes attr;
 attr.SetWrapMode (WrapModeTileFlipXY);
 gDC->DrawImage (imagesH [image], bounds, 0, 0, cellSize0, cellSize0, UnitPixel, &attr);
 DeleteObject (&attr);
 DeleteObject (&bounds);
 delete gDC;

 ReleaseDC (hwnd, hDC);
}


// http://www.kachkarvv.ru/src-cplus/dev-c-bmp-save.php
HBITMAP hbm;
HBITMAP Create_hBitmap (HDC hThisDC, int w, int h)
{
 HDC hDCmem;       
 HBITMAP hbm,holdBM;
 hDCmem=CreateCompatibleDC(hThisDC);
 hbm=CreateCompatibleBitmap(hThisDC,w,h);
 holdBM=(HBITMAP)SelectObject(hDCmem,hbm);
 BitBlt(hDCmem, 0,0, w, h, hDC, 0,0, SRCCOPY);
 SelectObject(hDCmem,holdBM);
 DeleteDC(hDCmem);
 DeleteObject(holdBM);
 return hbm;
}

HBITMAP CreateClientWindowBitmap (HWND hWND)
{
 RECT r; 
 GetClientRect(hWND,&r);

 return(Create_hBitmap(GetDC(hWND),r.right,r.bottom)); 
}



void show_info ()
{
 if (info_on==false)
 {
  if (soundOn && !infoSless)
   playWave ("info_on");

  info_on=true;

  float yCells;
  char header []="Corners";
  char footer []="2011, 2014-17 / Маркичевы Д.И., Н.И.";

  hDC=GetDC (hwnd);
  hbm=CreateClientWindowBitmap (hwnd);

  hCompatibleDC=CreateCompatibleDC (hDC);
  SelectObject (hCompatibleDC, bg);

  // Check AlphaBlend in "wingdi.h"
  AlphaBlend (hDC, xLeft, yTop, cellSize*9, cellSize*9, hCompatibleDC, 0, 0, 90, 90, bfn);// cellSize0, cellSize0

  char text [16] [32]={
   "NumPad, Пробел, Enter", "Курсор", 
   "Ctrl + R", "Сначала", 
   "Ctrl + Плюс, Минус, 0", "Размер окна", 
   "F", "На весь экран", 
   "1-0", "Фон", 
   "S", "Звук", 
   "ESC", "Выход"
  };

  int textS;
  textS=7;

  if (game_over)
  {
   sprintf (text [0], "Партий");
   sprintf (text [1], "%d", rounds);
   sprintf (text [2], "Выиграно");
   sprintf (text [3], "%d", wins);
   sprintf (text [4], "Проиграно");
   sprintf (text [5], "%d", loses);
   sprintf (text [6], "Вничью");
   sprintf (text [7], "%d", draws);
   sprintf (text [8], "");
   sprintf (text [9], "");
   sprintf (text [10], "Клик по доске");
   sprintf (text [11], "Продолжение");
   sprintf (text [12], "ESC");
   sprintf (text [13], "Выход");

   textS=7;
  }

  fontChk ();

  SetBkMode (hDC, 0);

  SelectObject (hDC, hFontCap);

  SetTextColor (hDC, RGB (175, 100, 0));
  int border=1;
  int iX=-border, iY=0;
  for (int i2=0; i2<5; i2++)
  {
   if (i2==1)
    iX=border;
   else if (i2==2)
   {
    iX=0;
    iY=-border;
   }
   else if (i2==3)
    iY=border;
   else if (i2==4)
   {
    SetTextColor (hDC, RGB (242, 170, 25));
    iX=0;
    iY=0;
   }

   yCells=2;
   SetRect (&Rect, xLeft+(1)*cellSize+iX, yTop+yCells*cellSize+iY, xLeft+(9)*cellSize+iX, yTop+(yCells+0.75)*cellSize+iY);
   DrawText (hDC, header, strlen (header), &Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  }

  SelectObject (hDC, hFont);
  SetTextColor (hDC, RGB (242, 170, 25));

  yCells=3.3;

  for (int i=0; i<textS; i++)
  {
   SetRect (&Rect, xLeft+(1)*cellSize, yTop+yCells*cellSize+i*cellSize/2, xLeft+(4.82)*cellSize, yTop+(yCells+0.75)*cellSize+i*cellSize/2);
   DrawText (hDC, text [i*2], strlen (text [i*2]), &Rect, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
  }

  SetTextColor (hDC, RGB (150, 150, 150));

  for (int i=0; i<textS; i++)
  {
   if (strlen (text [i*2])>0)
   {
    SetRect (&Rect, xLeft+(4.82)*cellSize, yTop+yCells*cellSize+i*cellSize/2, xLeft+(5.18)*cellSize, yTop+(yCells+0.75)*cellSize+i*cellSize/2);
    DrawText (hDC, "-", 1, &Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
   }
  }

  SetTextColor (hDC, RGB (255, 255, 255));

  for (int i=0; i<textS; i++)
  {
   SetRect (&Rect, xLeft+(5.18)*cellSize, yTop+yCells*cellSize+i*cellSize/2, xLeft+(9)*cellSize, yTop+(yCells+0.75)*cellSize+i*cellSize/2);
   DrawText (hDC, text [i*2+1], strlen (text [i*2+1]), &Rect, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOPREFIX);
  }

  SetTextColor (hDC, RGB (250, 250, 250));
  SetRect (&Rect, xLeft+(1)*cellSize, yTop+8*cellSize, xLeft+(9)*cellSize, yTop+(9)*cellSize);
  DrawText (hDC, footer, strlen (footer), &Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);

  DeleteDC (hCompatibleDC);
  ReleaseDC (hwnd, hDC);
 }
}

void info_clear ()
{
 hDC=GetDC (hwnd);
 hCompatibleDC=CreateCompatibleDC (hDC);
 SelectObject (hCompatibleDC, hbm);
 StretchBlt (hDC, 0, 0, xSize, ySize, hCompatibleDC, 0, 0, xSize, ySize, SRCCOPY);
 DeleteObject (hbm);
 ReleaseDC (hwnd, hDC);

 info_on=false;
}

void show_8x8 (bool on, int x, int y)
{
 if (!on)
 {
  if (y==0)
   show_image (12, x, y);
  else
   show_image (11, x, y);
 }
 else
 {
  if (y==0)
   show_image (14, x, y);
  else
   show_image (13, x, y);
 }

 hDC=GetDC (hwnd);

 char x8 [8]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
 char y8 [8]={'8', '7', '6', '5', '4', '3', '2', '1'};
 char txt [1];
 if (y==0)
  txt [0]=x8 [x-1];
 else
  txt [0]=y8 [y-1];

 fontChk ();

 SelectObject (hDC, hFont);

 SetBkMode (hDC, 0);

 if (y==0 || on==true)
 {
  if (y==0)
  {
   if (on==true)
    SetTextColor (hDC, RGB (10, 10, 10));
   else
    SetTextColor (hDC, RGB (0, 0, 255));
  }
  else
   SetTextColor (hDC, gColor0);
 }
 else
  SetTextColor (hDC, gColor1);

 SetRect (&Rect, xLeft+x*cellSize, yTop+y*cellSize, xLeft+(x+1)*cellSize, yTop+(y+1)*cellSize);
 DrawText (hDC, txt, 1, &Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);

 ReleaseDC (hwnd, hDC);
}

void x_hi (int x, bool on)
{
 if (on==true)
  show_8x8 (true, x, 0);
 else
  show_8x8 (false, x, 0);
}
void y_hi (int y, bool on)
{
 if (on==true)
  show_8x8 (true, 0, y);
 else
  show_8x8 (false, 0, y);
}

bool refresh=false;
void cls (int x1, int y1, int x2, int y2)
{
 if (refresh)
 {
  refresh=false;
  return;
 }

 hDC=GetDC (hwnd);

 HBRUSH hPenOld;
 HBRUSH hLinePen;
 COLORREF qLineColor;

 qLineColor=RGB (0, 0, 0);
 hLinePen=CreateSolidBrush (qLineColor);
 hPenOld=(HBRUSH)SelectObject (hDC, hLinePen);

 Rectangle(hDC, x1-2, y1-2, x2+2, y2+2);
   
 SelectObject (hDC, hPenOld);
 DeleteObject (hLinePen);

 ReleaseDC (hwnd, hDC);
}

void square (int x1, int y1, int x2, int y2, int on)
{
 hDC=GetDC (hwnd);

 HPEN hPenOld;
 HPEN hLinePen;
 COLORREF qLineColor;

 if (on==1)
  qLineColor=RGB (0, 118, 0);// dark green
 else if (on==2)
  qLineColor=RGB (255, 0, 0);// dark red

 hLinePen=CreatePen (PS_SOLID, 1, qLineColor);
 hPenOld=(HPEN)SelectObject (hDC, hLinePen);

 MoveToEx(hDC, xLeft+x1*cellSize, yTop+y1*cellSize, NULL);
 LineTo(hDC, xLeft+(x2+1)*cellSize-1, yTop+y1*cellSize);
 LineTo(hDC, xLeft+(x2+1)*cellSize-1, yTop+(y2+1)*cellSize-1);
 LineTo(hDC, xLeft+x1*cellSize, yTop+(y2+1)*cellSize-1);
 LineTo(hDC, xLeft+x1*cellSize, yTop+y1*cellSize);

 MoveToEx(hDC, xLeft+x1*cellSize+1, yTop+y1*cellSize+1, NULL);
 LineTo(hDC, xLeft+(x2+1)*cellSize-2, yTop+y1*cellSize+1);
 LineTo(hDC, xLeft+(x2+1)*cellSize-2, yTop+(y2+1)*cellSize-2);
 LineTo(hDC, xLeft+x1*cellSize+1, yTop+(y2+1)*cellSize-2);
 LineTo(hDC, xLeft+x1*cellSize+1, yTop+y1*cellSize+1);
   
 SelectObject (hDC, hPenOld);
 DeleteObject (hLinePen);

 ReleaseDC (hwnd, hDC);
}

void xy_hi (int x, int y, int on)
{
 if (game_over==true || exitx==true)
  return;

 if (square_white==true && (x<4 && y<4))
  return;

 if (square_black==true && (x>5 && y>5))
  return;

 if (x==0 || y==0)
  return;

 HPEN hPenOld;
 HPEN hLinePen;
 COLORREF qLineColor;

 hDC=GetDC (hwnd);

 if (on==0)
 {
  if((y%2&&x%2)||(!(y%2)&&!(x%2)))
   qLineColor=RGB (255, 255, 255);// blank
  else
   qLineColor=RGB (178, 178, 178);// blank
 }
 else if (on==1)
  qLineColor=RGB (118, 118, 118);// gray
 else if (on==2)
  qLineColor=RGB (0, 118, 0);// dark green
 else if (on==3)
  qLineColor=RGB (255, 0, 0);// dark red
 else if (on==4)
  qLineColor=RGB (0, 255, 0);// light green
 else if (on==5)
  qLineColor=RGB (255, 118, 118);// light red

 hLinePen=CreatePen (PS_SOLID, 1, qLineColor);
 SelectObject (hDC, hLinePen);

 MoveToEx(hDC, xLeft+x*cellSize, yTop+y*cellSize, NULL);
 LineTo(hDC, xLeft+(x+1)*cellSize-1, yTop+y*cellSize);
 LineTo(hDC, xLeft+(x+1)*cellSize-1, yTop+(y+1)*cellSize-1);
 LineTo(hDC, xLeft+x*cellSize, yTop+(y+1)*cellSize-1);
 LineTo(hDC, xLeft+x*cellSize, yTop+y*cellSize);

 if (cellSize>=cellSize0/3*2)
 {
  MoveToEx(hDC, xLeft+x*cellSize+1, yTop+y*cellSize+1, NULL);
  LineTo(hDC, xLeft+(x+1)*cellSize-2, yTop+y*cellSize+1);
  LineTo(hDC, xLeft+(x+1)*cellSize-2, yTop+(y+1)*cellSize-2);
  LineTo(hDC, xLeft+x*cellSize+1, yTop+(y+1)*cellSize-2);
  LineTo(hDC, xLeft+x*cellSize+1, yTop+y*cellSize+1);
 }

 if (cellSize>=cellSize0/2*3)
 {
  MoveToEx(hDC, xLeft+x*cellSize+2, yTop+y*cellSize+2, NULL);
  LineTo(hDC, xLeft+(x+1)*cellSize-3, yTop+y*cellSize+2);
  LineTo(hDC, xLeft+(x+1)*cellSize-3, yTop+(y+1)*cellSize-3);
  LineTo(hDC, xLeft+x*cellSize+2, yTop+(y+1)*cellSize-3);
  LineTo(hDC, xLeft+x*cellSize+2, yTop+y*cellSize+2);
 }   

 DeleteObject (hLinePen);

 ReleaseDC (hwnd, hDC);
}

void leaps_hi (int on)// 0-clear, 1-me, 2-pc
{
 int i;

 for (i=1; i<leaps_c; i++)
 {
  if (on==0)
   xy_hi (leaps_x [i], leaps_y [i], 0);
  else if (on==1)
   xy_hi (leaps_x [i], leaps_y [i], 4);
  else
   xy_hi (leaps_x [i], leaps_y [i], 5);
 }
}

void leaps (int x1, int y1, int x2, int y2)
{
 char d2 [64];
 int i, c, n=0, tx1, ty1;
 int ar_x [100], ar_y [100], ar_parent [100];

 memcpy (d2, init_d, 64);

 c=0;
 ar_x [c]=x1;
 ar_y [c]=y1;
 d2 [get_p (x1, y1)]='2';
 d2 [get_p (x2, y2)]='0';

 for (i=0; i<=c; i++)
 {
  tx1=ar_x [i];
  ty1=ar_y [i];

  if (tx1<7)
  {
   if ( (d2 [get_p (tx1+1, ty1)]=='1' || d2 [get_p (tx1+1, ty1)]=='a') && d2 [get_p (tx1+2, ty1)]=='0' )
   {
    c++;
    ar_x [c]=tx1+2;
    ar_y [c]=ty1;
    ar_parent [c]=i;
    d2 [get_p (tx1+2, ty1)]='2';
    if ( (tx1+2)==x2 && ty1==y2 )
    {
     n=c;
     break;
    }
   }
  }
  if (tx1>2)
  {
   if ( (d2 [get_p (tx1-1, ty1)]=='1' || d2 [get_p (tx1-1, ty1)]=='a') && d2 [get_p (tx1-2, ty1)]=='0' )
   {
    c++;
    ar_x [c]=tx1-2;
    ar_y [c]=ty1;
    ar_parent [c]=i;
    d2 [get_p (tx1-2, ty1)]='2';
    if ( (tx1-2)==x2 && ty1==y2 )
    {
     n=c;
     break;
    }
   }
  }
  if (ty1<7)
  {
   if ( (d2 [get_p (tx1, ty1+1)]=='1' || d2 [get_p (tx1, ty1+1)]=='a') && d2 [get_p (tx1, ty1+2)]=='0' )
   {
    c++;
    ar_x [c]=tx1;
    ar_y [c]=ty1+2;
    ar_parent [c]=i;
    d2 [get_p (tx1, ty1+2)]='2';
    if ( tx1==x2 && (ty1+2)==y2 )
    {
     n=c;
     break;
    }
   }
  }
  if (ty1>2)
  {
   if ( (d2 [get_p (tx1, ty1-1)]=='1' || d2 [get_p (tx1, ty1-1)]=='a') && d2 [get_p (tx1, ty1-2)]=='0' )
   {
    c++;
    ar_x [c]=tx1;
    ar_y [c]=ty1-2;
    ar_parent [c]=i;
    d2 [get_p (tx1, ty1-2)]='2';
    if ( tx1==x2 && (ty1-2)==y2 )
    {
     n=c;
     break;
    }
   }
  }
 }

 if (n!=0)
 {
  leaps_c=-1;
  for (i=c; i>=0; i--)
  {
   if (i==n)
   {
    leaps_c++;
    leaps_x [leaps_c]=ar_x [i];
    leaps_y [leaps_c]=ar_y [i];
    n=ar_parent [i];
   }
  }
 }
}

void xy_sel (int x, int y)
{
 hDC=GetDC (hwnd);

 int i;

 HPEN hPenOld;

 HPEN hLinePen;
 COLORREF qLineColor;

 if((y%2&&x%2)||(!(y%2)&&!(x%2)))
  qLineColor=RGB (255, 255, 255);
 else
  qLineColor=RGB (178, 178, 178);

 hLinePen=CreatePen (PS_SOLID, 1, qLineColor);
 hPenOld=(HPEN)SelectObject (hDC, hLinePen);

 for (i=2; i<cellSize-2; i=i+2)
 {
  MoveToEx(hDC, xLeft+x*cellSize+2, yTop+y*cellSize+i, NULL);
  LineTo(hDC, xLeft+(x+1)*cellSize-2, yTop+y*cellSize+i);
 }

 SelectObject (hDC, hPenOld);
 DeleteObject (hLinePen);

 ReleaseDC (hwnd, hDC);
}


void messPrint (HFONT hFontMessMP, float yCells, int Rgb, int rGb, int rgB, int Rgb2, int rGb2, int rgB2)
{
 hDC=GetDC (hwnd);

 char mess [256];
 sprintf (mess, "%s", messMP);

 SetBkMode (hDC, 0);
 SelectObject (hDC, hFontMessMP);

 SetTextColor (hDC, RGB (Rgb2, rGb2, rgB2));

 int border=1;
 int iX=-border, iY=0;
 for (int i2=0; i2<5; i2++)
 {
  if (i2==1)
   iX=border;
  else if (i2==2)
  {
   iX=0;
   iY=-border;
  }
  else if (i2==3)
   iY=border;
  else if (i2==4)
  {
   SetTextColor (hDC, RGB (Rgb, rGb, rgB));
   iX=0;
   iY=0;
  }

  SetRect (&Rect, xLeft+(1)*cellSize+iX, yTop+yCells*cellSize+iY, xLeft+(9)*cellSize+iX, yTop+(yCells+0.75)*cellSize+iY);

  DrawText (hDC, mess, strlen (mess), &Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
 }

 ReleaseDC (hwnd, hDC);
}

void game_goes ()
{
 gg_on=true;

 sprintf (messMP, "Игра продолжается...");
 messPrint (hFontMess, 5.5, 242, 170, 25, 175, 150, 0);
}

bool stats=false;
void movesQ ()
{
 int movesQS=movesQW;// +movesQB;

 memset (messMP, 0, 256);

 int movesQSn=movesQS;
 while (movesQSn>10)
  movesQSn-=10;

 if (movesQSn==1)
  sprintf (messMP, "%d ход", movesQS);
 else if (movesQSn>1 && movesQSn<5)
  sprintf (messMP, "%d хода", movesQS);
 else
  sprintf (messMP, "%d ходов", movesQS);

 messPrint (hFontMess, 3.5, 242, 170, 25, 175, 150, 0);

 bool whiteGame=false, blackGame=false;
 if (square_white==true || (square_black==true && side))
  whiteGame=true;
 if (square_black==true || (square_white==true && side))
  blackGame=true;

 if (square_white==true && square_black==false)
 {
  sprintf (messMP, "Выигрыш!!!");
  messPrint (hFontMessB, 4.5, 218, 0, 1, 244, 201, 10);

  if (soundOn && speechless==false)
   playWave ("speech_win");

  if (stats==false)
   wins++;

  side=false;
 }
 else if (square_white==false && square_black==true)
 {
  sprintf (messMP, "Проигрыш");
  messPrint (hFontMessB, 4.5, 10, 10, 10, 150, 150, 150); 

  if (soundOn && speechless==false)
   playWave ("speech_loose");

  if (stats==false)
   loses++;

  side=true;
 }
 else
 {
  sprintf (messMP, "Ничья!");
  messPrint (hFontMessB, 4.5, 35, 201, 10, 133, 61, 255); 

  if (soundOn && speechless==false)
   playWave ("speech_draw");

  if (stats==false)
   draws++;
 }

 speechless=true;

 if (stats==false)
 {
  rounds++;
  stats=true;
 }
}

void check_end ()
{
 if (square_white==true || square_black==true)
 {
  if (!lastMove)
  {
   game_over=true;
   x_hi (lx, false);
   y_hi (ly, false);
   movesQ ();
  }
 }
}

void square2 ()
{
 if (!side)
 {
  if (square_white==true && !paint_lt)
  {
   square (1, 1, 3, 3, 1);

   hDC=GetDC (hwnd);
   hCompatibleDC=CreateCompatibleDC (hDC);
   squareLeftTop=(HBITMAP)LoadImage (NULL, "data\\images\\slt.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);// ?
   SelectObject (hCompatibleDC, squareLeftTop);//
   AlphaBlend (hDC, xLeft+cellSize, yTop+cellSize, cellSize*3, cellSize*3, hCompatibleDC, 0, 0, 90, 90, bfnSquares);
   ReleaseDC (hwnd, hDC);

   paint_lt=true;
  }
 
  if (square_black==true && !paint_rb)
  {
   square (6, 6, 8, 8, 2);

   hDC=GetDC (hwnd);
   hCompatibleDC=CreateCompatibleDC (hDC);
   squareRightDown=(HBITMAP)LoadImage (NULL, "data\\images\\srd.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);// ?
   SelectObject (hCompatibleDC, squareRightDown);
   AlphaBlend (hDC, xLeft+cellSize*6, yTop+cellSize*6, cellSize*3, cellSize*3, hCompatibleDC, 0, 0, 90, 90, bfnSquares);
   ReleaseDC (hwnd, hDC);

   paint_rb=true;
  }
 }
 else
 {
  if (square_white==true && !paint_lt)
  {
   square (1, 1, 3, 3, 1);

   hDC=GetDC (hwnd);
   hCompatibleDC=CreateCompatibleDC (hDC);
   squareLeftTop=(HBITMAP)LoadImage (NULL, "data\\images\\srd.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);// ?
   SelectObject (hCompatibleDC, squareLeftTop);//
   AlphaBlend (hDC, xLeft+cellSize, yTop+cellSize, cellSize*3, cellSize*3, hCompatibleDC, 0, 0, 90, 90, bfnSquares);
   ReleaseDC (hwnd, hDC);

   paint_lt=true;
  }
 
  if (square_black==true && !paint_rb)
  {
   square (6, 6, 8, 8, 2);

   hDC=GetDC (hwnd);
   hCompatibleDC=CreateCompatibleDC (hDC);
   squareRightDown=(HBITMAP)LoadImage (NULL, "data\\images\\slt.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);// ?
   SelectObject (hCompatibleDC, squareRightDown);
   AlphaBlend (hDC, xLeft+cellSize*6, yTop+cellSize*6, cellSize*3, cellSize*3, hCompatibleDC, 0, 0, 90, 90, bfnSquares);
   ReleaseDC (hwnd, hDC);

   paint_rb=true;
  }
 }
}

void save_conf()
{
 FILE *file;
 int i, twx, twy, tcs, tmx, tsn, tvf, tsd=0;
 char conf [confL];

 twx=wLeft;
 twy=wTop;

 if (maxSize==true)
 {
  tcs=mxCellSize;
  tmx=1;
 }
 else
 {
  tcs=cellSize;
  tmx=0;
 }

 if (soundOn==true)
  tsn=1;
 else
  tsn=0;

 if (viewFull==true)
 {
  if (maxSize==false)
   tcs=cellSizeVF;
  tvf=1;
 }
 else
  tvf=0;

 if (side)
  tsd=1;

 sprintf (conf, "%d:%d:%d:%d:%d:%d:%d:%d...............................................................", twx, twy, tcs, tmx, tsn, tvf, tsd, wp);

 file=fopen (confPath, "w");
 if (file)
 {
  for (i=0; i<confL; i++)
   fputc (conf[i], file);
  fclose (file);
 }
}

char try_d [500] [64];
char try_d2 [10000] [64];
char try_d3 [150000] [64];

int try_p2 [50000];
int try_p3 [150000];

int try_b [500];
int try_b2 [10000];
int try_b3 [150000];

int try_b_s2 [500];
int try_b_s3 [10000];
int try_b_s4 [150000];

int try_i, try_i2, try_i3, 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 fine=false;
int do_move (char d [64], int x1, int y1, int x2, int y2, int take)
{
 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;

  if (v=='0')
  {
   r=(x1-x2)*2+(y1-y2)*2+50;

   if ((x1-x2)+(y1-y2)>0 && !(x1<=3 && y1<=3))
    r+=(x1+y1);

   if (x2>5 || y2>5)
    r+=abs (y1-x1)-abs (y2-x2);

   if ((x1>5 && y1>5) && (x2<6 || y2<6))
    r+=5;
   else if ((x1<6 || y1<6) && (x2>5 && y2>5))
    r-=5;
   else if ((x1>3 || y1>3) && (x2<4 && y2<4))
   {
    r+=5;
    if (fine==true)
    {
     if (try_s==0)
      r+=15;
     else if (try_s==3)
      r+=10;
    }
   }
   else if ((x1<4 && y1<4) && (x2>3 || y2>3))
    r-=25;
  }

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

   if (try_s==0)
   {
    memcpy (try_d [try_i], d2, 64);
    try_b [try_i]=r;
    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
   return 0;
 }
 else
  return 0;
}

void try_move (char d [64], int x1, int y1)
{
 char d2 [64];
 memcpy (d2, d, 64);
 d2 [get_p (x1, y1)]='3';

 char f=d2 [get_p (x1, y1)];
 int x2, y2, i, i2, r;

 int tx1, ty1, tx2, ty2;

 bool start=true, loop=true, out;

 int yi, xi;

 while (loop==true)
 {
  out=false;
  for (yi=1; yi<9; yi++)
  {
   for (xi=1; xi<9; xi++)
   {
    if (d2 [get_p (xi, yi)]=='3')
    {
     d2 [get_p (xi, yi)]='2';
     tx1=xi;
     ty1=yi;
     out=true;
    }
    if (out==true)
     break;
   }
   if (out==true)
    break;
  }

  if (out==true)
  {
   if (ty1>2)
   {
    if (d2 [get_p (tx1, ty1-1)]=='1' || d2 [get_p (tx1, ty1-1)]=='a')
    {
     if (d2 [get_p (tx1, ty1-2)]=='0')
     {
      do_move (d, x1, y1, tx1, ty1-2, 0);
      d2 [get_p (tx1, ty1-2)]='3';
     }
    }
    else if (start==true)
     do_move (d, x1, y1, tx1, ty1-1, 0);
   }
   else if (ty1>1 && start==true)
    do_move (d, x1, y1, tx1, ty1-1, 0);

   if (ty1<7)
   {
    if (d2 [get_p (tx1, ty1+1)]=='1' || d2 [get_p (tx1, ty1+1)]=='a')
    {
     if (d2 [get_p (tx1, ty1+2)]=='0')
     {
      do_move (d, x1, y1, tx1, ty1+2, 0);
      d2 [get_p (tx1, ty1+2)]='3';
     }
    }
    else if (start==true)
     do_move (d, x1, y1, tx1, ty1+1, 0);
   }
   else if (ty1<8 && start==true)
    do_move (d, x1, y1, tx1, ty1+1, 0);


   if (tx1>2)
   {
    if (d2 [get_p (tx1-1, ty1)]=='1' || d2 [get_p (tx1-1, ty1)]=='a')
    {
     if (d2 [get_p (tx1-2, ty1)]=='0')
     {
      do_move (d, x1, y1, tx1-2, ty1, 0);
      d2 [get_p (tx1-2, ty1)]='3';
     }
    }
    else if (start==true)
     do_move (d, x1, y1, tx1-1, ty1, 0);
   }
   else if (tx1>1 && start==true)
    do_move (d, x1, y1, tx1-1, ty1, 0);

   if (tx1<7)
   {
    if (d2 [get_p (tx1+1, ty1)]=='1' || d2 [get_p (tx1+1, ty1)]=='a')
    {
     if (d2 [get_p (tx1+2, ty1)]=='0')
     {
      do_move (d, x1, y1, tx1+2, ty1, 0);
      d2 [get_p (tx1+2, ty1)]='3';
     }
    }
    else if (start==true)
     do_move (d, x1, y1, tx1+1, ty1, 0);
   }
   else if (tx1<8 && start==true)
    do_move (d, x1, y1, tx1+1, ty1, 0);


   start=false;
  }
  else
   loop=false;
 }
}

bool check_move ()
{
 try_i=0;
 try_s=0;

 try_move (init_d, sel_x, sel_y);
 int i;
 char d2 [64];
 memcpy (d2, init_d, 64);
 d2 [get_p (gx, gy)]=d2 [get_p (sel_x, sel_y)];
 d2 [get_p (sel_x, sel_y)]='0';

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

 return false;
}

void 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]=='a')
   d [63-i]='1';
 }
}

bool check_corner (char d2 [64])
{
 int yi, xi, c=0;
 bool white=false, black=false;

 for (yi=1; yi<4; yi++)
 {
  for (xi=1; xi<4; xi++)
  {
   if (d2 [get_p (xi, yi)]!='0')
   {
    if (d2 [get_p (xi, yi)]=='1')
     white=true;
    c++;
   }
  }
 }

 if (white==true && c==9)
 {
  xy_hi (sel_x0, sel_y0, 0);
  xy_hi (sel_x, sel_y, 0);
  leaps_hi (0);
  leaps_c=0;

  square_white=true;
  square2 ();
 }

 c=0;
 for (yi=6; yi<9; yi++)
 {
  for (xi=6; xi<9; xi++)
  {
   if (d2 [get_p (xi, yi)]!='0')
   {
    if (d2 [get_p (xi, yi)]=='a')
     black=true;
    c++;
   }
  }
 }

 if (black==true && c==9)
 {
  xy_hi (move_x1, move_y1, 0);
  xy_hi (move_x2, move_y2, 0);
  move_x1=0; move_y1=0; move_x2=0; move_y2=0;
  leaps_hi (0);
  leaps_c=0;

  square_black=true;
  square2 ();
 }

 if (square_white || square_black)
  return true;
 else
  return false;
}

void pc ()
{
 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;
 int break_x=0, break_y=0;

 memcpy (d, init_d, 64);

 bool own=false;
 int c=0;
 for (y=6; y<9; y++)
 {
  for (x=6; x<9; x++)
  {
   if (d [get_p (x, y)]!='0')
   {
    if (d [get_p (x, y)]=='a')
     own=true;
    c++;
   }
  }
 }
 if (own==true && c>7)
  fine=true;

 flip_board (d);

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

 for (y=1; y<9; y++)
 {
  for (x=1; x<9; x++)
  {
   t=d [i];
   if (t=='1')
    try_move (d, x, y);

   i++;
  }
 }

 show_image (1, 0, 0);

 try_i2=0;
 try_s=2;

 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')
     try_move (d2, x, y);
    i++;
   }
  }
 }

 try_i3=0;
 try_s=3;

 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')
     try_move (d2, x, y);
    i++;
   }
  }
 }

 try_s=4;

 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++)
 {
  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')
     try_move (d2, x, y);
    i++;
   }
  }

  if (i3==i3_1)
  {
   Sleep (100);
   show_image (2, 0, 0);
  }
  else if (i3==i3_2)
  {
   Sleep (100);
   show_image (3, 0, 0);
  }
  else if (i3==i3_3)
  {
   Sleep (100);
   show_image (4, 0, 0);
  }
  else if (i3==i3_4)
  {
   Sleep (100);
   show_image (1, 0, 0);
  }
 }

 Sleep (100);
 show_image (2, 0, 0);

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

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

 try_n=0;
 int try_max=-100000;
 for (i=0; i<try_i; i++)
 {
  try_t=try_b [i]-try_b_s2 [i];
  try_b_s2 [i]=0;
  if (try_max<try_t)
  {
   try_max=try_t;
   try_n=i;
  }
  else if (try_max==try_t && rand()%2==1)
   try_n=i;
 }

 Sleep (100);
 show_image (3, 0, 0);

 flip_board (try_d [try_n]);

 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')
    {
     if (init_d [i]=='1')
     {
      break_x=x2;
      break_y=y2;
     }
     else
     {
      move_x1=x2;
      move_y1=y2;
     }
    }
    else
    {
     move_x2=x2;
     move_y2=y2;
     move_f=try_d [try_n] [i];
    }
   }
   i++;
  }
 }
 memcpy (init_d, try_d [try_n], 64);

 Sleep (100);
 show_image (4, 0, 0);

 turn=true;

 xy_hi (sel_x0, sel_y0, 0);
 xy_hi (sel_x, sel_y, 0);

 xy_sel_on=false;

 sel_x=0; sel_y=0; sel_x0=0; sel_y0=0;

 if (gx>0)
  x_hi (gx, false);
 if (gy>0)
  y_hi (gy, false);

 lx=move_x2;
 ly=move_y2;
 gx=move_x2;
 gy=move_y2;
 x_hi (gx, true);
 y_hi (gy, true);

 if (break_x!=0)
  show_image (char2num ('0', break_x, break_y), break_x, break_y);
 show_image (char2num ('0', move_x1, move_y1), move_x1, move_y1);
 show_image (char2num (move_f, move_x2, move_y2), move_x2, move_y2);

 xy_hi (move_x1, move_y1, 5);

 leaps_hi (0);
 leaps_c=-1;
 if ( (abs (move_x2-move_x1)>1 && abs (move_y2-move_y1)>1) || abs (move_x2-move_x1)>3 || abs (move_y2-move_y1)>3 || (abs (move_x2-move_x1)==2 && init_d [get_p ((move_x2-(move_x2-move_x1)/2), move_y1)]=='0')  || (abs (move_y2-move_y1)==2 && init_d [get_p (move_x1, (move_y2-(move_y2-move_y1)/2))]=='0') )
 {
  leaps (move_x1, move_y1, move_x2, move_y2);
  leaps_hi (2);
 }
 else
  leaps_c=abs (move_x2-move_x1)+abs (move_y2-move_y1)-1;

 xy_hi (move_x2, move_y2, 3);

 sndMoves ();

 movesQB++;

 move_hi=true;

 Sleep (100);
 show_image (1, 0, 0);

 Sleep (100);
 show_image (0, 0, 0);

 check_corner (init_d);

 if (square_white==true || square_black==true)
 {
  if (side && square_black==true && square_white==false && lastMove==false)
   lastMove=true;
  else
   check_end ();
 }
}

void pls (int x1, int y1, int x2, int y2)
{
 hDC=GetDC (hwnd);

 if (wp<5)
 {
  HPEN tPen;
  HBRUSH tBrush;

  if (wp==0)
  {
   tPen=CreatePen (PS_SOLID, 1, RGB (0, 0, 0));
   tBrush=CreateSolidBrush (RGB (0, 0, 0));
  }
  else if (wp==1)
  {
   tPen=CreatePen (PS_SOLID, 1, RGB (255, 255, 255));
   tBrush=CreateSolidBrush (RGB (255, 255, 255));
  }
  else if (wp==2)
  {
   tPen=CreatePen (PS_SOLID, 1, RGB (0, 171, 0));
   tBrush=CreateSolidBrush (RGB (0, 171, 0));
  }
  else if (wp==3)
  {
   tPen=CreatePen (PS_SOLID, 1, RGB (0, 0, 255));
   tBrush=CreateSolidBrush (RGB (0, 0, 255));
  }
  else if (wp==4)
  {
   tPen=CreatePen (PS_SOLID, 1, RGB (242, 170, 25));
   tBrush=CreateSolidBrush (RGB (242, 170, 25));
  }

  (HBRUSH)SelectObject (hDC, tBrush);
  (HPEN)SelectObject (hDC, tPen);

  Rectangle (hDC, x1-2, y1-2, x2+2, y2+2);
   
  DeleteObject (tPen);
  DeleteObject (tBrush);
 }
 else
 {
  if (wp==5)
   show_image (51, 0, 0);
  else if (wp==6)
   show_image (52, 0, 0);
  else if (wp==7)
   show_image (53, 0, 0);
  else if (wp==8)
   show_image (54, 0, 0);
  else if (wp==9)
   show_image (55, 0, 0);
 }

 wpl=wp;

 ReleaseDC (hwnd, hDC);
}

void paint ()
{
 if (noPaint)
  return;

 info_on=false;

 hDC=GetDC (hwnd);

 if (viewFull==true || maxSize==true)
  pls (0, 0, xSize, ySize);
 else
  cls (0, 0, xSize, ySize);

 show_image (0, 0, 0);// logo

 int x, y;

 for (x=1; x<9; x++)
  show_8x8 (false, x, 0);

 for (y=1; y<9; y++)
  show_8x8 (false, 0, y);

 int i=0;
 for (y=1; y<9; y++)
 {
  for (x=1; x<9; x++)
  {
   show_image (char2num (init_d [i], x, y), x, y);// white cell
   i++;
  }
 }

 if (gx!=0 && turn && !game_over)
  x_hi (gx, true);
 if (gy!=0 && turn && !game_over)
  y_hi (gy, true);

 if (sel_x!=0 && sel_y!=0)
  xy_hi (sel_x, sel_y, 2);
 else if (gx!=0 && gy!=0 && loaded)
  xy_hi (gx, gy, 1);

 if (sel_x0!=0 && sel_y0!=0)
 {
  xy_hi (sel_x0, sel_y0, 4);
  leaps_hi (1);
 }

 if (move_x1>0 && xy_sel_on==false)
 {
  xy_hi (move_x1, move_y1, 5);
  xy_hi (move_x2, move_y2, 3);
  leaps_hi (2);
 }

 if (square_white==true)
 {
  paint_lt=false;
  square2 ();
 }
 if (square_black==true)
 {
  paint_rb=false;
  square2 ();
 }

 if (game_over)
  movesQ ();

 if (gg_on)
  game_goes ();

 ReleaseDC (hwnd, hDC);
}

void scrUp ()
{
 sx=(LONG)::GetSystemMetrics (SM_CXFULLSCREEN);
 sy=(LONG)::GetSystemMetrics (SM_CYFULLSCREEN);
 cx=(LONG)::GetSystemMetrics (SM_CXSCREEN);
 cy=(LONG)::GetSystemMetrics (SM_CYSCREEN);
}

void view_max (int lpar)
{
 float xSizeQ, ySizeQ;

 mxCellSize=cellSize;
 xSizeLast=xSize;
 ySizeLast=ySize;

 xSize=LOWORD (lpar);
 ySize=HIWORD (lpar);

 xSizeQ=float (LOWORD (lpar)/xSize0);
 ySizeQ=float (HIWORD (lpar)/ySize0);
 if (xSizeQ>ySizeQ)
 {
  xLeft=int ((xSizeQ-ySizeQ)*xSize0/2);
  cellSize=int (cellSize0*ySizeQ);
  yTop=int ((HIWORD (lpar)-cellSize*9)/2);
 }
 else
 {
  xLeft=0;
  yTop=int ((ySizeQ-xSizeQ)*ySize0/2);
  cellSize=int (cellSize0*xSizeQ);
 }

 maxSize=true;
}

void view_full ()
{
 float xSizeQ, ySizeQ;

 xoffVF=xoff; yoffVF=yoff;
 xoff=0; yoff=0;

 xLeftVF=xLeft; yTopVF=yTop;

 xSizeVF=xSize; ySizeVF=ySize;
 xSize=cx;
 ySize=cy;

 cellSizeVF=cellSize;

 xSizeQ=float (cx/xSize0);
 ySizeQ=float (cy/ySize0);
 if (xSizeQ>ySizeQ)
 {
  xLeft=int ((xSizeQ-ySizeQ)*xSize0/2);
  cellSize=int (cellSize0*ySizeQ);

  yTop=int ((cy-cellSize*9)/2);
 }
 else
 {
  xLeft=0;
  yTop=int ((ySizeQ-xSizeQ)*ySize0/2);
  cellSize=int (cellSize0*xSizeQ);
 }
 
 noRest=true;

 hwndB = CreateWindowEx (
  0,              // Extended possibilites for variation
  szClassName,    // Classname
  title,          // Title Text
  WS_POPUP,       // WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX WS_OVERLAPPEDWINDOW default window
  -1,             // CW_USEDEFAULT Windows decides the position
  -1,             // CW_USEDEFAULT where the window ends up on the screen
  cx+2,           // The programs width
  cy+2,           // and height in pixels
  HWND_DESKTOP,   // The window is a child-window to desktop
  NULL,           // No menu
  gThisInstance,  // Program Instance handler
  NULL            // No Window Creation data
 );

 ShowWindow (hwndB, gFunsterStil);
 ShowWindow (hwnd, 0);
 hwnd=hwndB;

 noRest=false;

 playWave ("full_on");

 viewFull=true;
}

void view_full_res ()
{
 float xSizeQ, ySizeQ;

 xoff=0; yoff=0;

 xSize=cx;
 ySize=cy;

 xSizeQ=float (cx/xSize0);
 ySizeQ=float (cy/ySize0);
 if (xSizeQ>ySizeQ)
 {
  xLeft=int ((xSizeQ-ySizeQ)*xSize0/2);
  cellSize=int (cellSize0*ySizeQ);

  yTop=int ((cy-cellSize*9)/2);
 }
 else
 {
  xLeft=0;
  yTop=int ((ySizeQ-xSizeQ)*ySize0/2);
  cellSize=int (cellSize0*xSizeQ);
 }

 noRest=true;

 hwndB = CreateWindowEx (
  0,              // Extended possibilites for variation
  szClassName,    // Classname
  title,          // Title Text
  WS_POPUP,       // WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX WS_OVERLAPPEDWINDOW default window
  -1,             // CW_USEDEFAULT Windows decides the position
  -1,             // CW_USEDEFAULT where the window ends up on the screen
  cx+2,           // The programs width
  cy+2,           // and height in pixels
  HWND_DESKTOP,   // The window is a child-window to desktop
  NULL,           // No menu
  gThisInstance,  // Program Instance handler
  NULL            // No Window Creation data
 );

 ShowWindow (hwndB, gFunsterStil);
 ShowWindow (hwnd, 0);
 hwnd=hwndB;

 noRest=false;
}

void view_norm ()
{
 float xSizeQ, ySizeQ;
 xoff=xoffVF; yoff=yoffVF;
 xLeft=xLeftVF; yTop=yTopVF;
 xSize=xSizeVF; ySize=ySizeVF;
 cellSize=cellSizeVF;

 noRest=true;

 if (maxSize==true)
 {
  xSize=mxCellSize*9;
  ySize=mxCellSize*9;
 }

 hwndB = CreateWindowEx (
  0,                   // Extended possibilites for variation
  szClassName,         // Classname
  title,               // Title Text
  WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX, // WS_OVERLAPPEDWINDOW default window
  wLeft,               // CW_USEDEFAULT Windows decides the position
  wTop,                // CW_USEDEFAULT where the window ends up on the screen
  xSize+xAdd,          // The programs width
  ySize+yAdd,          // and height in pixels
  HWND_DESKTOP,        // The window is a child-window to desktop
  NULL,                // No menu
  gThisInstance,       // Program Instance handler
  NULL                 // No Window Creation data
 );

 if (maxSize==true)
 {
  xSizeQ=float (sx/xSize0);
  ySizeQ=float (sy/ySize0);
  if (xSizeQ>ySizeQ)
  {
   xLeft=int ((xSizeQ-ySizeQ)*xSize0/2);
   cellSize=int (cellSize0*ySizeQ);
   yTop=int ((sy-cellSize*9)/2);
  }
  else
  {
   xLeft=0;
   yTop=int ((ySizeQ-xSizeQ)*ySize0/2);
   cellSize=int (cellSize0*xSizeQ);
  }

  ShowWindow (hwndB, SW_MAXIMIZE);

  GetWindowRect (hwnd, &Rect);
  xSize=Rect.right;
  ySize=Rect.bottom;
 }
 else
  ShowWindow (hwndB, gFunsterStil);

 ShowWindow (hwnd, 0);
 hwnd=hwndB;

 noRest=false;

 playWave ("full_off");

 viewFull=false;
}

void view_rest (bool doPaint=true)
{
 maxSize=false;
 noRest=true;
 ShowWindow (hwnd, SW_RESTORE);// SW_SHOWNORMAL
 noRest=false;

 cellSize=mxCellSize;
 xSize=cellSize*9;
 ySize=cellSize*9;
 xLeft=0;
 yTop=0;

 if (doPaint)
  paint ();
}

void view_plus ()
{
 if (viewFull==true || maxSize==true)
 {
  if (viewFull==true)
  {
   view_norm ();

   if (maxSize==true)
    view_rest (false);
  }
  else if (maxSize==true)
  {
   view_rest (false);
   paint ();
  }
 }
 else if (cellSize<cellSizeMax)
 {
  cellSize+=5;
  if (cellSize>cellSizeMax)
   cellSize=cellSizeMax;
  xSize=cellSize*9;
  ySize=cellSize*9;
  xLeft=0;
  yTop=0;

  noRest=true;
  SetWindowPos (hwnd, HWND_TOP, 0, 0, xSize+xAdd, ySize+yAdd, SWP_NOMOVE);
  noRest=false;
 }
}

void view_minus ()
{
 if (viewFull==true || maxSize==true)
 {
  if (viewFull==true)
  {
   view_norm ();

   if (maxSize==true)
    view_rest (false);
  }
  else if (maxSize==true)
  {
   view_rest (false);
   paint ();
  }
 }
 else if (cellSize>cellSizeMin)
 {
  cellSize-=5;
  if (cellSize<cellSizeMin)
   cellSize=cellSizeMin;
  xSize=cellSize*9;
  ySize=cellSize*9;
  xLeft=0;
  yTop=0;

  SetWindowPos (hwnd, HWND_TOP, 0, 0, xSize+xAdd, ySize+yAdd, SWP_NOMOVE);
 }
}

void view_min ()
{
 bool doPaint=true;

 if (viewFull && maxSize)
  doPaint=false;

 if (viewFull==true)
  view_norm ();

 if (maxSize==true)
 {
  maxSize=false;
  noRest=true;
  ShowWindow (hwnd, SW_RESTORE);// SW_SHOWNORMAL
  noRest=false;

  xSize=xSize0;
  ySize=ySize0;

  xLeft=0;
  yTop=0;

  if (mxCellSize!=cellSize0)
  {
   cellSize=cellSize0;
   if (!doPaint)
    noPaint=true;
   SetWindowPos (hwnd, HWND_TOP, 0, 0, xSize+xAdd, ySize+yAdd, SWP_NOMOVE);
   noPaint=false;
  }
  else
  {
   cellSize=cellSize0;
   if (doPaint)
    paint ();
  }
 }
 else if (xSize!=xSize0)
 {
  xSize=xSize0;
  ySize=ySize0;

  xLeft=0;
  yTop=0;

  cellSize=cellSize0;

  SetWindowPos (hwnd, HWND_TOP, 0, 0, xSize+xAdd, ySize+yAdd, SWP_NOMOVE);
 }
}

void view_any (bool border=false)
{
 int xS, yS, xyS;

 GetWindowRect (hwnd, &Rect);

 xS=Rect.right-Rect.left-xAdd;
 yS=Rect.bottom-Rect.top-yAdd;
 if (xS>yS)
  xyS=yS;
 else
  xyS=xS;
 if (xyS<cellSizeMin*9)
  xyS=cellSizeMin*9;

 cellSize=xyS/9;

 xSize=cellSize*9;
 ySize=cellSize*9;
 xLeft=0;
 yTop=0;

 if (border==true)
  SetWindowPos (hwnd, HWND_TOP, 0, 0, xSize+xAdd, ySize+yAdd, SWP_NOMOVE);

 cls (0, 0, xS, yS);
 paint ();
}



void mouseMove (int xKey=0, int yKey=0)
{
 if (blur_on==false && loaded==true && (turn==true || game_over==true))
 {
  moved=true;

  GetCursorPos (&mypoint);

  GetWindowRect (hwnd,&Rect);

  int gxT, gyT;
  if (xKey!=0 || yKey!=0)
  {
   gxT=xKey;
   gyT=yKey;
  }
  else
  {
   gxT=(int)(mypoint.x-Rect.left-xLeft-xoff)/cellSize;
   gyT=(int)(mypoint.y-Rect.top-yTop-yoff)/cellSize;
  }

  if (gxT==0 && gyT==0 && (mypoint.x-Rect.left-xLeft-xoff)>=0 && (mypoint.y-Rect.top-yTop-yoff)>=0)
  {
   if (info_on==false && ng_on==false)
    show_info ();
  }
  else if (info_on==true)
  {
   info_clear ();

   if (soundOn)
    playWave ("info_off");
  }

  if (gxT>0 && gxT<9 && gyT>0 && gyT<9 && !game_over && !((square_white==true && gxT<4 && gyT<4) || (square_black==true && gxT>5 && gyT>5)))
  {
   gx=gxT;
   gy=gyT;

   bool xy_on=false;
   if (gx>0 && gy>0)
   {
    if(gx!=lx || gy!=ly)
    {
     if(lx!=0&&ly!=0)
     {
      int n=0;
      if (lx==move_x1 && ly==move_y1 && xy_sel_on==false)
       n=5;
      else if (lx==move_x2 && ly==move_y2 && xy_sel_on==false)
       n=3;
      if (xy_sel_on==false && leaps_c>0 && n==0)
      {
       int i;
       for (i=1; i<leaps_c; i++)
       {
        if (lx==leaps_x [i] && ly==leaps_y [i])
        {
         n=5;
         break;
        }
       }
      }

      xy_hi (lx, ly, n);
     }
     xy_on=true;

     if (lx==sel_x && ly==sel_y && lx!=0 && ly!=0)
      xy_hi (lx, ly, 2);// 2
     if (lx==sel_x0 && ly==sel_y0 && lx!=0 && ly!=0)
      xy_hi (lx, ly, 4);
    }
    if(gx!=lx)
    {
     if(lx!=0)
      x_hi (lx, false);
     lx=gx;
     x_hi (lx, true);
    }
    if(gy!=ly)
    {
     if(ly!=0)
      y_hi (ly, false);
     ly=gy;
     y_hi (ly, true);
    }
    if (xy_on==true)
    {
     if (lx==sel_x && ly==sel_y && xy_sel_on==true)
      xy_hi (lx, ly, 2);
     else
      xy_hi (lx, ly, 1);
    }
   }
  }
 }
}

void sndMoves ()
{
 int smRnd=0;

 if (leaps_c==0)
 {
  smRnd=rand()%3;
  if (smRnd==0)
   playWave ("dash");
  else if (smRnd==1)
   playWave ("slash");
  else if (smRnd==2)
   playWave ("smash");
 }
 else// if (leaps_c==1)
 {
  smRnd=rand()%3;
  if (smRnd==0)
   playWave ("click1x");
  else if (smRnd==1)
   playWave ("clk1x");
  else if (smRnd==2)
   playWave ("clkplus");
 }
}

void newGame ()
{
 ng_on=false;
 gg_on=false;
 speechless=false;
 stats=false;
 fine=false;
 turn=true;
 movesQW=0; movesQB=0;
 square_white=false;
 square_black=false;
 xy_sel_on=false;
 leap_x=0;
 leap_y=0;
 sel_x=0; sel_y=0; sel_x0=0; sel_y0=0;
 move_x1=0; move_y1=0; move_x2=0; move_y2=0;
 paint_lt=false; paint_rb=false;

 game_over=false;

 memcpy (init_d, init_p, 64);

 int ngY, ngX, ngI=0;
 for (ngY=1; ngY<9; ngY++)
 {
  for (ngX=1; ngX<9; ngX++)
  {
   show_image (char2num (init_d [ngI], ngX, ngY), ngX, ngY);
   ngI++;
  }
 }

 if (side)
  pc ();
}

void reStartGame ()
{
 if (movesQW+movesQB==0)
  return;

 if (soundOn)
  playWave ("restart");

 if (info_on)
 {
  info_clear ();
  newGame ();
  infoSless=true;
  show_info ();
  infoSless=false;
 }
 else
  newGame ();
}

void wallPaper (int wpt=0)
{
 if (wp==wpt || (!maxSize && !viewFull))
  return;

 wp=wpt;

 if (info_on)
 {
  paint ();
  infoSless=true;
  show_info ();
  infoSless=false;
 }
 else
  paint ();

 playWave ("shake");
}

void mouseClick ()
{
 if (gx>0 && gx<9 && gy>0 && gy<9 && blur_on==false && moved==true)
 {
  if (game_over==true && !ng_on && info_on==false)
  {
   new_gameC=0;
   ng_on=true;
   SetTimer (hwnd, TIMER_NG, 500, NULL);
   if (soundOn)
    playWave ("new");
  }
  else if (!info_on)
  {
   if (turn==true)
   {
    char t=init_d [get_p (lx, ly)];
    if (t=='1')
    {
     if (xy_sel_on==true)
      xy_hi (sel_x, sel_y, 0);

     if (sel_x==gx && sel_y==gy)
     {
      xy_hi (sel_x, sel_y, 1);
      sel_x=0,sel_y=0;
      if (move_x1>0)
      {
       xy_hi (move_x1, move_y1, 5);
       xy_hi (move_x2, move_y2, 3);
       leaps_hi (2);
      }
      xy_sel_on=false;
      playWave ("checkdrop");
     }
     else
     {
      xy_hi (gx, gy, 2);
      sel_x=gx;
      sel_y=gy;
      if (move_x1>0)
      {
       xy_hi (move_x1, move_y1, 0);
       xy_hi (move_x2, move_y2, 0);
       leaps_hi (0);
      }
      xy_sel_on=true;

      playWave ("checktake");
     }
    }
    else if (xy_sel_on==true)
    {
     leap_x=0;
     leap_y=0;
     if (check_move ()==true)
     {
      if (move_x1>0)
      {
       xy_hi (move_x1, move_y1, 0);
       xy_hi (move_x2, move_y2, 0);
      }

      char t=init_d [get_p (sel_x, sel_y)];
      init_d [get_p (sel_x, sel_y)]='0';
      init_d [get_p (gx, gy)]=t;
      show_image (char2num ('0', sel_x, sel_y), sel_x, sel_y);
      show_image (char2num (t, gx, gy), gx, gy);

      movesQW++;

      xy_hi (sel_x, sel_y, 4);
      xy_hi (gx, gy, 2);
      sel_x0=sel_x;
      sel_y0=sel_y;
      sel_x=gx;
      sel_y=gy;
      int gxT=gx, gyT=gy;
      turn=false;

      if ( (abs (sel_x-sel_x0)>1 && abs (sel_y-sel_y0)>1) || abs (sel_x-sel_x0)>3 || abs (sel_y-sel_y0)>3 || (abs (sel_x-sel_x0)==2 && init_d [get_p ((sel_x-(sel_x-sel_x0)/2), sel_y0)]=='0')  || (abs (sel_y-sel_y0)==2 && init_d [get_p (sel_x0, (sel_y-(sel_y-sel_y0)/2))]=='0') )
      {
       leaps (sel_x0, sel_y0, sel_x, sel_y);
       leaps_hi (1);
      }
      else
       leaps_c=abs (sel_x-sel_x0)+abs (sel_y-sel_y0)-1;

      sndMoves ();
 
      if (lastMove==true)
      {
       lastMove=false;
       check_corner (init_d);

       if (square_white==true || square_black==true)
        check_end ();
      }
      else if (check_corner (init_d))
      {
       if (!side)
        pc ();
       else
        check_end ();
      }
      else
       pc ();

      if (keyClick==false)
       mouseMove ();
      else
       mouseMove (gxT, gyT);
     }
     else
      playWave ("break");
    }
   }
  }
 }
}



int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
 gThisInstance=hThisInstance;
 gFunsterStil=nFunsterStil;

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

 // The Window structure
 wincl.hInstance = hThisInstance;
 wincl.lpszClassName = szClassName;
 wincl.lpfnWndProc = WindowProcedure;// This function is called by windows
 wincl.style = CS_DBLCLKS;// | CS_HREDRAW | CS_VREDRAW | CS_OWNDC Catch double-clicks
 wincl.cbSize = sizeof (WNDCLASSEX);

 // Use default icon and mouse-pointer
 wincl.hIcon = LoadIcon (hThisInstance, MAKEINTRESOURCE(ID_PIC));// NULL IDI_APPLICATION*/
 wincl.hIconSm = LoadIcon (hThisInstance, MAKEINTRESOURCE(ID_PIC));// NULL IDI_APPLICATION*/
 wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
 wincl.lpszMenuName = NULL; // No menu
 wincl.cbClsExtra = 0;      // No extra bytes after the window class
 wincl.cbWndExtra = 0;      // structure or the window instance
 // Use Windows's default color as the background of the window
 wincl.hbrBackground = (HBRUSH)CreateSolidBrush (bGround);// 128,128,128 COLOR_BACKGROUND+1;(COLOR_WINDOWFRAME);

 // Register the window class, and if it fails quit the program
 if (!RegisterClassEx (&wincl))
  return 0;

 FILE *file;
 int i, i1=0, i2=0, s=0, twx, twy;
 char conf [confL], conf_wx [confL], conf_wy [confL], conf_cs [confL], conf_mx [confL],
   conf_sn [confL], conf_vf [confL], conf_sd [confL], conf_wp [confL];
 memset (conf, 0, confL);
 memset (conf_wx, 0, confL);
 memset (conf_wy, 0, confL);
 memset (conf_cs, 0, confL);
 memset (conf_mx, 0, confL);
 memset (conf_sn, 0, confL);
 memset (conf_vf, 0, confL);
 memset (conf_sd, 0, confL);
 memset (conf_wp, 0, confL);

 if (sx>sy)
  cellSizeMax=(sy-xAdd)/9+1;
 else
  cellSizeMax=(sx-xAdd)/9+1;

 char AppPath [_MAX_PATH];
 int ap_l=0;
 memset (AppPath, 0, _MAX_PATH);
 memset (AppDir, 0, _MAX_PATH);
 memset (confPath, 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);
 memcpy (confPath, AppPath, ap_l);
 strcat (confPath, "data\\config.txt");

 file=fopen (confPath, "r");
 if (file!=NULL)
 {
  fgets (conf, confL, file);
  fclose (file);

  for (i=0; i<confL; i++)
  {
   if (conf [i]=='.')
    break;
   else if (conf [i]==':')
   {
    s++;
    i1=0;
   }
   else
   {
    if (s==0)
     conf_wx [i1]=conf [i];
    else if (s==1)
     conf_wy [i1]=conf [i];
    else if (s==2)
     conf_cs [i1]=conf [i];
    else if (s==3)
     conf_mx [i1]=conf [i];
    else if (s==4)
     conf_sn [i1]=conf [i];
    else if (s==5)
     conf_vf [i1]=conf [i];
    else if (s==6)
     conf_sd [i1]=conf [i];
    else if (s==7)
     conf_wp [i1]=conf [i];
    i1++;
   }
  }

  wLeft=atoi (conf_wx), wTop=atoi (conf_wy);

  if (wLeft<0)
   wLeft=0;
  if (wTop<0)
   wTop=0;
  if (wLeft>sx-100)
   wLeft=sx-100;
  if (wTop>sy-100)
   wTop=sy-100;

  cellSize=atoi (conf_cs);
  if (cellSize<cellSizeMin)
   cellSize=cellSizeMin;
  else if (cellSize>cellSizeMax)
   cellSize=cellSizeMax;
  if (cellSize!=cellSize0)
  {
   xSize=cellSize*9;
   ySize=cellSize*9;
  }

  if (atoi (conf_mx)==1)
   maxSize=true;

  if (atoi (conf_sn)==1)
   soundOn=true;

  if (atoi (conf_vf)==1)
   viewFull=true;

  if (atoi (conf_sd)==1)
  {
   side=true;
   turn=false;
  }

  wp=atoi (conf_wp);
  if (wp<0 || wp>9)
   wp=0;
 }

 // The class is registered, let's create the program*/
 hwnd = CreateWindowEx (
  0,                   // Extended possibilites for variation
  szClassName,         // Classname
  title,               // Title Text
  WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX, // WS_OVERLAPPEDWINDOW default window
  wLeft,               // CW_USEDEFAULT Windows decides the position
  wTop,                // CW_USEDEFAULT where the window ends up on the screen
  xSize+xAdd,          // The programs width
  ySize+yAdd,          // and height in pixels
  HWND_DESKTOP,        // The window is a child-window to desktop
  NULL,                // No menu
  hThisInstance,       // Program Instance handler
  NULL                 // No Window Creation data
 );

 // Make the window visible on the screen
 ShowWindow (hwnd, nFunsterStil);

 GetClientRect (hwnd,&Rect);
 if(Rect.bottom!=ySize || Rect.right!=xSize)
 {
  ShowWindow (hwnd, 0);

  xAdd-=Rect.right-xSize;
  xoff=xoff-(Rect.right-xSize)/2;
  yAdd-=Rect.bottom-ySize;
  yoff=yoff-(Rect.bottom-ySize)+(Rect.right-xSize)/2;

  hwnd = CreateWindowEx (
   0,                   // Extended possibilites for variation
   szClassName,         // Classname
   title,               // Title Text
   WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX, // WS_OVERLAPPEDWINDOW default window
   wLeft,               // CW_USEDEFAULT Windows decides the position
   wTop,                // CW_USEDEFAULT where the window ends up on the screen
   xSize+xAdd,          // The programs width
   ySize+yAdd,          // and height in pixels
   HWND_DESKTOP,        // The window is a child-window to desktop
   NULL,                // No menu
   hThisInstance,       // Program Instance handler
   NULL                 // No Window Creation data
  );

  ShowWindow (hwnd, nFunsterStil);
 }

 bool rePos=false;

 if (sx>sy)
  cellSizeMax=(sy-xAdd)/9+1;
 else
  cellSizeMax=(sx-xAdd)/9+1;

 if (cellSize>cellSizeMax)
 {
  cellSize=cellSizeMax;
  xSize=cellSize*9;
  ySize=cellSize*9;
  rePos=true;
 }

 twx=wLeft; twy=wTop;
 if (wLeft+xSize+xAdd>sx)
 {
  wLeft=sx-xSize-xAdd;
  if (wLeft<0)
   wLeft=0;
 }
 if (wTop+ySize+xAdd>sy)
 {
  wTop=sy-ySize-xAdd;
  if (wTop<0)
   wTop=0;
 }
 if (twx!=wLeft || twy!=wTop)
  rePos=true;

 if (rePos==true)
 {
  if (maxSize || viewFull)
   noPaint=true;
  SetWindowPos (hwnd, HWND_TOP, wLeft, wTop, xSize+xAdd, ySize+yAdd, SWP_SHOWWINDOW);
  noPaint=false;
 }
 if (maxSize==true)
 {
  if (viewFull)
   noPaint=true;
  ShowWindow (hwnd, SW_MAXIMIZE);
  noPaint=false;
 }
 if (viewFull==true)
  view_full ();

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

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

 loaded=true;

 if (soundOn==true)
 {
  playWave ("enter");
  if (side)
   SetTimer (hwnd, TIMER_MOVE, 3500, NULL);
 }
 else if (side)
  SetTimer (hwnd, TIMER_MOVE, 1500, NULL);

 // Run the message loop. It will run until GetMessage() returns 0
 while (GetMessage (&messages, NULL, 0, 0))
 {
  // Translate virtual-key messages into character messages
  TranslateMessage(&messages);
  // Send message to WindowProcedure
  DispatchMessage(&messages);
 }

 // The program return-value is 0 - The value that PostQuitMessage() gave
 return messages.wParam;
}

// This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)
 {
  case WM_KEYUP:
   switch (wParam)
   {
    case VK_CONTROL:
     ctrl_key=false;
     break;

    case 83:
     keyLockS=false;
     break;

    case 70:
     keyLockF=false;
     break;

    case 176:
     keyLockF=false;
     break;
   }
   break;

  case WM_KEYDOWN:

   switch (wParam)
   {
    case VK_ESCAPE:

     if (exitx==false)
     {
      exitx=true;
      save_conf ();
      playWave ("exit");
      if (info_on==false && game_over==false)
      {
       sprintf (messMP, "Пока!");
       messPrint (hFontCap, 4.5, 242, 170, 25, 175, 150, 0);
       SetTimer (hwnd, TIMER_EXIT, 2500, NULL);
      }
      else if (soundOn)
       SetTimer (hwnd, TIMER_EXIT, 2500, NULL);
      else
      {
       Gdiplus::GdiplusShutdown (gdiplusToken);
       PostQuitMessage (0);// send a WM_QUIT to the message queue
      }
     }
     break;

    case VK_CONTROL:
     ctrl_key=true;
     break;

    case 107:
     if (ctrl_key==true)
     {
      view_plus ();
      mxLparX=0; mxLparY=0;
     }
     break;

    case 187:
     if (ctrl_key==true)
     {
      view_plus ();
      mxLparX=0; mxLparY=0;
     }
     break;

    case 109:
     if (ctrl_key==true)
     {
      view_minus ();
      mxLparX=0; mxLparY=0;
     }
     break;

    case 189:
     if (ctrl_key==true)
     {
      view_minus ();
      mxLparX=0; mxLparY=0;
     }
     break;

    case 48:
     if (ctrl_key==true)
     {
      view_min ();
      mxLparX=0; mxLparY=0;
     }
     else
      wallPaper (9);
     break;

    case 83:
     if (keyLockS==false)
     {
      if (soundOn==true)
      {
       soundOn=false;
       playWave ("turn_off", true);
      }
      else
      {
       soundOn=true;
       playWave ("turn_on", true);
      }

      keyLockS=true;
     }
     break;

    case 70:
     if (keyLockF==false)
     {
      if (viewFull==false)
       view_full ();
      else
       view_norm ();

      keyLockF=true;
     }
     break;

    case 176:
     if (keyLockF==false)
     {
      if (viewFull==false)
       view_full ();
      else
       view_norm ();

      keyLockF=true;
     }
     break;


    case 82:
     if (ctrl_key)
      reStartGame ();
    break;

    
    case '1':
     wallPaper (0);
    break;

    case '2':
     wallPaper (1);
    break;

    case '3':
     wallPaper (2);
    break;

    case '4':
     wallPaper (3);
    break;

    case '5':
     wallPaper (4);
    break;

    case '6':
     wallPaper (5);
    break;

    case '7':
     wallPaper (6);
    break;

    case '8':
     wallPaper (7);
    break;

    case '9':
     wallPaper (8);
    break;

    case 33:
     if (lx<8 && ly>1)
      mouseMove (lx+1, ly-1);
     break;

    case 34:
     if (lx<8 && ly<8)
      mouseMove (lx+1, ly+1);
     break;

    case 35:
     if (lx>1 && ly<8)
      mouseMove (lx-1, ly+1);
     break;

    case 36:
     if (lx>1 && ly>1)
      mouseMove (lx-1, ly-1);
     break;

    case 37:
     if (lx>1)
      mouseMove (lx-1, ly);
     break;

    case 38:
     if (ly>1)
      mouseMove (lx, ly-1);
     break;

    case 39:
     if (lx<8)
      mouseMove (lx+1, ly);
     break;

    case 40:
     if (ly<8)
      mouseMove (lx, ly+1);
     break;
  
    case 12:
     keyClick=true;
     mouseClick ();
     break;

    case 13:
     keyClick=true;
     mouseClick ();
     break;

    case 32:
     keyClick=true;
     mouseClick ();
     break;
   }

   if (wParam==176)
   {
    if (keyLockF==false)
    {
     if (viewFull==false)
      view_full ();
     else
      view_norm ();

     keyLockF=true;
    }
   }
   break;

  case WM_MOVE:

   GetWindowRect (hwnd, &Rect);
   if (Rect.left>0)
    wLeft=Rect.left;
   if (Rect.top>0)
    wTop=Rect.top;
   break;

  case WM_MOVING:// WM_WINDOWPOSCHANGED
   if (paintOn==0 && noRest==false)
   {
    paintOn=1;
    refresh=true;
    SetTimer (hwnd, TIMER_PAINT, 500, NULL);
   }
   break;

  case WM_EXITSIZEMOVE:
   if (sizing==true && noRest==false)
   {
    view_any (true);// gLpar
    sizing=false;
   }
   break;

  case WM_SIZE:

   switch (wParam)
   {
    case SIZE_MAXIMIZED:

     if (noRest==false && !resPaint)
     {
      if (cx!=(LONG)::GetSystemMetrics (SM_CXSCREEN) || cy!=(LONG)::GetSystemMetrics (SM_CYSCREEN))
      {
       mxLparX=LOWORD (lParam); mxLparY=HIWORD (lParam);

       scrUp ();
       view_max (lParam);
       paint ();

       resPaint=true;
       SetTimer (hwnd, TIMER_RES, 500, NULL);
      }
      else if ((LOWORD (lParam)!=mxLparX || HIWORD (lParam)!=mxLparY) && !blur_on) 
      {
       mxLparX=LOWORD (lParam); mxLparY=HIWORD (lParam);
       view_max (lParam);
      }
     }
     break;

    case SIZE_RESTORED:

     if (LOWORD (lParam)==cx && HIWORD (lParam)==cy)
      break;

     if (loaded==true && noRest==false && !resPaint)
     {
      if (cx!=(LONG)::GetSystemMetrics (SM_CXSCREEN) || cy!=(LONG)::GetSystemMetrics (SM_CYSCREEN))
      {
       scrUp ();

       if (viewFull)
        view_full_res ();
       else if (paintOn==0)
        paint ();

       resPaint=true;
       SetTimer (hwnd, TIMER_RES, 500, NULL);
      }
      else if (maxSize==true)
      {
       mxLparX=LOWORD (lParam); mxLparY=HIWORD (lParam);
       maxSize=false;
       view_any (true);
      }
      else if (LOWORD (lParam)==xSizeLast && HIWORD (lParam)==ySizeLast && !(xSizeLast==cellSize*9 && ySizeLast==cellSize*9))
       view_any (true);
      else if (paintOn==0)
       paint ();

      gLpar=lParam;
     }
     break;
   }
   break;

  case WM_SIZING:

   if (paintOn==0 && noRest==false)
   {
    paintOn=2;
    SetTimer (hwnd, TIMER_PAINT, 500, NULL);
   }
   sizing=true;
   break;

  case WM_NCMOUSEMOVE:

   if (info_on==true && blur_on==false)
   {
    hDC=GetDC (hwnd);
    hCompatibleDC=CreateCompatibleDC (hDC);
    SelectObject(hCompatibleDC, hbm);
    StretchBlt (hDC, 0, 0, xSize, ySize, hCompatibleDC, 0, 0, xSize, ySize, SRCCOPY);
    DeleteObject (hbm);

    info_on=false;
   }
   break;

  case WM_TIMER:
 
   switch (wParam)
   {
    case TIMER_RES:
     KillTimer (hwnd, TIMER_RES);

     resPaint=false;
     break;

    case TIMER_PAINT:
     KillTimer (hwnd, TIMER_PAINT);

     if (paintOn==2)
     {
      if (sizing==true)
       view_any ();
     }
     else
      paint ();

     paintOn=0;   
     break;

    case TIMER_NG:
     if (new_gameC==0)
      game_goes ();

     if (new_gameC==new_gameN)
     {
      KillTimer (hwnd, TIMER_NG);
      new_gameC=0;
      show_image (0, 0, 0);
      newGame ();
     }
     else
     {
      new_gameC++;
      if (new_gameC==1 || new_gameC==5 || new_gameC==9)
       show_image (1, 0, 0);
      else if (new_gameC==2 || new_gameC==6)
       show_image (2, 0, 0);
      else if (new_gameC==3 || new_gameC==7)
       show_image (3, 0, 0);
      else if (new_gameC==4 || new_gameC==8)
       show_image (4, 0, 0);
     }
    break;

    case TIMER_MOVE:
     KillTimer (hwnd, TIMER_MOVE);

     if (!exitx)
      pc ();
     break;

    case TIMER_EXIT:
     KillTimer (hwnd, TIMER_EXIT);
     Gdiplus::GdiplusShutdown (gdiplusToken);
     PostQuitMessage (0);// send a WM_QUIT to the message queue
    break;
   }
   break;

  case WM_KILLFOCUS:

   blur_on=true;
   break;

  case WM_SETFOCUS:

   if (cx!=(LONG)::GetSystemMetrics (SM_CXSCREEN) || cy!=(LONG)::GetSystemMetrics (SM_CYSCREEN))
    scrUp ();

   blur_on=false;
   break;

  case WM_PAINT:

   BeginPaint(hwnd, &PaintStruct);

   if (!paintOn)
    paint ();

   EndPaint (hwnd, &PaintStruct);
   break;

  case WM_LBUTTONUP:

   mouseClick ();
   break;

  case WM_MOUSEMOVE:
   
   mouseMove ();
   break;

  case WM_DESTROY:

   save_conf();
   Gdiplus::GdiplusShutdown (gdiplusToken);
   PostQuitMessage (0);// send a WM_QUIT to the message queue
   break;

  default:// for messages that we don't deal with
 
   return DefWindowProc (hwnd, message, wParam, lParam);
 }
}