// uses ChessAlpha2.ttf fonts
#include <windows.h>
#include "resource.h"

#define WhiteBishop 192
#define WhiteKnight 194
#define WhiteRook 196
#define WhiteQueen 198
#define WhiteKing 200
#define WhitePawn 202
#define BlackBishop 224
#define BlackKnight 226
#define BlackRook 228
#define BlackQueen 230
#define BlackKing 232
#define BlackPawn 234
#define Check 1
#define EitherOne 2
#define DiscoveredCheck 3

int x, y, z, f, fBiggest, SquareSize, SquareSize2, AllSquareSize, LeftSide, TopSide, endoffens, Shifted;
int X, Y, X2, Y2, xPos, yPos, cX, cY, cX2, cY2;
int ScreenWidth, ScreenHeight, Title, Menu, Border = 16;
int BlackKingX, BlackKingY, WhiteKingX, WhiteKingY;
int KingX, KingY, King, BlackKingcX, BlackKingcY, WhiteKingcX, WhiteKingcY;
int checktype, HalfMoves = 0, FullMoves = 1, NumberOfOnes = 32;
DWORD dwBytesWritten, dwBytesRead, fileSize, PrevBestMove;
BYTE MovedPiece, ReplacedPiece, chessenginemove = FALSE, chessengine = FALSE, notfound = FALSE, done = FALSE, frompromoted = FALSE;
BOOL first = TRUE, WhitesMove = TRUE, movingPiece = FALSE, choosePiece = FALSE, itsdiscoveredcheck = FALSE, leftright = FALSE;
BOOL promoted = FALSE, returned, rotated = FALSE, placepieces = FALSE, itscheck = FALSE, checkmate = FALSE, enpassant1 = FALSE, enpassant2 = FALSE;
BOOL bk = FALSE, wk = FALSE, bqr = FALSE, bkr = FALSE, wqr = FALSE, wkr = FALSE;
// if Fen[Y][X] is a 'B' (a white bishop), it's 66 in ASCII decimal and the 66th entry in Pieces is 192 which is the number of a white bishop in the ChessAlpha2.ttf font, so (BYTE*)&Pieces[Fen[Y][X]] will display a white bishop
BYTE Pieces[] = {000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,192,000,000,000,000,000,000,000,000,200,000,000,194,000,202,198,196,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,224,000,000,000,000,000,000,000,000,232,000,000,226,000,234,230,228}; // B,K,N,P,Q,R b,k,n,p,q,r

char szAppName[] = "   SimpleChess";
char WhiteMoves[] = "   WHITE'S MOVE";
char BlackMoves[] = "   BLACK'S MOVE";
char Letters[] = "abcdefgh";
char letter[1], num[1], piece;
char ChessAlpha2[] = "Chess Alpha 2";
char Filename[MAX_PATH];
char FullFilename[MAX_PATH];
char CurrentDir[MAX_PATH];
char EnPassant[4] = "--"; // "e3" or "-"
char PlacePieces[] = "&Place Pieces Help";
char Knight;

char OptionsHelp[] = "\
PLACE PIECES \n\
To place a piece, move the mouse pointer to a square,\n\
and press one of these letters\n\
(and press Shift for a white piece):\n\
K - King\n\
Q - Queen\n\
B - Bishop\n\
N - Knight\n\
R - Rook\n\
P - Pawn\n\
Press Delete to delete the piece the mouse pointer is over.\n\
\n\
ROTATE BOARD\n\
Pressing this or X will rotate the board.";

char Help[] = "\
Move a piece by holding the LEFT mouse button down while moving it.\n\
\n\
Use the left and right arrow keys to go back/ahead in the game.\n\
If you play a piece after going back in a game,\n\
it becomes the last piece played.\n\
\n\
To Castle, move the King two places left or right.\n\
\n\
To take a pawn En Passant, move your pawn to where it would end up.\n\
\n\
If you want to play against the computer,\n\
download a chess engine from the Internet,\n\
and then select File -Open Chess Engine on the Menu\n\
and find and select that chess engine.\n\
\n\
Pressing the RIGHT mouse button causes\n\
the chess engine to make the move.\n\
\n\
Pressing 0 thru 9 or A thru F on your\n\
computer keyboard will change the depth\n\
of search the chess engine makes.\n\
(A thru F are 10 thru 15 in hexadecimal)\n\
\n\
Doug Cox jdmcox@jdmcox.com\n\
Updates at jdmcox.com\n\
Put this font with your other fonts:\n\
http:\\\\jdmcox.com\\ChessAlpha2.ttf";

char AdvancedHelp[] = "\
Opening a chess engine will show CHECKMATE (if it happens) because it's calculated by the chess engine, not SimpleChess.\n\
\n\
You can see what a chess engine is doing by opening it directly (click on it in the directory it's in). The first command you can send it is \"uci\" followed by pressing the Enter key. It should respond with a screen of strange options. If it doesn't, maybe that chess engine doesn't support the Universal Chess Interface (UCI)). You can then enter \"isready\" followed by Enter if you want. I don't. Then you can even enter \"ucinewgame\" followed by Enter. I don't.\n\
\n\
The first important command to send to a chess engine is a special line of characters that represent the current location of the chess pieces followed by some other information. SimpleChess automatically sends this when you press the right mouse button while playing SimpleChess. This string is called the Forsythe-Edwards Notation (FEN). It looks like this:\n\
position fen rnbqkbnr/pppppppp/11111111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR w KQkq - 0 1\n\
this is a chess board layout with no pieces having been moved (the lower case pieces are black). The small w following the chess pieces means it's white's move. The KQkq tells the chess engine if the kings can or can't castle in each of the 4 possible directions. The - indicates no pawn can be taken en passant. Next is the number of moves since the last capture or pawn move, and the last number is the total moves divided by 2 (1 is there at the beginning of a game).\n\
\n\
You can see the FEN string that will go to the chess engine by pressing the Z key in SimpleChess (you'll also see the chess engine's name if a move has been made). This FEN string is put into the Windows Clipboard every time a move is made. Thus you can paste the current FEN string from SimpleChess into a chess engine you opened directly (it will include the Enter command at the end).\n\
\n\
The next command to send to a chess engine is simply \"go\" (followed by pressing the Enter key). This tells the chess engine to begin searching for the best move. SimpleChess alters this \"go\" command to include how deep a search the chess engine makes by using the \"Go Depth x\" command. I've found that 16 is the best maximum depth to use in SimpleChess. To alter the depth, press a number between 0 and 9 or a letter between A and F (16 hexadecimal numbers) on your computer keyboard. Pressing F sends \"go depth 16\". Zero is the default setting.\n\
\n\
If you open a chess engine directly, and then you play a move in SimpleChess, and then press Ctrl-V at the flashing cursor on the chess engine's screen, SimpleChess' move will be pasted into the chess engine. Then you only need to enter \"go\" or \"go depth x\" at the next flashing cursor (followed by Enter). This will show you a line of data for each depth of the chess engine's search for the best move. If you just entered \"go\", you might have to enter \"stop\" (followed by Enter) while the search is going on to stop it. You can also enter \"quit\" to quit.\n\
\n\
C:\\Users\\Public\\Chess Engines\\CurrentEngine.txt\ncontains the current chess engine's name.";

HWND hwnd, hwndEdit, hwndCheck, hwndCheckMate;
HINSTANCE hInst;
HANDLE hFile, hFindFile;
HFONT hFont;
LOGFONT lf;
OPENFILENAME ofn;
HBRUSH hBeigeBrush, hBrownBrush, hBorderBrush, hGreyBrush;
HPEN hBeigePen, hBrownPen, hBorderPen, hGreyPen;
HGDIOBJ hOldBrush, hOldPen, hOldFont;
RECT rect;
HBITMAP hMemBitmap, hMem2Bitmap;
HDC hdc, hdcMem = 0, hdcMem2;
PAINTSTRUCT ps;

////////////////////////////////////// chess engine stuff
HGLOBAL hGlob = 0;
HANDLE hClipboard;
SECURITY_ATTRIBUTES saAttr; 
HANDLE IN_Rd = NULL;
HANDLE IN_Wr = NULL;
HANDLE OUT_Rd = NULL;
HANDLE OUT_Wr = NULL;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
WIN32_FIND_DATA fd;
int fook, fook2, x0, x1, y0, y1, dx, dy, sx, sy, err, e2, skip, Size = 12;
char CurrentEngine[] = "C:\\Users\\Public\\ChessEngines\\CurrentEngine.txt";
char ChessEngine[MAX_PATH];
char GoDepth[16] = "go depth 1\r\n\0";
char GoDepth2[16] = "go depth 10\r\n\0";
char Quit[7] = "quit\r\n\0";
char cBuf[10240];
DWORD dwRead, dwWritten;
char fen, Promoted = 'x';
char Fen[8][12]; // 12 to have a following zero
char Fens[500][108];
char OrigPositions[72] = "rnbqkbnr/pppppppp/11111111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR";
char OrigFenString[100] = "position fen rnbqkbnr/pppppppp/11111111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR w KQkq - 0 1\r\n";
char PlPoFenString[100] = "position fen r111k11r/11111111/11111111/11111111/11111111/11111111/11111111/R111K11R w KQkq - 0 1\r\n";
//////////////////////////////////////

int CheckKing(int, int, int);
BOOL CheckMove(void);
BOOL CheckRook(void);
BOOL CheckKnight(void);
BOOL CheckBishop(void);
BOOL CheckQueen(void);
void UpdateMoves(void);
void Enpassant(int);
void GetFensData(void);
void PlacePiece(WPARAM);
void LeftRight(void);
void InCommon(void);
void LoadChessEngine(void);
int CALLBACK CheckProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK CheckMateProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK PromotionProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	MSG          msg;
	WNDCLASS     wndclass;

	hInst = hInstance;
	wndclass.style         = CS_HREDRAW|CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE ("PAWN"));
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName  = "MENU";
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
		return 0;

	hwnd = CreateWindow(szAppName, szAppName,
		WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);
	ShowWindow(hwnd, SW_SHOWNORMAL);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_CREATE:
		f = fBiggest = 0;
		for (x = 0; OrigFenString[x] != 0; x++)
			Fens[f][x] = OrigFenString[x];
		Fens[f][x] = 0;
		for (y = 0, z = 0; z < 8; z++) {
			for (x = 0; x < 8; x++, y++)
				Fen[z][x] = OrigPositions[y];
			y++; // past '/' 
		}
		AddFontResource("ChessAlpha2.ttf");
		SetWindowText(hwnd, WhiteMoves);
		Filename[0] = 0;

		hBeigeBrush = CreateSolidBrush(0x95B3BA);
		hBeigePen = CreatePen(PS_SOLID, 1, 0x65838A);
		hBrownBrush = CreateSolidBrush(0x6084A2);
		hBrownPen = CreatePen(PS_SOLID, 1, 0x305472);
		hBorderBrush = CreateSolidBrush(0x2D4868);
		hBorderPen = CreatePen(PS_SOLID, 1, 0x2D4868);
		hGreyBrush = CreateSolidBrush(0xBBBBBB);
		hGreyPen = CreatePen(PS_SOLID, 1, 0xBBBBBB);

		ofn.lStructSize       = sizeof(OPENFILENAME);
		ofn.lpstrFilter       = TEXT(" *.*\0*.*\0\0");
		ofn.lpstrCustomFilter = NULL;
		ofn.lpstrFile         = FullFilename;
		ofn.lpstrFileTitle    = Filename;
		ofn.Flags             = OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_OVERWRITEPROMPT;
		ofn.lpstrDefExt       = NULL;
		ofn.hwndOwner         = hwnd;
		ofn.hInstance         = NULL;
		ofn.nMaxFile          = MAX_PATH;
		ofn.nMaxCustFilter    = 0;
		ofn.nFilterIndex      = 0;
		ofn.nMaxFileTitle     = MAX_PATH;
		ofn.lpstrInitialDir   = NULL;
		ofn.nFileOffset       = 0;
		ofn.nFileExtension    = 0;
		ofn.lCustData         = 0;
		ofn.lpfnHook          = NULL;
		ofn.lpTemplateName    = NULL;

		ScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
		ScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN);
		Menu = GetSystemMetrics(SM_CYMENU);
		Title = GetSystemMetrics(SM_CYCAPTION);
		GetClientRect(hwnd, &rect); // CW_USEDEFAULT (the sizing here and in WM_SIZE is weird but necessary)
		if (rect.bottom < rect.right)
			SquareSize = (rect.bottom - (2*Border)) / 8;
		else
			SquareSize = (rect.right - (2*Border)) / 8;
		AllSquareSize = 8 * SquareSize;
		LeftSide = (ScreenWidth / 2) - (Border + (SquareSize * 4));
		TopSide = (ScreenHeight / 2) - (Border + (SquareSize * 4));
		MoveWindow(hwnd, LeftSide, TopSide, AllSquareSize+(2*Border), rect.bottom+Title+Menu, FALSE);
		break;

	case WM_SIZE: // in case I put sizing capability back
		rect.right = LOWORD(lParam);
		rect.bottom = HIWORD(lParam);
		if (rect.bottom < rect.right)
			SquareSize = (rect.bottom - (2*Border)) / 8; // height
		else
			SquareSize = (rect.right - (2*Border)) / 8; // width
		AllSquareSize = 8 * SquareSize;
		SquareSize2 = (2 * SquareSize);

		lf.lfHeight = -((SquareSize*3*96)/(4*72)); // presumes 96 = dots/inch of monitor
		lf.lfWeight = 700;
		lf.lfItalic = 0;
		lf.lfUnderline = 0;
		lf.lfStrikeOut = 0;
		lf.lfCharSet = 0;
		lf.lfOutPrecision = 3;
		lf.lfClipPrecision = 2;
		lf.lfQuality = 1;
		lf.lfPitchAndFamily = 0x22;
		for (x = 0; ChessAlpha2[x] != 0; x++)
			lf.lfFaceName[x] = ChessAlpha2[x];
		lf.lfFaceName[x] = 0;
		hFont = CreateFontIndirect(&lf); // chess pieces
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case ID_FILE_CHESSENGINE:
			for (x = 0; ofn.lpstrFile[x] != 0; x++)
				ofn.lpstrFile[x] = 0;
			if (GetOpenFileName(&ofn)) {
				if (chessengine)
					WriteFile(IN_Wr, Quit, 7, &dwBytesWritten, NULL);
				for (x = 0; ofn.lpstrFile[x] != 0; x++)
					;
				hFile = CreateFile(CurrentEngine, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
				if (hFile != INVALID_HANDLE_VALUE) {
					WriteFile(hFile, ofn.lpstrFile, x, &dwBytesWritten, NULL); // new current engine name saved in CurrentEngine
					CloseHandle(hFile);
					LoadChessEngine();
				}
				else {
					GetCurrentDirectory(255, CurrentDir);
					SetCurrentDirectory(TEXT("C:\\USERS\\PUBLIC\\"));
					hFindFile = FindFirstFile(TEXT("ChessEngines"), &fd);
					if (INVALID_HANDLE_VALUE == hFindFile)
						CreateDirectory(TEXT("ChessEngines"), NULL);
					SetCurrentDirectory(CurrentDir);
					hFile = CreateFile(CurrentEngine, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
					if (hFile != INVALID_HANDLE_VALUE) {
						WriteFile(hFile, ofn.lpstrFile, x, &dwBytesWritten, NULL); // new current engine name saved in CurrentEngine
						FlushFileBuffers(hFile);
						CloseHandle(hFile);
						LoadChessEngine();
					}
					else
						MessageBox(hwnd, "?", "", MB_OK);
				}
			}
 			break;

		case FILE_SAVE:
			for (x = 0; ofn.lpstrFile[x] != 0; x++)
				ofn.lpstrFile[x] = 0;
			if (GetSaveFileName(&ofn)) {
				if (INVALID_HANDLE_VALUE != (hFile = CreateFile(FullFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL))) {
					for (x = 0; x <= f; x++)
						WriteFile(hFile, Fens[x], 108, &dwBytesWritten, NULL);
					CloseHandle(hFile);
				}
			}
			break;

		case ID_FILE_LOADGAME:
			if (GetOpenFileName(&ofn)) {
				if (INVALID_HANDLE_VALUE != (hFile = CreateFile(FullFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))) {
					if (fileSize = GetFileSize(hFile, NULL)) {
						f = fileSize / 108;
						for (x = 0; x < f; x++)
							ReadFile(hFile, Fens[x], 108, &dwBytesRead, NULL);
						CloseHandle(hFile);
						f--;
						fBiggest = f;
						if (Fens[f][85] == 'w') {
							WhitesMove = TRUE;
							SetWindowText(hwnd, WhiteMoves);
						}
						else {
							WhitesMove = FALSE;
							SetWindowText(hwnd, BlackMoves);
						}
						for (y = 13, z = 0; z < 8; z++) {
							for (x = 0; x < 8; x++, y++)
								Fen[z][x] = Fens[f][y];
							y++; // past '/'
						}
						GetFensData();
						rotated = FALSE;
						placepieces = FALSE;
					}

					InvalidateRect(hwnd, &rect, FALSE);
					UpdateWindow(hwnd);
				}
			}
			break;

		case ID_FILE_EXIT:
			DestroyWindow(hwnd);
			break;
		case ID_OPTIONSHELP:
			MessageBox(hwnd, OptionsHelp, "Options Help", MB_OK);
			break;
		case ID_SETUPPIECES:
			SetWindowText(hwnd, szAppName);
			bk = FALSE; wk = FALSE; bqr = FALSE; bkr = FALSE; wqr = FALSE; wkr = FALSE; // both kings can castle either way
			rotated = FALSE;
			WhitesMove = TRUE;
			SetWindowText(hwnd, WhiteMoves);
			placepieces = TRUE;
			if (IDNO == MessageBox(hwnd, "Place pieces from game?", "", MB_YESNO|MB_DEFBUTTON2)) {
				for (x = 0; PlPoFenString[x] != 0; x++)
					Fens[f][x] = PlPoFenString[x];
				x = 13;
				for (z = 0; z < 8; z++) { // update Fen from Fens
					for (y = 0; y < 8; y++)
						Fen[z][y] = Fens[f][x++];
					x++;
				}
			}
			InvalidateRect(hwnd, &rect, FALSE);
			break;

		case ROTATE:
			if (rotated)
				rotated = FALSE;
			else
				rotated = TRUE;
			first = TRUE; // to rotate letters and numbers on border
			InvalidateRect(hwnd, &rect, FALSE);
			break;

		case ID_HELP40029:
			MessageBox(hwnd, Help, szAppName, MB_OK);
			break;

		case ID_ADVANCEDHELP:
			MessageBox(hwnd, AdvancedHelp, szAppName, MB_OK);
			break;
		} // end of case WM_COMMAND:
		break;

	case WM_KEYDOWN:
		Shifted = GetKeyState(VK_SHIFT) & 0x00008000; // for PlacePiece
		switch(wParam)
		{
		case VK_DELETE:
		case 'B':
		case 'K':
		case 'N':
		case 'P':
		case 'Q':
		case 'R':
			if (placepieces)
				PlacePiece(wParam);
			break;
		case 'Z':
			for (x = 0; ChessEngine[x] != 0; x++)
				;
			for ( ; (x >= 0) && (ChessEngine[x] != '\\'); x--)
				;
			x++;
			MessageBox(hwnd, Fens[f], &ChessEngine[x], MB_OK);
			break;
		case 'X':
			SendMessage (hwnd, WM_COMMAND, ROTATE, 0);
			break;
		case VK_LEFT:
			if (f) {
				f--;
				LeftRight();
			}
			Sleep(5);
			SetFocus(hwnd); // this has to be here for a necessary delay after CHECK or CHECKMATE
			break;
		case VK_RIGHT:
			if (f < fBiggest) {
				f++;
				LeftRight();
			}
			Sleep(5);
			SetFocus(hwnd); // this has to be here for a necessary delay after CHECK or CHECKMATE
			break;
		} // end of switch
		if ((wParam >= '0') && (wParam <= '8')) {
			GoDepth[9] = wParam + 1;
			Size = 12;
		}
		else if ((wParam >= 'A') && (wParam <= 'F')) {
			if ((!placepieces) || (wParam != 'B')) {
				GoDepth2[9] = '1';
				GoDepth2[10] = wParam - 16; // make 'A' a '1'
				Size = 13;
			}
		}
		else if (wParam == '9') {
			GoDepth2[9] = '1';
			GoDepth2[10] = '0';
			Size = 13;
		}
		break;

	case WM_MOUSEMOVE:
		xPos = LOWORD(lParam) - LeftSide;
		yPos = HIWORD(lParam);
		if (!chessenginemove && (movingPiece || placepieces)) {
			InvalidateRect(hwnd, &rect, FALSE);
			UpdateWindow(hwnd);
		}
		break;

	case WM_LBUTTONDOWN:
		if (checkmate)
			break;
		DestroyWindow(hwndCheck);
		chessenginemove = FALSE;
		xPos = LOWORD(lParam) - LeftSide;
		yPos = HIWORD(lParam);
		X = xPos / SquareSize;
		Y = yPos / SquareSize;
		if (!rotated)
			fen = Fen[Y][X];
		else
			fen = Fen[7-Y][7-X];
		if (((WhitesMove) && (fen < 98)) || ((!WhitesMove) && (fen >= 98))) { // 98 is ASCII for 'b'
			if (!rotated)
				Fen[Y][X] = '1';
			else
				Fen[7-Y][7-X] = '1';
			MovedPiece = fen;
			movingPiece = TRUE;
			InvalidateRect(hwnd, &rect, FALSE);
			UpdateWindow(hwnd);
		}
		break;

	case WM_LBUTTONUP: // piece was moved by me
		if (checkmate)
			break;
		if ((!chessengine) && (!notfound))
			LoadChessEngine();
		if (leftright) {
			leftright = FALSE;
			UpdateMoves();
		}
		if (movingPiece) {
			xPos = LOWORD(lParam) - LeftSide;
			yPos = HIWORD(lParam);
			X2 = xPos / SquareSize;
			Y2 = yPos / SquareSize;
			if (!rotated) {
				cX = X; cY = Y; cX2 = X2; cY2 = Y2;
			}
			else {
				cX = 7-X; cY = 7-Y; cX2 = 7-X2; cY2 = 7-Y2;
			}
			ReplacedPiece = Fen[cY2][cX2];
			Fen[cY2][cX2] = MovedPiece;
			if (FALSE == CheckMove()) {
				if ((cX != cX2) || (cY != cY2)) {
					Fen[cY][cX] = MovedPiece;
					Fen[cY2][cX2] = ReplacedPiece;
				}
				choosePiece = FALSE;
				movingPiece = FALSE;
				InvalidateRect(hwnd, &rect, FALSE);
				break; // out of case WM_LBUTTONUP
			}
			InCommon();
		}
		break; // end of WM_LBUTTONUP

	case WM_RBUTTONDOWN: // to have the chess engine move piece
		if (checkmate)
			break;
		DestroyWindow(hwndCheck);
		if ((!chessengine) && (!notfound))
			LoadChessEngine();
		if (notfound)
			break;
		if (leftright) {
			leftright = FALSE;
			UpdateMoves();
		}
		chessenginemove = TRUE;
		for (x = 0; Fens[f][x] != 0; x++)
			;
		WriteFile(IN_Wr, Fens[f], x, &dwBytesWritten, NULL);
		if (Size == 12)
			WriteFile(IN_Wr, GoDepth, 12, &dwWritten, NULL);
		if (Size == 13)
			WriteFile(IN_Wr, GoDepth2, 13, &dwWritten, NULL);

		for (fook2 = 0; fook2 < 0x6FFFFF; fook2++) {
			fileSize = GetFileSize(OUT_Rd, NULL);
			if (!fileSize)
				continue;
			ReadFile(OUT_Rd, cBuf, fileSize, &dwRead, NULL);
			for (x = 0; x < (int)dwRead; x++) {
				if ((0x74736562 == *(DWORD*)&cBuf[x]) && (0x65766F6D == *(DWORD*)&cBuf[x+4])) // bestmove
					break;
			}
			Sleep(5);
			if (x < (int)dwRead) { // if "bestmove" found
				PrevBestMove = *(DWORD*)&cBuf[x+9];
				X = cBuf[x+9] - 'a';
				X2 = cBuf[x+11] - 'a';
				Y = '8' - cBuf[x+10];
				Y2 = '8' - cBuf[x+12];
				if (rotated) {
					X = 7 - X;
					X2 = 7 - X2;
					Y = 7 - Y;
					Y2 = 7 - Y2;
				}
				break;
			}
		} // end of for (fook = 0;...
		if (fook2 >= 0x6FFFFF) {
			MessageBox(hwnd, Fens[f], "The chess engine thought for over 7 million loops over this Fen string:", MB_OK);
			DestroyWindow(hwnd);
			break;
		}
		movingPiece = TRUE;
		if (!rotated)
			fen = Fen[Y][X]; // used in WM_PAINT
		else
			fen = Fen[7-Y][7-X];
		if (!rotated)
			Fen[Y][X] = '1'; // used in WM_PAINT
		else
			Fen[7-Y][7-X] = '1';
		x0 = LeftSide+(SquareSize*X)+(SquareSize/2); // Bresenham's algorithm
		y0 = Border+(SquareSize*Y)+(SquareSize/2);
		x1 = LeftSide+(SquareSize*X2)+(SquareSize/2);
		y1 = Border+(SquareSize*Y2)+(SquareSize/2);
		dx = abs(x1-x0);
		dy = abs(y1-y0);
		if (x0 < x1)
			sx = 1;
		else
			sx = -1;
		if (y0 < y1)
			sy = 1;
		else
			sy = -1;
		err = dx-dy;
hdc = GetDC(hwnd);
		for (skip = 0; (x0 != x1) || (y0 != y1); skip++) { // this shows moving piece
			e2 = 2*err;
			if (e2 > (-dy)) {
				err = err - dy;
				x0 = x0 + sx;
			}
			if (e2 < dx) {
				err = err + dx;
				y0 = y0 + sy; 
			}
			if (0 == (skip % 2)) {
				xPos = x0-LeftSide; // used in WM_PAINT
				yPos = y0; // used in WM_PAINT
				BitBlt(hdcMem2, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
				for (y = 0; y < 8; y++) { // place pieces
					for (x = 0; x < 8; x++) {
						if (!rotated)
							TextOut(hdcMem2, LeftSide+(SquareSize*x), Border+(SquareSize*y), (BYTE*)&Pieces[Fen[y][x]], 1);
						else
							TextOut(hdcMem2, LeftSide+(SquareSize*x), Border+(SquareSize*y), (BYTE*)&Pieces[Fen[7-y][7-x]], 1);
					}
				}
				TextOut(hdcMem2, LeftSide+xPos-(SquareSize/2), yPos-(SquareSize/2), (BYTE*)&Pieces[fen], 1);
				BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem2, 0, 0, SRCCOPY);
			}
		}
ReleaseDC(hwnd, hdc);
		if (!rotated) {
			cX = X; cY = Y; cX2 = X2; cY2 = Y2;
		}
		else {
			cX = 7-X; cY = 7-Y; cX2 = 7-X2; cY2 = 7-Y2;
		}
		MovedPiece = fen;
		ReplacedPiece = Fen[cY2][cX2];
		Fen[cY2][cX2] = MovedPiece;
		CheckMove();
		InCommon();
		break; // end of case WM_RBUTTONDOWN

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		if (first) {
			first = FALSE;
			if (!hdcMem) {
				hdcMem = CreateCompatibleDC(hdc);
				hMemBitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
				SelectObject(hdcMem, hMemBitmap);
				FillRect(hdcMem, &rect, hGreyBrush);
				hdcMem2 = CreateCompatibleDC(hdc);
				hMem2Bitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
				SelectObject(hdcMem2, hMem2Bitmap);
			}
			hOldPen = SelectObject(hdcMem, hBorderPen);
			hOldBrush = SelectObject(hdcMem, hBorderBrush);
			SetBkMode(hdcMem, TRANSPARENT);
			LeftSide = Border;
			Rectangle(hdcMem, LeftSide, 0, LeftSide+AllSquareSize, Border); // top border
			Rectangle(hdcMem, LeftSide, Border+AllSquareSize, LeftSide+AllSquareSize, Border + AllSquareSize + Border); // bottom border
			Rectangle(hdcMem, LeftSide-Border, 0, LeftSide+Border, Border + AllSquareSize + Border); // left border
			Rectangle(hdcMem, LeftSide+AllSquareSize, 0, LeftSide+AllSquareSize+Border, Border + AllSquareSize + Border); // right border
			SelectObject(hdcMem, hOldBrush);
			SelectObject(hdcMem, hOldPen);
			hOldPen = SelectObject(hdcMem, hBeigePen);
			hOldBrush = SelectObject(hdcMem, hBeigeBrush);
			SetTextColor(hdcMem, 0xCCCCCC);
			if (!rotated) {
				letter[0] = 'a';
				for (x = 0; x < AllSquareSize; x += SquareSize, letter[0]++) {
					TextOut(hdcMem, LeftSide+x+(SquareSize/2), Border+AllSquareSize, &letter[0], 1);
					TextOut(hdcMem, LeftSide+x+(SquareSize/2), 0, &letter[0], 1);
				}
				num[0] = '8';
				for (y = 0; y < AllSquareSize; y += SquareSize, num[0]--) {
					TextOut(hdcMem, LeftSide-(Border*3/4), (Border/2)+y+(SquareSize/2), &num[0], 1);
					TextOut(hdcMem, LeftSide+(Border/4)+AllSquareSize, (Border/2)+y+(SquareSize/2), &num[0], 1);
				}
			}
			else {
				letter[0] = 'h';
				for (x = 0; x < AllSquareSize; x += SquareSize, letter[0]--) {
					TextOut(hdcMem, LeftSide+x+(SquareSize/2), Border+AllSquareSize, &letter[0], 1);
					TextOut(hdcMem, LeftSide+x+(SquareSize/2), 0, &letter[0], 1);
				}
				num[0] = '1';
				for (y = 0; y < AllSquareSize; y += SquareSize, num[0]++) {
					TextOut(hdcMem, LeftSide-(Border*3/4), (Border/2)+y+(SquareSize/2), &num[0], 1);
					TextOut(hdcMem, LeftSide+(Border/4)+AllSquareSize, (Border/2)+y+(SquareSize/2), &num[0], 1);
				}
			}
			SelectObject(hdcMem, hOldBrush);
			SelectObject(hdcMem, hOldPen);
			hOldPen = SelectObject(hdcMem, hBeigePen);
			hOldBrush = SelectObject(hdcMem, hBeigeBrush);
			for (y = Border; y < (Border + AllSquareSize); y += SquareSize2) {
				for (x = LeftSide; x < (LeftSide+AllSquareSize); x += SquareSize2)
					Rectangle(hdcMem, x, y, x+SquareSize, y+SquareSize);
			}
			for (y = Border+SquareSize; y < (Border+AllSquareSize); y += SquareSize2) {
				for (x = LeftSide+SquareSize; x < (LeftSide+SquareSize+AllSquareSize); x += SquareSize2)
					Rectangle(hdcMem, x, y, x+SquareSize, y+SquareSize);
			}
			SelectObject(hdcMem, hOldBrush);
			SelectObject(hdcMem, hOldPen);
			hOldBrush = SelectObject(hdcMem, hBrownBrush);
			hOldPen = SelectObject(hdcMem, hBrownPen);
			for (y = Border+SquareSize; y < (Border + AllSquareSize); y += SquareSize2) {
				for (x = LeftSide; x < (LeftSide+AllSquareSize); x += SquareSize2)
					Rectangle(hdcMem, x, y, x+SquareSize, y+SquareSize);
			}
			for (y = Border; y < (Border + AllSquareSize); y += SquareSize2) {
				for (x = LeftSide+SquareSize; x < (LeftSide+SquareSize+AllSquareSize); x += SquareSize2)
					Rectangle(hdcMem, x, y, x+SquareSize, y+SquareSize);
			}
			SelectObject(hdcMem, hOldBrush);
			SelectObject(hdcMem, hOldPen);
			SelectObject(hdcMem2, hFont);
			SetBkMode(hdcMem2, TRANSPARENT);
			SetTextColor(hdcMem2, 0);
		} // end of if (first)
		BitBlt(hdcMem2, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
		for (y = 0; y < 8; y++) { // place pieces
			for (x = 0; x < 8; x++) {
				if (!rotated)
					TextOut(hdcMem2, LeftSide+(SquareSize*x), Border+(SquareSize*y), (BYTE*)&Pieces[Fen[y][x]], 1);
				else
					TextOut(hdcMem2, LeftSide+(SquareSize*x), Border+(SquareSize*y), (BYTE*)&Pieces[Fen[7-y][7-x]], 1);
			}
		}
		if (movingPiece)
			TextOut(hdcMem2, LeftSide+xPos-(SquareSize/2), yPos-(SquareSize/2), (BYTE*)&Pieces[fen], 1);
		BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem2, 0, 0, SRCCOPY);
		EndPaint(hwnd, &ps);
		break;

	case WM_DESTROY:
		if (chessengine)
			WriteFile(IN_Wr, Quit, 7, &dwBytesWritten, NULL);
		RemoveFontResource("ChessAlpha2.ttf");
		DeleteDC(hdcMem);
		DeleteObject(hMemBitmap);
		DeleteDC(hdcMem2);
		DeleteObject(hMem2Bitmap);
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
 }

 //SUB-ROUTINES*******************************************************
BOOL CheckRook(void) // see if this is a legal move
{
	if ((cX == cX2) || (cY == cY2)) {
		returned = TRUE;
		if (cY2 > cY) {
			for (y = cY+1; y < cY2; y++) {
				if (Fen[y][cX] != '1') {
					returned = FALSE;
					break;
				}
			}
		}
		else if (cY2 < cY) {
			for (y = cY-1; y > cY2; y--) {
				if (Fen[y][cX] != '1') {
					returned = FALSE;
					break;
				}
			}
		}
		else if (cX2 > cX) {
			for (x = cX+1; x < cX2; x++) {
				if (Fen[cY][x] != '1') {
					returned = FALSE;
					break;
				}
			}
		}
		else if (cX2 < cX) {
			for (x = cX-1; x > cX2; x--) {
				if (Fen[cY][x] != '1') {
					returned = FALSE;
					break;
				}
			}
		}
		if (returned == TRUE) {
			if (fen == 'r') {
				if (cX == 0)
					bqr = TRUE;
				else if (cX == 7)
					bkr = TRUE;
			}
			else if (fen == 'R') {
				if (cX == 0)
					wqr = TRUE;
				else if (cX == 7)
					wkr = TRUE;
			}
		}
		return returned;
	}
	else
		return FALSE;
}

BOOL CheckKnight(void) // is this a legal move?
{
	if ((cX2 == cX-1) && (cY2 == cY+2)) return TRUE;
	else if ((cX2 == cX+1) && (cY2 == cY+2)) return TRUE;
	else if ((cX2 == cX-2) && (cY2 == cY+1)) return TRUE;
	else if ((cX2 == cX+2) && (cY2 == cY+1)) return TRUE;
	else if ((cX2 == cX-1) && (cY2 == cY-2)) return TRUE;
	else if ((cX2 == cX+1) && (cY2 == cY-2)) return TRUE;
	else if ((cX2 == cX-2) && (cY2 == cY-1)) return TRUE;
	else if ((cX2 == cX+2) && (cY2 == cY-1)) return TRUE;
	else return FALSE;
}

BOOL CheckBishop(void) // is this a legal move?
{
	if (abs(cX2-cX) != abs(cY2-cY))
		return FALSE;
	if ((cX2 > cX) && (cY2 > cY)) {
		for (x = cX+1, y = cY+1; x < cX2; x++, y++) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	else if ((cX2 < cX) && (cY2 > cY)) {
		for (x = cX-1, y = cY+1; x > cX2; x--, y++) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	else if ((cX2 > cX) && (cY2 < cY)) {
		for (x = cX+1, y = cY-1; x < cX2; x++, y--) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	else if ((cX2 < cX) && (cY2 < cY)) {
		for (x = cX-1, y = cY-1; x > cX2; x--, y--) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	return FALSE;
}

BOOL CheckQueen(void) // is this a legal move?
{
	if (cX2 == cX) {
		if (cY2 > cY) {
			for (y = cY+1; y < cY2; y++)
				if (Fen[y][cX] != '1')
					return FALSE;
		}
		else { // if (cY2 <= cY) {
			for (y = cY-1; y > cY2; y--) {
				if (Fen[y][cX] != '1')
					return FALSE;
			}
		}
		return TRUE;
	}
	else if (cY2 == cY) {
		if (cX2 > cX) {
			for (x = cX+1; x < cX2; x++) {
				if (Fen[cY][x] != '1')
					return FALSE;
			}
		}
		else { // if (cX2 <= cX) {
			for (x = cX-1; x > cX2; x--) {
				if (Fen[cY][x] != '1')
					return FALSE;
			}
		}
		return TRUE;
	}
	else if (abs(cX2-cX) != abs(cY2-cY))
		return FALSE;
	else if ((cX2 > cX) && (cY2 > cY)) {
		for (x = cX+1, y = cY+1; x < cX2; x++, y++) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	else if ((cX2 < cX) && (cY2 > cY)) {
		for (x = cX-1, y = cY+1; x > cX2; x--, y++) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	else if ((cX2 > cX) && (cY2 < cY)) {
		for (x = cX+1, y = cY-1; x < cX2; x++, y--) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	else if ((cX2 < cX) && (cY2 < cY)) {
		for (x = cX-1, y = cY-1; x > cX2; x--, y--) {
			if (Fen[y][x] != '1')
				return FALSE;
		}
		return TRUE;
	}
	return FALSE;
}

BOOL CheckMove(void)
{
 	if ((cX2 == cX) && (cY2 == cY))
		return FALSE;
	switch (MovedPiece)
	{
	case 'p':
		enpassant1 = FALSE;
		if (cY2 == 7) choosePiece = TRUE; // promote the pawn
		else choosePiece = FALSE;
		if ((cY2 == cY+1) && (cX2 == cX) && (ReplacedPiece == '1')) // moving down
			return TRUE;
		if (ReplacedPiece >= 98) // can't take a black piece
			return FALSE;
		if ((cY2 == cY+1) && (ReplacedPiece != '1') && ((cX2 == cX+1) || (cX2 == cX-1))) // taking something
			return TRUE;
		if ((cY == 1) && (cX2 == cX) && (ReplacedPiece == '1') && ((cY2 == 2) || (cY2 == 3))) // first move
			return TRUE;
		if ((EnPassant[0] == Letters[cX2])
			&& (((cX-cX2) == 1) || ((cX2-cX) == 1))
			&& (EnPassant[1] == (8-cY2)+'0')
			&& ((cY2-cY) == 1)) { // En Passant
				enpassant1 = TRUE;
				Fen[cY2-1][cX2] = '1';
				return TRUE;
		}
		return FALSE;
	case 'P':
		enpassant2 = FALSE;
		if (cY2 == 0) choosePiece = TRUE; // promote the pawn
		else choosePiece = FALSE;
		if ((cY2 == cY-1) && (cX2 == cX) && (ReplacedPiece == '1')) // moving up
			return TRUE;
		if ((ReplacedPiece != '1') && (ReplacedPiece < 98)) // can't take a white piece
			return FALSE;
		if ((cY2 == cY-1) && (ReplacedPiece != '1') && ((cX2 == cX+1) || (cX2 == cX-1))) // taking something
			return TRUE;
		if ((cY == 6) && (cX2 == cX) && (ReplacedPiece == '1') && ((cY2 == 5) || (cY2 == 4))) // first move
			return TRUE;
		if ((EnPassant[0] == Letters[cX2])
		 && (((cX-cX2) == 1) || ((cX2-cX) == 1))
		 && (EnPassant[1] == (8-cY2)+'0')
		 && ((cY-cY2) == 1)) { // En Passant
			enpassant2 = TRUE;
			Fen[cY2+1][cX2] = '1';
			return TRUE;
		}
		return FALSE;
	case 'n':
		if (ReplacedPiece >= 98)
			return FALSE;
		if (CheckKnight())
			return TRUE;
		else
			return FALSE;
	case 'N':
		if ((ReplacedPiece != '1') && (ReplacedPiece < 98))
			return FALSE;
		if (CheckKnight())
			return TRUE;
		else
			return FALSE;
	case 'b':
		if (ReplacedPiece >= 98)
			return FALSE;
		if (CheckBishop())
			return TRUE;
		else
			return FALSE;
	case 'B':
		if ((ReplacedPiece != '1') && (ReplacedPiece < 98))
			return FALSE;
		if (CheckBishop())
			return TRUE;
		else
			return FALSE;
	case 'r':
		if (ReplacedPiece >= 98) {
			return FALSE;
		}
		if (CheckRook())
			return TRUE;
		else
			return FALSE;
	case 'R':
		if ((ReplacedPiece != '1') && (ReplacedPiece < 98)) {
			return FALSE;
		}
		if (CheckRook())
			return TRUE;
		else
			return FALSE;
	case 'q':
		if (ReplacedPiece >= 98)
			return FALSE;
		if (CheckQueen())
			return TRUE;
		else
			return FALSE;
	case 'Q':
		if ((ReplacedPiece != '1') && (ReplacedPiece < 98))
			return FALSE;
		if (CheckQueen())
			return TRUE;
		else
			return FALSE;
	case 'k':
		if (ReplacedPiece >= 98)
			return FALSE;
		if ((bk == FALSE) && (bkr == FALSE)) { // if neither king nor the king's rook has moved
			if ((cX == 4) && (cX2 == 6) && (cY == 0)) { // CASTLE ON KING'S SIDE  (the King has already moved)
				if ((ReplacedPiece == '1') && (Fen[0][5] == '1') && (Fen[0][6] == 'k') && (Fen[0][7] == 'r')) {
					if (CheckKing(4, 0, BlackKing))
						return FALSE;
					if (CheckKing(5, 0, BlackKing))
						return FALSE;
					if (CheckKing(6, 0, BlackKing))
						return FALSE;
					*(DWORD*)&Fen[0][4] = 0x316B7231; // 1rk1 (making 4 moves at once (well, the king was already there))
					bk = bkr = TRUE;
					return TRUE;
				}
			}
			else if ((cX == 4) && (cX2 == 2) && (cY == 0)) { // CASTLE ON QUEEN'S SIDE  (the King has already moved)
				if ((bk == TRUE) && (bqr == TRUE))
					return FALSE; // king or rook moved
				if ((ReplacedPiece == '1') && (Fen[0][3] == '1') && (Fen[0][2] == 'k') && (Fen[0][1] == '1') && (Fen[0][0] == 'r')) {
					if (CheckKing(2, 0, BlackKing))
						return FALSE;
					if (CheckKing(3, 0, BlackKing))
						return FALSE;
					if (CheckKing(4, 0, BlackKing))
						return FALSE;
					*(DWORD*)&Fen[0][1] = 0x31726B31; // 1kr1
					Fen[0][0] = '1';
					bk = bqr = TRUE;
					return TRUE;
				}
			}
		}
		if (((cX2 == cX+1) || (cX2 == cX-1) || (cX2 == cX)) && ((cY2 == cY+1) || (cY2 == cY-1) || (cY2 == cY))) {
			bk = TRUE;
			return TRUE;
		}
		else
			return FALSE;
	case 'K':
		if ((ReplacedPiece != '1') && (ReplacedPiece < 98))
			return FALSE;
		if ((wk == FALSE) && (wkr == FALSE)) {
			if ((cX == 4) && (cX2 == 6) && (cY == 7)) { // king was already moved
				if ((ReplacedPiece == '1') && (Fen[7][5] == '1') && (Fen[7][6] == 'K') && (Fen[7][7] == 'R')) {
					if (CheckKing(4, 7, WhiteKing))
						return FALSE;
					if (CheckKing(5, 7, WhiteKing))
						return FALSE;
					if (CheckKing(6, 7, WhiteKing))
						return FALSE;
					*(DWORD*)&Fen[7][4] = 0x314B5231; // 1RK1
					wk = wkr = TRUE;
					return TRUE;
				}
			}
			else if ((cX == 4) && (cX2 == 2) && (cY == 7)) {
				if ((wk == TRUE) && (wqr == TRUE))
					return FALSE; // king or rook moved
				if ((ReplacedPiece == '1') && (Fen[7][3] == '1') && (Fen[7][2] == 'K') && (Fen[7][1] == '1') && (Fen[7][0] == 'R')) {
					if (CheckKing(2, 7, WhiteKing))
						return FALSE;
					if (CheckKing(3, 7, WhiteKing))
						return FALSE;
					if (CheckKing(4, 7, WhiteKing))
						return FALSE;
					*(DWORD*)&Fen[7][1] = 0x31524b31; // 1KR1
					Fen[7][0] = '1';
					wk = wqr = TRUE;
					return TRUE;
				}
			}
		}
		if (((cX2 == cX+1) || (cX2 == cX-1) || (cX2 == cX)) && ((cY2 == cY+1) || (cY2 == cY-1) || (cY2 == cY))) {
			wk = TRUE;
			return TRUE;
		}
		else
			return FALSE;
	}
	return FALSE;
}

int CheckKing(int KingX, int KingY, int King)
{
	returned = 0;
	if (KingX) { // check left
		if (((Fen[KingY][KingX-1] == 'K') && (King == BlackKing)) || ((Fen[KingY][KingX-1] == 'k') && (King == WhiteKing)))
			return DiscoveredCheck;
		for (x = KingX-1; x >= 0; x--) {
			if (Fen[KingY][x] != '1') {
				if (((Fen[KingY][x] == 'R') && (King == BlackKing)) || ((Fen[KingY][x] == 'r') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[KingY][x] == 'Q') && (King == BlackKing)) || ((Fen[KingY][x] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
	if (KingX < 7) { // check right
		if (((Fen[KingY][KingX+1] == 'K') && (King == BlackKing)) || ((Fen[KingY][KingX+1] == 'k') && (King == WhiteKing)))
			return DiscoveredCheck;
		for (x = KingX+1; x < 8; x++) {
			if (Fen[KingY][x] != '1') {
				if (((Fen[KingY][x] == 'R') && (King == BlackKing)) || ((Fen[KingY][x] == 'r') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[KingY][x] == 'Q') && (King == BlackKing)) || ((Fen[KingY][x] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
	if (KingY < 7) { // check down
		if (((Fen[KingY+1][KingX] == 'K') && (King == BlackKing)) || ((Fen[KingY+1][KingX] == 'k') && (King == WhiteKing)))
			return DiscoveredCheck;
		for (y = KingY+1; y < 8; y++) { // top y is 0
			if (Fen[y][KingX] != '1') {
				if (((Fen[y][KingX] == 'R') && (King == BlackKing)) || ((Fen[y][KingX] == 'r') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[y][KingX] == 'Q') && (King == BlackKing)) || ((Fen[y][KingX] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
	if (KingY) { // check up
		if (((Fen[KingY-1][KingX] == 'K') && (King == BlackKing)) || ((Fen[KingY-1][KingX] == 'k') && (King == WhiteKing)))
			return DiscoveredCheck;
		for (y = KingY-1; y >= 0; y--) { // top y is 0
			if (Fen[y][KingX] != '1') {
				if (((Fen[y][KingX] == 'R') && (King == BlackKing)) || ((Fen[y][KingX] == 'r') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[y][KingX] == 'Q') && (King == BlackKing)) || ((Fen[y][KingX] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
/////////
	if ((KingX < 7) && (KingY > 0)) { // check up and right
		if ((King == WhiteKing) && (Fen[KingY-1][KingX+1] == 'p'))
			return EitherOne;
		if (((King == WhiteKing) && (Fen[KingY-1][KingX+1] == 'k')) || ((King == BlackKing) && (Fen[KingY-1][KingX+1] == 'K')))
			return DiscoveredCheck;
		for (z = 1; ((KingY-z) >= 0) && ((KingX+z) < 8); z++) {
			if (Fen[KingY-z][KingX+z] != '1') {
				if (((Fen[KingY-z][KingX+z] == 'B') && (King == BlackKing)) || ((Fen[KingY-z][KingX+z] == 'b') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[KingY-z][KingX+z] == 'Q') && (King == BlackKing)) || ((Fen[KingY-z][KingX+z] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
	if ((KingX > 0) && (KingY > 0)) { // check up and left
		if ((King == WhiteKing) && (Fen[KingY-1][KingX-1] == 'p'))
			return EitherOne;
		if (((King == WhiteKing) && (Fen[KingY-1][KingX-1] == 'k')) || ((King == BlackKing) && (Fen[KingY-1][KingX-1] == 'K')))
			return DiscoveredCheck;
		for (z = 1; ((KingY-z) >= 0) && ((KingX-z) >= 0); z++) {
			if (Fen[KingY-z][KingX-z] != '1') {
				if (((Fen[KingY-z][KingX-z] == 'B') && (King == BlackKing)) || ((Fen[KingY-z][KingX-z] == 'b') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[KingY-z][KingX-z] == 'Q') && (King == BlackKing)) || ((Fen[KingY-z][KingX-z] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
 	}
	if ((KingX > 0) && (KingY < 7)) { // check down and left
		if ((King == BlackKing) && (Fen[KingY+1][KingX-1] == 'P'))
			return EitherOne;
		if ((King == BlackKing) && (Fen[KingY+1][KingX-1] == 'K'))
			return DiscoveredCheck;
		for (z = 1; ((KingY+z) < 8) && ((KingX-z) >= 0); z++) {
			if (Fen[KingY+z][KingX-z] != '1') {
				if (((Fen[KingY+z][KingX-z] == 'B') && (King == BlackKing)) || ((Fen[KingY+z][KingX-z] == 'b') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[KingY+z][KingX-z] == 'Q') && (King == BlackKing)) || ((Fen[KingY+z][KingX-z] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
	if ((KingX < 7) && (KingY < 7)) { // check down and right
		if ((King == BlackKing) && (Fen[KingY+1][KingX+1] == 'P'))
			return EitherOne;
		if ((King == BlackKing) && (Fen[KingY+1][KingX+1] == 'K'))
			return DiscoveredCheck;
		for (z = 1; ((KingY+z) < 8) && ((KingX+z) < 8); z++) {
			if (Fen[KingY+z][KingX+z] != '1') {
				if (((Fen[KingY+z][KingX+z] == 'B') && (King == BlackKing)) || ((Fen[KingY+z][KingX+z] == 'b') && (King == WhiteKing)))
					return EitherOne;
				if (((Fen[KingY+z][KingX+z] == 'Q') && (King == BlackKing)) || ((Fen[KingY+z][KingX+z] == 'q') && (King == WhiteKing)))
					return EitherOne;
				break;
			}
		}
	}
// check check by a knight
	if (King == 200) Knight = 'n';
	else Knight = 'N';			
	if (((KingY+2) < 8) && (KingX+1 < 8) && (Fen[KingY+2][KingX+1] == Knight))
		returned = EitherOne;
	else if (((KingY+1) < 8) && (KingX+2 < 8) && (Fen[KingY+1][KingX+2] == Knight))
		returned = EitherOne;
	else if (((KingY-1) >= 0) && (KingX+2 < 8) && (Fen[KingY-1][KingX+2] == Knight))
		returned = EitherOne;
	else if (((KingY-2) >= 0) && (KingX+1 < 8) && (Fen[KingY-2][KingX+1] == Knight))
		returned = EitherOne;
	else if (((KingY-2) >= 0) && (KingX-1 >= 0) && (Fen[KingY-2][KingX-1] == Knight))
		returned = EitherOne;
	else if (((KingY-1) > 0) && (KingX-2 >= 0) && (Fen[KingY-1][KingX-2] == Knight))
		returned = EitherOne;
	else if (((KingY+1) < 8) && (KingX-2 >= 0) && (Fen[KingY+1][KingX-2] == Knight))
		returned = EitherOne;
	else if (((KingY+2) < 8) && (KingX-1 >= 0) && (Fen[KingY+2][KingX-1] == Knight))
		returned = EitherOne;
	return returned;
}

void UpdateMoves(void)
{
	for (x = 87; Fens[f][x] != ' '; x++)
		;
	for (x++; Fens[f][x] != ' '; x++)
		;
	for (x++, y = 0; Fens[f][x] != ' '; x++, y++) {
		if (y == 0)
			HalfMoves = Fens[f][x] - '0';
		else if (y == 1) {
			HalfMoves *= 10;
			HalfMoves += Fens[f][x] - '0';
		}
	}
	for (x++; Fens[f][x] != '\r'; x++) {
		FullMoves = Fens[f][x] - '0';
		x++;
		if (Fens[f][x] == '\r')
			break;
		FullMoves *= 10;
		FullMoves += (Fens[f][x] - '0');
		x++;
		if (Fens[f][x] == '\r')
			break;
		FullMoves *= 10;
		FullMoves += (Fens[f][x] - '0');
	}
}

void ItsDiscoveredCheck(void)
{
	if ((cX != cX2) || (cY != cY2)) { // move it back
		Fen[cY][cX] = MovedPiece;
		Fen[cY2][cX2] = ReplacedPiece;
		if (MovedPiece == 'K') {
			WhiteKingX = cX;
			WhiteKingY = cY;
		}
		else if (MovedPiece == 'k') {
			BlackKingX = cX;
			BlackKingY = cY;
		}
	}
	itscheck = FALSE;
	itsdiscoveredcheck = TRUE;
	fen = ReplacedPiece; // for InCommon
}

void CheckBothKings(KingX, KingY, King)
{	
	returned = CheckKing(KingX, KingY, King);
	if (returned == Check) 
		itscheck = TRUE;
	if (returned == EitherOne) {
		if (WhitesMove) {
			if (King == BlackKing)
				itscheck = TRUE;
			else if (!frompromoted)
  				ItsDiscoveredCheck();
			else
				itscheck = TRUE;
		}
		else {
			if (King == WhiteKing)
				itscheck = TRUE;
			else if (!frompromoted)
  				ItsDiscoveredCheck();
			else
				itscheck = TRUE;
		}
	}
	else if (returned == DiscoveredCheck)
		ItsDiscoveredCheck();
}

int CALLBACK PromotionProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		CheckRadioButton(hwndDlg, IDC_RADIO1, IDC_RADIO4, IDC_RADIO1);
		SetFocus(hwndDlg);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
		case IDCANCEL:
			if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADIO1))
				Promoted = 'Q';
			else if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADIO2))
				Promoted = 'R';
			else if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADIO3))
				Promoted = 'B';
			else if (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADIO4))
				Promoted = 'N';
			if (cY2 == 0)
				Fen[cY2][cX2] = Promoted;
			else if (cY2 = 7)
				Fen[cY2][cX2] = Promoted + 0x20;
			EndDialog (hwndDlg, TRUE);
			return TRUE;
		}
	}
	return 0;
}

int CALLBACK CheckProc(HWND hwndCheck, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_LBUTTONDOWN)
		DestroyWindow(hwndCheck);
	else if (message == WM_DESTROY)
		itscheck = FALSE;
	return 0;
}

int CALLBACK CheckMateProc(HWND hwndCheckMate, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_LBUTTONDOWN)
		DestroyWindow(hwndCheckMate);
	else if (message == WM_DESTROY)
		checkmate = FALSE;
	return 0;
}

void GetFensData(void)
{ // if the below are FALSE, they indicate that those pieces can castle!
	wk = wkr = wqr = bk = bkr = bqr = TRUE;
	x = 87;
	if (Fens[f][x] == 'K') {
		wk = wkr = FALSE;
		x++;
	}
	if (Fens[f][x] == 'Q') {
		wk = wqr = FALSE;
		x++;
	}
	if (Fens[f][x] == 'k') {
		bk = bkr = FALSE;
		x++;
	}
	if (Fens[f][x] == 'q') {
		bk = bqr = FALSE;
		x++;
	}
	x++; // past space
	if (Fens[f][x] == ' ') // happens with no KQkq
		x++;
	if (Fens[f][x] != '-') {
		EnPassant[0] = Fens[f][x];
		EnPassant[1] = Fens[f][x+1];
	}
}

void Enpassant(int x)
{
	Fens[f][x++] = ' ';
	Fens[f][x++] = EnPassant[0];
	if (EnPassant[0] != '-')
		Fens[f][x++] = EnPassant[1];
	Fens[f][x++] = ' ';
	for (y = 13, z = 0; Fens[f][y] != ' '; y++) {
		if (Fens[f][y] == '1')
			z++;
	}
	if (z == NumberOfOnes+1) {
		NumberOfOnes = z;
		HalfMoves = 0;
	}
	else if ((Fen[cY2][cX2] != 'P') && (Fen[cY2][cX2] != 'p'))
		HalfMoves++;
	else
		HalfMoves = 0;
	if (HalfMoves < 10)
		Fens[f][x++] = (char)(HalfMoves + '0');
	else {
		Fens[f][x++] = (char)((HalfMoves/10) + '0');
		Fens[f][x++] = (char)((HalfMoves%10)+ '0');
	}
	Fens[f][x++] = ' ';
	if (FullMoves < 10)
		Fens[f][x++] = (char)(FullMoves + '0');
	else if (FullMoves <= 99) {
		Fens[f][x++] = (char)((FullMoves/10) + '0');
		Fens[f][x++] = (char)((FullMoves%10)+ '0');
	}
	else {
		Fens[f][x++] = (char)((FullMoves/100) + '0');
		Fens[f][x++] = (char)(((FullMoves%100)/10) + '0');
		Fens[f][x++] = (char)((FullMoves%10)+ '0');
	}
	Fens[f][x++] = '\r';
	Fens[f][x++] = '\n';
	Fens[f][x++] = 0;
	endoffens = x;
}

void PlacePiece(WPARAM wParam)
{
	if (wParam == VK_DELETE)
		piece = '1';
	else {
		piece = wParam;
		if (!Shifted)
			piece += 0x20; // make lower case
	}
	cX = xPos / SquareSize;
	cY = yPos / SquareSize;
	if (rotated) {
		cX = 7 - cX;
		cY = 7 - cY;
	}
	Fen[cY][cX] = piece; // xPos & yPos from WM_MOUSEMOVE
	Fens[f][13+(9*cY)+cX] = piece;
	for (x = 0; Fens[f][x] != 0; x++)
		;
	endoffens = x+1;
	OpenClipboard(hwnd);
	EmptyClipboard();
	hGlob = LocalAlloc(GMEM_FIXED, 108); // (divisible by 4) GlobalAlloc
	strncpy((char*)hGlob, Fens[f], endoffens); // endoffens from Enpassant
	hClipboard = SetClipboardData(CF_TEXT, hGlob);
	CloseClipboard();
	movingPiece = FALSE;
	InvalidateRect(hwnd, &rect, FALSE);
}

void LeftRight(void)
{
	GetFensData();
	x = 13;
	for (z = 0; z < 8; z++) { // update Fen from Fens
		for (y = 0; y < 8; y++)
			Fen[z][y] = Fens[f][x++];
		x++;
	}
	if (Fens[f][85] == 'w') {
		WhitesMove = TRUE;
		SetWindowText(hwnd, WhiteMoves);
	}
	else if (Fens[f][85] == 'b') {
		WhitesMove = FALSE;
		SetWindowText(hwnd, BlackMoves);
	}
	DestroyWindow(hwndCheck);
	if (checkmate)
		DestroyWindow(hwndCheckMate);
	leftright = TRUE;
	if (Fens[f][0] == 'C')
		hwndCheck = CreateDialog(hInst, TEXT("CHECK"), hwnd, (DLGPROC)CheckProc);
	else if (hwndCheck)
		DestroyWindow(hwndCheck);
	if (Fens[f][1] == 'M')
		hwndCheckMate = CreateDialog(hInst, TEXT("CHECKMATE"), hwnd, (DLGPROC)CheckMateProc);
	else if (hwndCheckMate)
		DestroyWindow(hwndCheckMate);
	InvalidateRect(hwnd, &rect, FALSE);
	UpdateWindow(hwnd);
}

void InCommon(void)
{
	for (BlackKingY = 0; BlackKingY < 8; BlackKingY++) {
		for (BlackKingX = 0; BlackKingX < 8; BlackKingX++) {
			if (Fen[BlackKingY][BlackKingX] == 'k') {
				BlackKingcX = BlackKingX;
				BlackKingcY = BlackKingY;
			}
		}
	}
	for (WhiteKingY = 0; WhiteKingY < 8; WhiteKingY++) {
		for (WhiteKingX = 0; WhiteKingX < 8; WhiteKingX++) {
			if (Fen[WhiteKingY][WhiteKingX] == 'K') {
				WhiteKingcX = WhiteKingX;
				WhiteKingcY = WhiteKingY;
			}
		}
	}
	CheckBothKings(BlackKingcX, BlackKingcY, BlackKing); // for check or discovered check
	CheckBothKings(WhiteKingcX, WhiteKingcY, WhiteKing);
	if (itsdiscoveredcheck) {
		itsdiscoveredcheck = FALSE;
		Fen[cY][cX] = MovedPiece;
		Fen[cY2][cX2] = ReplacedPiece;
		if (enpassant1) { // put white pawn back
			Fen[cY2-1][cX2] = 'P';
		}
		else if (enpassant2) { // put black pawn back
			Fen[cY2+1][cX2] = 'p';
		}
		choosePiece = FALSE;
		movingPiece = FALSE;
		InvalidateRect(hwnd, &rect, FALSE);
		return;
	}
	else {
		WhitesMove ^= 1;
		if (WhitesMove)
			SetWindowText(hwnd, WhiteMoves);
		else
			SetWindowText(hwnd, BlackMoves);
		if (choosePiece) {
			choosePiece = FALSE;
			promoted = TRUE;
			DialogBox(hInst, TEXT("PROMOTION"), hwnd, PromotionProc);
		}
	}
	if (Promoted == 'x') // not a promoted pawn
		Fen[cY2][cX2] = fen; // moved piece
	else {
		Promoted = 'x';
		frompromoted = TRUE;
		if (cY2 == 0)
			CheckBothKings(BlackKingcX, BlackKingcY, BlackKing); // for itscheck
		else if (cY2 == 7)
			CheckBothKings(WhiteKingcX, WhiteKingcY, WhiteKing);
		frompromoted = FALSE;
	}
	f++;
	fBiggest = f;
	for (x = 0; x < 13; x++)
		Fens[f][x] = OrigFenString[x];
	for (z = 0; z < 8; z++) { // update Fens from Fen
		for (y = 0; y < 8; y++)
			Fens[f][x++] = Fen[z][y];
		Fens[f][x++] = '/';
	}
	Fens[f][x-1] = ' ';
	if (WhitesMove) {
		Fens[f][x++] = 'w';
		FullMoves++;
	}
	else
		Fens[f][x++] = 'b';
	Fens[f][x++] = ' ';
	if ((ReplacedPiece == 'r') && (cX2 == 7) && (cY2 == 0)) bkr = TRUE;
	else if ((ReplacedPiece == 'r') && (cX2 == 0) && (cY2 == 0)) bqr = TRUE;
	else if ((ReplacedPiece == 'R') && (cX2 == 7) && (cY2 == 7)) wkr = TRUE;
	else if ((ReplacedPiece == 'R') && (cX2 == 0) && (cY2 == 7)) wqr = TRUE;
	if (bkr && bqr) bk = TRUE;
	if (wkr && wqr) wk = TRUE;
	y = x; // 87 (KQkq or whatever)
	if ((wk == FALSE) && (wkr == FALSE)) Fens[f][x++] = 'K';
	if ((wk == FALSE) && (wqr == FALSE)) Fens[f][x++] = 'Q';
	if ((bk == FALSE) && (bkr == FALSE)) Fens[f][x++] = 'k';
	if ((bk == FALSE) && (bqr == FALSE)) Fens[f][x++] = 'q';
	if (x == y)
		Fens[f][x++] = '-';
	if ((cY == 1) && (cY2 == 3) && (Fen[cY2][cX2] == 'p')) { // show en passant is possible
		EnPassant[0] = Letters[cX];
		EnPassant[1] = '6';
		Enpassant(x);
	}
	else if ((cY == 6) && (cY2 == 4) && (Fen[cY2][cX2] == 'P')) { // show en passant is possible
		EnPassant[0] = Letters[cX];
		EnPassant[1] = '3';
		Enpassant(x);
	}
	else {
		EnPassant[0] = '-';
		EnPassant[1] = '-';
		Enpassant(x);
	}
	OpenClipboard(hwnd);
	EmptyClipboard();
	hGlob = LocalAlloc(GMEM_FIXED, 108); // (divisible by 4) GlobalAlloc
	strncpy((char*)hGlob, Fens[f], endoffens); // endoffens from Enpassant
	hClipboard = SetClipboardData(CF_TEXT, hGlob);
	CloseClipboard();
	movingPiece = FALSE;
	InvalidateRect(hwnd, &rect, FALSE);
	UpdateWindow(hwnd);
//check for CHECKMATE:
	if (chessengine) {
		for (x = 0; Fens[f][x] != 0; x++)
			;
		WriteFile(IN_Wr, Fens[f], x, &dwBytesWritten, NULL);
		WriteFile(IN_Wr, "go depth 1\r\n\0", 12, &dwWritten, NULL);
		for (fook2 = 0; fook2 < 1000000; fook2++) {
			fileSize = GetFileSize(OUT_Rd, NULL);
			if (!fileSize)
				continue;
			ReadFile(OUT_Rd, cBuf, fileSize, &dwRead, NULL);
			done = FALSE;
			for (x = 0; x < (int)dwRead; x++) {
				if ((*(DWORD*)&cBuf[x] == 0x31613161) && (*(WORD*)&cBuf[x-3] == 0x7670)) { // "pv a1a1"
					done = TRUE;
					break;
				}
				if ((0x74736562 == *(DWORD*)&cBuf[x]) && (0x65766F6D == *(DWORD*)&cBuf[x+4])) // bestmove
					break;
			}
			if (done)
				break;
			Sleep(5);
			if ((x < (int)dwRead) && !done) { // if "bestmove" found
				X = cBuf[x+9] - 'a';
				X2 = cBuf[x+11] - 'a';
				Y = '8' - cBuf[x+10];
				Y2 = '8' - cBuf[x+12];
				if (((X == X2) && (Y == Y2)) || (X > 7) || (X < 0) || (PrevBestMove == *(DWORD*)&cBuf[x+9]))
					done = TRUE;
				PrevBestMove = *(DWORD*)&cBuf[x+9];
				break;
			}
		}
		if (fook2 >= 1000000)
			MessageBox(hwnd, "This chess engine doesn't indicate checkmate!", "", MB_OK);
		if (done) {
			done = FALSE;
			if (itscheck) {
				Fens[f][1] = 'M';
				checkmate = TRUE;
				hwndCheckMate = CreateDialog(hInst, TEXT("CHECKMATE"), hwnd, (DLGPROC)CheckMateProc);
			}
		}
		else if (itscheck) {
			Fens[f][0] = 'C';
			hwndCheck = CreateDialog(hInst, TEXT("CHECK"), hwnd, (DLGPROC)CheckProc);
		}
	} // end of if (chessengine)
	else if (itscheck) {
		Fens[f][0] = 'C';
		hwndCheck = CreateDialog(hInst, TEXT("CHECK"), hwnd, (DLGPROC)CheckProc);
	}
	Sleep(5);
	SetFocus(hwnd); // this has to be here for a necessary delay after CHECK or CHECKMATE
}

void LoadChessEngine(void)
{
	if (INVALID_HANDLE_VALUE != (hFile = CreateFile(CurrentEngine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))) {
		if (fileSize = GetFileSize(hFile, NULL)) {
			for (x = 0; x < MAX_PATH; x++)
				ChessEngine[x] = 0;
			ReadFile(hFile, ChessEngine, fileSize, &dwBytesRead, NULL); // current engine name
			CloseHandle(hFile);
			hFile = NULL;
			if (INVALID_HANDLE_VALUE != FindFirstFile(ChessEngine, &fd)) {
				saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
				saAttr.bInheritHandle = TRUE; 
				saAttr.lpSecurityDescriptor = NULL; 
				CreatePipe(&OUT_Rd, &OUT_Wr, &saAttr, 0);
				CreatePipe(&IN_Rd, &IN_Wr, &saAttr, 0);
				SetHandleInformation(OUT_Rd, HANDLE_FLAG_INHERIT, 0);
				SetHandleInformation(IN_Wr, HANDLE_FLAG_INHERIT, 0);
				ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
				ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
				siStartInfo.cb = sizeof(STARTUPINFO);
				siStartInfo.hStdOutput = OUT_Wr;
				siStartInfo.hStdInput = IN_Rd;
				siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
				if (0 != CreateProcess(ChessEngine, ChessEngine, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &siStartInfo, &piProcInfo)) {
					CloseHandle(piProcInfo.hProcess); // these are the normal procedures
					CloseHandle(piProcInfo.hThread);
					CloseHandle(OUT_Wr);
					CloseHandle(IN_Rd);
				}
				chessengine = TRUE;
				notfound = FALSE;
			}
		}
		else
			MessageBox(hwnd, "Filesize is 0", ChessEngine, MB_OK);
	}
	else
		notfound = TRUE;
}
