#include <windows.h>
#include <stdio.h> // for sprintf_s
#include "resource.h"
#define GREEN 0x307000
#define RED 0xE8
#define BLUE 0xF0A080

char *pbn, *lin, *p, End;
int W, pl, w, n, e, s, v, x, y, z, X, SaveX, xBid, yBid, xOld, yOld, one, passes, CardTop, index, Title, TitleAndMenu, HelpType;
//int nx, ny, sx, sy, wx, wy, ex, ey;
int pbnDiamondSize, pbnClubSize, DiamondsLoc, BidLoc, cp, Y;
int tempSuits[4], SuitLengths[4][4]; // [WNES][SHCD]
int WestSuitsCopy[4], NorthSuitsCopy[4], EastSuitsCopy[4], SouthSuitsCopy[4];
int SuitHeight, SuitWidth, SpadeWidth, HeartWidth, DiamondWidth, ClubWidth;
int pts[] = {4,3,2,1,0,0,0,0,0,0,0,0,0};
int wOffset, nOffset, eOffset, sOffset;
DWORD ScreenWidth, ScreenHeight, xCenter, yCenter, CardWidth, CardHeight;
DWORD WestLeft = 10, WestTop, DummyLeft, EastLeft, EastBiddingLeft, EastTop, HandLeft, HandTop;
DWORD WestCard, NorthCard, EastCard, SouthCard, EWPlayedTop, EWCardTop, NorthCardTop, SouthCardTop;
DWORD fileSize, fileSize2, RandomFileSize, dwBytesRead, dwBytesWritten, dwRandomBytesRead = 0;
DWORD Offset, RandomOffset[1], OldRandomOffset[1];
BYTE Balanced[4], Doubletons[4];
BYTE SuitSymbols[] = "\xAA\xA9\xA7\xA8"; // S H C D
BYTE highcardpoints[4], lengthpoints[4];
BYTE b, Bidder, Declarer, Dealer = 3, DealerCopy, PreviousDealer, OrigDealer = 3; // Dealer becomes the player to the left of South in NewDeal
BYTE currentcard, cardsplayed, tricksplayed, pbnsuit, pbnplayer;
char Char;
char *RandomBytes;
char *PreviousGames;
char *HelpBuf;
char Savedtime[4124];
char SavedGames[] = "C:\\Users\\Public\\BridgeGames.txt";
char SaveDiamonds[14], SaveClubs[14];
//char Comments[4096];
char BidSuit;
char suitled, highcard, hightrump;
char szAppName[] = "Bridge2";
char Deal[] = "WNES";
char Suit[] = "AKQJT98765432";
char Suits[] = "SHCD";
char card[1], suit[1];
char TimesNewRoman[] = "Times New Roman";
char Symbol[] = "Symbol";
char West[] = "WEST", North[] = "NORTH", East[] = "EAST", South[] = "SOUTH";
char Bidding[] = "     's bid";
char TricksLost[] = "Tricks Lost: 0";
char Bid[32][20]; // 8 rows of 4 bids each
char BidCopy[32][20];
char LastBid[16] = "Bid:       ";
char Spade[] = " Spade";
char Spades[] = " Spades";
char Heart[] = " Heart";
char Hearts[] = " Hearts";
char Diamond[] = " Diamond";
char Diamonds[] = " Diamonds";
char Club[] = " Club";
char Clubs[] = " Clubs";
char NT[] = " NT";
char Pass[] = "Pass";
char Double[] = "Double";
char Redouble[] = "Redouble";
char HighCardPoints[10] = "   Points";
BOOL bidding = TRUE, first = TRUE, showbid = FALSE, previousgame = FALSE, bidagain = FALSE, firstplay = FALSE, showallcards = FALSE, fromx = FALSE;
BOOL opener, responder, rebidder, responderrebidder, linbidding, linplaying, loaded = FALSE, cardsloaded = FALSE, frombids = FALSE, fromagain = FALSE;
BOOL Red[52], Green[52];
bool trick = false;
struct Kards {
	BYTE Order;
	DWORD RandomNumber;
} cards[52];
struct Hands { //			S			 H			  C			   D
	char number; // from 0: AKQJT98765432AKQJT98765432AKQJT98765432AKQJT98765432
	char card[4]; // e.g. 'S5'
};
char numbers[53] = "AKQJT98765432AKQJT98765432AKQJT98765432AKQJT98765432";
char pbnDiamonds[13], pbnClubs[13];
char Bids[18][3];
char Plays[13][15]; // e.g. "H2 HA H3 H7 \r\n"
char SavedPlays[13][15];
char winner[13];
int sp;
struct Hands west[13];
struct Hands north[13];
struct Hands east[13];
struct Hands south[13];
struct Hands temp[13];
struct Hands westcopy[13];
struct Hands northcopy[13];
struct Hands eastcopy[13];
struct Hands southcopy[13];
struct Hands *player;
struct Hands Played[4]; // west north east south
struct Hands CardsPlayed[104];
struct Hands *ptr;
struct {
	int x;
	int y;
	BYTE player;
	BYTE card;
	BYTE suitnum;
} Playing[4];
char Filename[MAX_PATH];
char FullFilename[MAX_PATH];
char Play[] = "[Play \"W\"]\r\n";
char Pbn[1024];
char templatePbn[282] = "[Event \"\"]\r\n\
[Site \"\"]\r\n\
[Date \"\"]\r\n\
[Board \"\"]\r\n\
[West \"\"]\r\n\
[North \"\"]\r\n\
[East \"\"]\r\n\
[South \"\"]\r\n\
[Dealer \"?\"]\r\n\
[Vulnerable \"\"]\r\n\
[Deal \"N:XXXXXX.X.XX.XXXX.XXX.XXXXX.XX.XXX.XX.XXX.XXXXX.XXX.XX.XXXX.XXXX.XXX\"]\r\n\
[Scoring \"\"]\r\n\
[Declarer \"?\"]\r\n\
[Contract \"??\"]\r\n\
[Result \"?\"]\r\n\
[Auction \"?\"]\r\n";
HANDLE hFile;
SIZE Size;
HWND hwnd, hwndBid, hwndOK;
HWND hwndBid2, hwndBids[13];
HINSTANCE hInst;
HDC hdc, hdcMem = NULL;
HBITMAP hBitmap;
PAINTSTRUCT ps;
RECT rect;
OPENFILENAME ofn;
HGDIOBJ hGreenBrush, hLeadingBrush, hOldBrush;
HGDIOBJ hFont, hUpsideDownFont, hSuitFont, hSmallSuitFont, hUpsideDownSuitFont, hSmallUpsideDownSuitFont, hOldFont;
LOGFONT lf, lfSuit;
SYSTEMTIME st;
FILETIME ft;
ULARGE_INTEGER ul;
WNDPROC pBidProc;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	MSG          msg;
	WNDCLASS     wndclass;
	hInst = hInstance;
	hGreenBrush = CreateSolidBrush(GREEN);
	hLeadingBrush = CreateSolidBrush(BLUE);

	wndclass.style         = CS_HREDRAW|CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = LoadIcon(hInstance, "ICON");
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)hGreenBrush;
	wndclass.lpszMenuName  = "MENU";
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
		return 0;

	hwnd = CreateWindow(szAppName, szAppName,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInst, NULL);

	ShowWindow(hwnd, SW_SHOWMAXIMIZED);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}
DWORD Atoi(CHAR *ptr)
{
	DWORD x;

	for (x = 0; (*ptr >= CHAR('0')) && (*ptr <= CHAR('9')); ptr++) {
		x *= 10;
		x += *ptr - CHAR('0');
	}
	return x;
}


//sub-class procedure
LRESULT CALLBACK BidProc(HWND hwnd2, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_KEYUP) {
		int x, y;

		p = NULL;
		switch (wParam)
		{
		case '1':
			one = 1;
			break;
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
			one = 2;
			break;
		case 'S':
		case 's':
			if (one == 1)
				p = Spade;
			else if (one != -1)
				p = Spades;
			else {
				SendMessage(hwndBid, EM_SETSEL, 0, -1);
				SendMessage(hwndBid, WM_CLEAR, 0, 0);
			}
			passes = 0;
			break;
		case 'H':
		case 'h':
			if (one == 1)
				p = Heart;
			else if (one == 2)
				p = Hearts;
			else if (one == -1) {
				SendMessage(hwndBid, EM_SETSEL, 0, -1);
				SendMessage(hwndBid, WM_CLEAR, 0, 0);
			}
			passes = 0;
			break;
		case 'D':
		case 'd':
			if (one == 1) {
				p = Diamond;
				passes = 0;
			}
			else if (one != -1) {
				p = Diamonds;
				passes = 0;
			}
			else if (one == -1) {
				for (x = Bidder; x >= 0; x--) {
					if ((Bid[x][0] >= '0') && (Bid[x][0] <= '7')) {
						p = Double;
						passes = 0;
						break;
					}
				}
			}
			break;
		case 'C':
		case 'c':
			if (one == 1)
				p = Club;
			else if (one != -1)
				p = Clubs;
			else {
				SendMessage(hwndBid, EM_SETSEL, 0, -1);
				SendMessage(hwndBid, WM_CLEAR, 0, 0);
			}
			passes = 0;
			break;
		case 'N':
		case 'n':
			if (one != -1)
				p = NT;
			else {
				SendMessage(hwndBid, EM_SETSEL, 0, -1);
				SendMessage(hwndBid, WM_CLEAR, 0, 0);
			}
			passes = 0;
			break;
		case 'P':
		case 'p':
			p = Pass;
			passes++;
			break;
		case 'R':
		case 'r':
			for (x = Bidder; x >= 0; x--) {
				if ((Bid[x][0] >= '0') && (Bid[x][0] <= '7')) {
					p = Redouble;
					passes = 0;
					break;
				}
			}
			break;
		default:
			one = -1;
			SendMessage(hwndBid, EM_SETSEL, 0, -1);
			SendMessage(hwndBid, WM_CLEAR, 0, 0);
			break;
		}

		if (p) {
			GetWindowText(hwndBid, Bid[Bidder], 20);
			if (one == -1) x = 0; else x = 1;
			for ( ; *p != 0; x++, p++)
				Bid[Bidder][x] = *p;
			Bid[Bidder][x] = 0;
			if ((Bid[Bidder][0] >= '1') && (Bid[Bidder][0] <= '7')) {
				for (x = 0, y = 5; (y < 16) && (Bid[Bidder][x] != 0); x++, y++)
					LastBid[y] = Bid[Bidder][x];
				LastBid[y] = 0;
			}
			xOld = xBid;
			yOld = yBid;
			xBid += 80;
			if (xBid == 330) {
				xBid = 10;
				yBid += 30;
			}
			one = -1;
			showbid = TRUE;
			Bidder++;
			DestroyWindow(hwndBid); // bid window
			first = TRUE;
			InvalidateRect(hwnd, &rect, FALSE);
		}
	}
	return CallWindowProc(pBidProc, hwnd2, message, wParam, lParam);
}

int compare1(const void *x, const void *y)
{
	if (((struct Kards*)x)->RandomNumber > ((struct Kards*)y)->RandomNumber)
		return 1;
	else if (((struct Kards*)x)->RandomNumber < ((struct Kards*)y)->RandomNumber)
		return -1;
	else {
		MessageBox(hwnd, "Two random numbers are the same!", ERROR, MB_OK);
		return 0;
	}
}

int compare2(const void *x, const void *y)
{
	if (((struct Hands*)x)->number > ((struct Hands*)y)->number)
		return 1;
	else if (((struct Hands*)x)->number < ((struct Hands*)y)->number)
		return -1;
	else
		return 0;
}

void ConvertNumbersToNames(struct Hands *ptr, int CardsInSuits[4]){
	if (ptr[x].number < 13) {
		ptr[x].card[0] = 'S';
		CardsInSuits[0]++;
	}
	else if (ptr[x].number < 26) {
		ptr[x].card[0] = 'H';
		CardsInSuits[1]++;
	}
	else if (ptr[x].number < 39) {
		ptr[x].card[0] = 'C';
		CardsInSuits[2]++;
	}
	else {//if (ptr[x].number < 52)
		ptr[x].card[0] = 'D';
		CardsInSuits[3]++;
	}
	ptr[x].card[1] = Suit[ptr[x].number % 13];
}

void ShowCard(struct Hands *ptr, int x, int y, int v)
{
	if (CardHeight != (7 * ScreenWidth / 51)) {
		MessageBox(hwnd, "Something went wrong.", "", MB_OK);
	}
	if ((ptr == player) && (currentcard == v)) {
		hOldBrush = SelectObject(hdcMem, hLeadingBrush);
		RoundRect(hdcMem, x, y, x+CardWidth, y+CardHeight, 12, 12);
		SelectObject(hdcMem, hOldBrush);
	}
	else
		RoundRect(hdcMem, x, y, x+CardWidth, y+CardHeight, 12, 12);
	suit[0] = SuitSymbols[w];
	if ((SuitSymbols[w] == 0xA8) || (SuitSymbols[w] == 0xA9))
		SetTextColor(hdcMem, RED);
	else
		SetTextColor(hdcMem, 0); // black
	hOldFont = SelectObject(hdcMem, hSmallSuitFont);
	TextOut(hdcMem, x+2, y + 18, suit, 1);
	SelectObject(hdcMem, hSmallUpsideDownSuitFont);
	TextOut(hdcMem, x+CardWidth-2, y+CardHeight-18, suit, 1);

	if (v < 13) // if v == 0xFF then card[0] = Playing[].card
		card[0] = ptr[v].card[1];
	SelectObject(hdcMem, hFont);
	if (card[0] == 'T')
		TextOut(hdcMem, x-1, y+1, "10", 2);
	else if ((card[0] > '9') && (card[0] != 'J'))
		TextOut(hdcMem, x+3, y+1, card, 1);
	else
		TextOut(hdcMem, x+5, y+1, card, 1);
	SelectObject(hdcMem, hUpsideDownFont);
	if (card[0] == 'T')
		TextOut(hdcMem, x+CardWidth+1, y+CardHeight-1, "10", 2);
	else if ((card[0] > '9') && (card[0] != 'J'))
		TextOut(hdcMem, x+CardWidth-3, y+CardHeight-1, card, 1);
	else
		TextOut(hdcMem, x+CardWidth-5, y+CardHeight-1, card, 1);
	if ((card[0] == 'J') || (card[0] == 'Q') || (card[0] == 'K')) {
		MoveToEx(hdcMem, x+27, y+28, NULL);
		LineTo(hdcMem, x+27, y+CardHeight-28);
		LineTo(hdcMem, x+CardWidth-27, y+CardHeight-28);
		LineTo(hdcMem, x+CardWidth-27, y+28);
		LineTo(hdcMem, x+27, y+28);
	}

	SelectObject(hdcMem, hSuitFont);
	GetTextExtentPoint32(hdcMem, "\xAA", 1, &Size);
	SuitHeight = Size.cy;
	SpadeWidth = Size.cx;
	GetTextExtentPoint32(hdcMem, "\xA9", 1, &Size);
	HeartWidth = Size.cx;
	GetTextExtentPoint32(hdcMem, "\xA8", 1, &Size);
	DiamondWidth = Size.cx;
	GetTextExtentPoint32(hdcMem, "\xA7", 1, &Size);
	ClubWidth = Size.cx;
	if (suit[0] == '\xAA')
		SuitWidth = SpadeWidth;
	else if (suit[0] == '\xA9')
		SuitWidth = HeartWidth;
	else if (suit[0] == '\xA8')
		SuitWidth = DiamondWidth;
	else if (suit[0] == '\xA7')
		SuitWidth = ClubWidth;
	CardTop = y-3;
	switch (card[0])
	{
	case '2':
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '3':
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '4':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '5':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '6':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '7':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)-(SuitHeight), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '8':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)-(SuitHeight), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)+(SuitHeight/8), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case '9':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight/5), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight/5), suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)-(SuitHeight/2), suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight*4/5)-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight*4/5)-SuitHeight, suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	case 'T':
		TextOut(hdcMem, x+20, CardTop, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(SuitHeight/4), suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight/5), suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight/5), suit, 1);
		TextOut(hdcMem, x+20, CardTop+(CardHeight*4/5)-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+(CardHeight*4/5)-SuitHeight, suit, 1);
		TextOut(hdcMem, x+(CardWidth/2)-(SuitWidth/2), CardTop+(CardHeight/2)+(SuitHeight/4), suit, 1);
		TextOut(hdcMem, x+20, CardTop+CardHeight-SuitHeight, suit, 1);
		TextOut(hdcMem, x+CardWidth-20-SuitWidth, CardTop+CardHeight-SuitHeight, suit, 1);
		break;
	}
	SelectObject(hdcMem, hOldFont);
}

void Deal1(void)
{
	opener = responder = rebidder = responderrebidder = firstplay = FALSE;
	currentcard = 0;
	tricksplayed = 0;
	TricksLost[13] = '0';
	for (x = 0; x < 4; x++)
		Playing[x].player = 0xFF;
	for (x = 0; x < 20; x++)
		Bid[x][0] = 0;
	if (hwndBid)
		DestroyWindow(hwndBid);
	Bidder = 0;
	bidding = first = TRUE;
	passes = 0;
	LastBid[5] = 0;
	yBid = 30;
	loaded = FALSE;
	cardsloaded = FALSE;
	sp = 0;
}

void Deal2(void)
{
	for (x = 0; x < 4; x++) {
		if (SuitLengths[0][x] == 2)
			Doubletons[0]++;
		if (SuitLengths[1][x] == 2)
			Doubletons[1]++;
		if (SuitLengths[2][x] == 2)
			Doubletons[2]++;
		if (SuitLengths[3][x] == 2)
			Doubletons[3]++;
		if ((SuitLengths[0][x] < 2) || (Doubletons[0] == 2))
			Balanced[0] = 0;
		if ((SuitLengths[1][x] < 2) || (Doubletons[1] == 2))
			Balanced[1] = 0;
		if ((SuitLengths[2][x] < 2) || (Doubletons[2] == 2))
			Balanced[2] = 0;
		if ((SuitLengths[3][x] < 2) || (Doubletons[3] == 2))
			Balanced[3] = 0;
	}
}

void NewDeal(void)
{
	for (x = 0; x < 52; x++) {
		CardsPlayed[x].card[0] = 0;
		CardsPlayed[x].card[1] = 0;
		Red[x] = FALSE;
		Green[x] = FALSE;
	}
	cp = 0;
	for (x = 0; x < 13; x++)
		winner[x] = 0;
	for (x = 0; x < 14; x++)
		SavedPlays[x][0] = 0;
	for (x = 0; x < 282; x++)
		Pbn[x] = templatePbn[x];
	if (previousgame) {
		DealerCopy = Dealer;
		Dealer = PreviousDealer;
	}
	else { // next game
		Dealer++;
		if (Dealer == 4)
			Dealer = 0; // west
	}
//	Dealer = OrigDealer;
//	Dealer++;
//	if (Dealer == 4)
//		Dealer = 0;
	////////
	Deal1();
	////////
	if ((Dealer+Bidder%4) == 0)
		xBid = 10;
	else if ((Dealer+Bidder%4) == 1)
		xBid = 90;
	else if ((Dealer+Bidder%4) == 2)
		xBid = 170;
	else if ((Dealer+Bidder%4) == 3)
		xBid = 250;
	for (x = 0; x < 4; x++) {
		for (y = 0; y < 4; y++) {
			SuitLengths[x][y] = 0;
		}
	}
//shuffle
	if (dwRandomBytesRead == 0) {
		if (!previousgame)
			GetLocalTime(&st);
		SystemTimeToFileTime(&st, &ft);
		ul.LowPart = ft.dwLowDateTime;
		ul.HighPart = ft.dwHighDateTime;
		ul.QuadPart /= 10000;//because low 4 digits are 0's
		srand(ul.LowPart);
		srand((UINT)rand());
		for (x = 0; x < 52; x++) {
			cards[x].Order = x;
			cards[x].RandomNumber = rand();
		}
	}
	else { // if "InfiniteNoise.dta" was found and opened
		if (previousgame) {
			OldRandomOffset[0] = RandomOffset[0];
			RandomOffset[0] = Offset;
		}
		for (x = 0; x < 52; x++, RandomOffset[0] += 4) {
			cards[x].Order = x;
			cards[x].RandomNumber = *(DWORD*)&RandomBytes[RandomOffset[0]]; // DWORD so chance of same random number is VERY small
		}
		if (previousgame)
			RandomOffset[0] = OldRandomOffset[0];
		if (RandomOffset[0] < (RandomFileSize - 208)) {
			hFile = CreateFile("C:\\Users\\Public\\RandomOffset.dta", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
			WriteFile(hFile, RandomOffset, 4, &dwBytesWritten, NULL);
			CloseHandle(hFile);
		}
		else
			MessageBox(hwnd, "RandomOffset needs to be reset\n(get mod RandomOffset[0])", "", MB_OK);
	}
	previousgame = FALSE;
	qsort(cards, 52, sizeof(struct Kards), compare1);
//deal
	for (x = 0, y = 0; x < 52; y++) {
		west[y].number = cards[x++].Order;
		north[y].number = cards[x++].Order;
		east[y].number = cards[x++].Order;
		south[y].number = cards[x++].Order;
	}
//sort hands
	qsort(west, 13, sizeof(struct Hands), compare2);
	qsort(north, 13, sizeof(struct Hands), compare2);
	qsort(east, 13, sizeof(struct Hands), compare2);
	qsort(south, 13, sizeof(struct Hands), compare2);
//convert numbers to names
	for (x = 0; x < 13; x++) {
		ConvertNumbersToNames(west, SuitLengths[0]);
		ConvertNumbersToNames(north, SuitLengths[1]);
		ConvertNumbersToNames(east, SuitLengths[2]);
		ConvertNumbersToNames(south, SuitLengths[3]);
	}
	for (x = 0; x < 13; x++) {
		westcopy[x] = west[x];
		northcopy[x] = north[x];
		eastcopy[x] = east[x];
		southcopy[x] = south[x];
	}
	for (x = 0; x < 4; x++) {
		*(WORD*)&Played[x].card = 0x2020;
		WestSuitsCopy[x] = SuitLengths[0][x];
		NorthSuitsCopy[x] = SuitLengths[1][x];
		EastSuitsCopy[x] = SuitLengths[2][x];
		SouthSuitsCopy[x] = SuitLengths[3][x];
		Balanced[x] = 1;
		Doubletons[x] = 0;
	}
	////////
	Deal2();
	////////
	if (previousgame)
		Dealer = DealerCopy;
	else
		DealerCopy = Dealer;
}

void ShowPoints(int player)
{
	HighCardPoints[0] = (highcardpoints[player] / 10) + '0';
	if (HighCardPoints[0] == '0') HighCardPoints[0] = ' ';
	HighCardPoints[1] = (highcardpoints[player] % 10) + '0';
	TextOut(hdcMem, x, y, HighCardPoints, 9);
}

int CALLBACK HelpProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int dlgWidth;
	static HWND hwndEdit;
	RECT dlgRect, rectEdit;

	switch (message)
	{
	case WM_INITDIALOG:
		if (HelpType == 1)
			SetWindowText(hwndDlg, "Opening");
		else if (HelpType == 2)
			SetWindowText(hwndDlg, "Responding");
		else if (HelpType == 3)
			SetWindowText(hwndDlg, "Responding to 1 NT");
		else if (HelpType == 4)
			SetWindowText(hwndDlg, "Opener's Rebid");
		else if (HelpType == 5)
			SetWindowText(hwndDlg, "Responder's Rebid");
		GetWindowRect(hwndDlg, &dlgRect);
		dlgWidth = dlgRect.right-dlgRect.left;
		MoveWindow(hwndDlg, (rect.right/2)-(dlgWidth/2), TitleAndMenu, dlgWidth, rect.bottom, TRUE);
		hwndEdit = GetDlgItem(hwndDlg, IDC_EDIT1);
		MoveWindow(hwndEdit, 0, 0, dlgWidth, rect.bottom-Title, TRUE);
		GetClientRect(hwndEdit, & rectEdit);
		rectEdit.left += 10;
		SendMessage(hwndEdit, EM_SETRECT, 0, (LPARAM)(LPRECT)&rectEdit);
		SetWindowText(hwndEdit, HelpBuf);
		SetFocus(hwndEdit);
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			EndDialog (hwndDlg, TRUE);
			break;
		case IDCANCEL:
			EndDialog (hwndDlg, FALSE);
			break;
		}
	}
	return 0;
}

void Help(void)
{
	if	(fileSize = GetFileSize(hFile, NULL)) {
		HelpBuf = (char*)malloc(fileSize+1);
		ReadFile(hFile, HelpBuf, fileSize, &dwBytesRead, NULL);
		HelpBuf[fileSize] = 0;
		DialogBox(hInst, "BIDDINGHELP", hwnd, HelpProc);
		free(HelpBuf);
	}
	CloseHandle(hFile);
}
/*
int CALLBACK CommentsProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND hwndEdit;

	switch (message)
	{
	case WM_INITDIALOG:
		hwndEdit = GetDlgItem(hwndDlg, IDC_EDIT1);
		SetFocus(hwndEdit);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			GetWindowText(hwndEdit, Comments, 4095);
			EndDialog (hwndDlg, TRUE);
			break;
		case IDCANCEL:
			EndDialog (hwndDlg, FALSE);
			break;
		}
	}
	return 0;
}
*/
///////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_CREATE:
		hwndBid = NULL;
		lf.lfWeight = 700;
		lf.lfItalic = 0;
		lf.lfUnderline = 0;
		lf.lfStrikeOut = 0;
		lf.lfCharSet = 0;
		lf.lfOutPrecision = 3;//1;
		lf.lfClipPrecision = 2;
		lf.lfQuality = 1;
		lf.lfPitchAndFamily = 34;//0x22;
		for (x = 0; TimesNewRoman[x] != 0; x++)
			lf.lfFaceName[x] = TimesNewRoman[x];
		lf.lfFaceName[x] = 0;

		lfSuit.lfWeight = 400;
		lfSuit.lfItalic = 0;
		lfSuit.lfUnderline = 0;
		lfSuit.lfStrikeOut = 0;
		lfSuit.lfCharSet = 0;
		lfSuit.lfOutPrecision = 1;
		lfSuit.lfClipPrecision = 2;
		lfSuit.lfQuality = 1;
		lfSuit.lfPitchAndFamily = 0x22;
		for (x = 0; Symbol[x] != 0; x++)
			lfSuit.lfFaceName[x] = Symbol[x];
		lfSuit.lfFaceName[x] = 0;

		ofn.lStructSize       = sizeof(OPENFILENAME);
		ofn.hwndOwner         = hwnd;
		ofn.hInstance         = hInst;
		ofn.lpstrFilter       = TEXT(" Portable Bridge Notation\0")TEXT("*.pbn\0\0");
		ofn.lpstrFile         = FullFilename;
		ofn.lpstrFileTitle    = Filename;
		ofn.Flags             = OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_ENABLESIZING;
		ofn.lpstrTitle        = NULL;
		ofn.lpstrDefExt       = TEXT("pbn");
		ofn.nMaxFile          = MAX_PATH;
		ofn.lpstrCustomFilter = 0;
		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;

		hFile = CreateFile("C:\\Users\\Public\\InfiniteNoise.dta", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
		if (hFile != INVALID_HANDLE_VALUE) {
			RandomFileSize = GetFileSize(hFile, NULL);
			RandomBytes = (char*)malloc(RandomFileSize);
			ReadFile(hFile, RandomBytes, RandomFileSize, &dwRandomBytesRead, NULL);
			CloseHandle(hFile);

			hFile = CreateFile("C:\\Users\\Public\\RandomOffset.dta", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
			if (hFile != INVALID_HANDLE_VALUE) {
				ReadFile(hFile, &RandomOffset[0], 4, &dwBytesRead, NULL);
				CloseHandle(hFile);
				if (RandomOffset[0] > dwRandomBytesRead)
					RandomOffset[0] = 1;
			}
			else {
				RandomOffset[0] = 0;
			}
		}

		NewDeal();
		Title = GetSystemMetrics(SM_CYCAPTION);
		TitleAndMenu = Title + GetSystemMetrics(SM_CYMENU);
		return 0;

	case WM_SIZE:
		GetClientRect(hwnd, &rect);
		if (hdcMem) {
			DeleteDC (hdcMem);
			DeleteObject (hBitmap);
		}
		hdc = GetDC(hwnd);
		hdcMem = CreateCompatibleDC(hdc);
		hBitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
		ReleaseDC(hwnd, hdc);
		SelectObject(hdcMem, hBitmap);
		FillRect(hdcMem, &rect, (HBRUSH)hGreenBrush);

		ScreenWidth = LOWORD(lParam);// redundant...
		ScreenHeight = HIWORD(lParam);// redundant...
		xCenter = ScreenWidth / 2;
		yCenter = ScreenHeight / 2;
		// card proportion is 5:7
		CardWidth = 5 * ScreenWidth / 51;// 125
		CardHeight = 7 * ScreenWidth / 51;//175
		HandTop = ScreenHeight - CardHeight - 10;
		WestTop = EastTop = HandTop - 10 - CardHeight - (CardHeight*3/3);
		DummyLeft = xCenter - (CardWidth*2) - 25;
		EastLeft = xCenter + (CardWidth * 2) + 50;
		EastBiddingLeft = ScreenWidth - 10 - CardWidth - (12*25);
		HandLeft = xCenter - ((CardWidth + (12 * 25))/2);
		EWCardTop = yCenter-(CardHeight/2);
		EWPlayedTop = HandTop - CardHeight - (CardHeight/6) - 10;
		WestCard = xCenter-(CardWidth*3/4);
		NorthCardTop = HandTop - CardHeight - (CardHeight/3) - 10;
		NorthCard = xCenter-(CardWidth/2);
		EastCard = xCenter-(CardWidth/4);
		SouthCardTop = HandTop - CardHeight - 10;
		SouthCard = xCenter-(CardWidth/2);

		if (rect.right >= 1600) {
			lf.lfHeight = -29;
			lfSuit.lfHeight = -59; // big suit symbol
		}
		else if (rect.right >= 1200) {
			lf.lfHeight = -27;
			lfSuit.lfHeight = -45;
		}
		else { // if (rect.right == 1024) {
			lf.lfHeight = -23;
			lfSuit.lfHeight = -35; // big suit symbol
		}
		lf.lfEscapement = lf.lfOrientation = 1800;
		hUpsideDownFont = CreateFontIndirect(&lf);
		lf.lfEscapement = lf.lfOrientation = 0;
		hFont = CreateFontIndirect(&lf);

		lfSuit.lfEscapement = lfSuit.lfOrientation = 1800;
		hUpsideDownSuitFont = CreateFontIndirect(&lfSuit);
		lfSuit.lfEscapement = lfSuit.lfOrientation = 0;
		hSuitFont = CreateFontIndirect(&lfSuit);

		if (rect.right >= 1600) {
			lfSuit.lfHeight = -31; // small suit symbol
		}
		else if (rect.right >= 1200)
			lfSuit.lfHeight = -27; // small suit symol
		else // if (rect.right == 1024)
			lfSuit.lfHeight = -21;
		hSmallSuitFont = CreateFontIndirect(&lfSuit);
		lfSuit.lfEscapement = lfSuit.lfOrientation = 1800;
		hSmallUpsideDownSuitFont = CreateFontIndirect(&lfSuit);
		return 0;

	case WM_COMMAND:
		if ((hwndOK) && (HWND)lParam == hwndOK) {
			SendMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0);
			return 0;
		}
		switch (LOWORD(wParam))
		{
		case ID_FILES_SAVEGAME: // (pbn files use SHDC and Bridge2 uses SHCD)
			for (x = 0; x < 4; x++) {
				if (Dealer == x)
					Pbn[101] = Deal[x];
			}
			Pbn[130] = Pbn[101];
			if (Dealer == 0)
				ptr = westcopy;
			else if (Dealer == 1)
				ptr = northcopy;
			else if (Dealer == 2)
				ptr = eastcopy;
			else if (Dealer == 3)
				ptr = southcopy;
			for (x = 132; x < 199; x++, y++) { //[Deal "N:AK9872.A.64.A743 Q64.86543.T5.KT9 T5.QT7.AKQ97.J85 J3.KJ92.J832.Q62"]
				for (w = 0; w < 4; w++) {
					for (y = 0; ptr[y].card[0] == 'S'; x++, y++)
						Pbn[x] = ptr[y].card[1];
					Pbn[x++] = '.';
					for ( ; ptr[y].card[0] == 'H'; x++, y++)
						Pbn[x] = ptr[y].card[1];
					Pbn[x++] = '.';
					// swap diamonds and clubs
					for (z = 0; ptr[y].card[0] == 'C'; y++, z++)
						SaveClubs[z] = ptr[y].card[1];
					SaveClubs[z] = 0;
					for (z = 0; ptr[y].card[0] == 'D'; y++, z++)
						SaveDiamonds[z] = ptr[y].card[1];
					SaveDiamonds[z] = 0;
					//
					for (z = 0; SaveDiamonds[z]; x++, z++)
						Pbn[x] = SaveDiamonds[z];
					Pbn[x++] = '.';
					for (z = 0; SaveClubs[z]; x++, z++)
						Pbn[x] = SaveClubs[z];
					if (x < 199) {
						Pbn[x++] = ' ';
						if (ptr == westcopy)
							ptr = northcopy;
						else if (ptr == northcopy)
							ptr = eastcopy;
						else if (ptr == eastcopy)
							ptr = southcopy;
						else if (ptr == southcopy)
							ptr = westcopy;
					}
				}
			}
			Declarer = 3;
			Pbn[228] = 'S'; // Declarer
			Pbn[244] = LastBid[5]; // Contract
			Pbn[245] = LastBid[7];
			if (LastBid[7] == 'N') {
				for (x = 281; x > 246; x--)
					Pbn[x] = Pbn[x-1];
				Pbn[246] = 'T';
			}
			x = 247;
			if (tricksplayed == 52) {
				for ( ; Pbn[x] != 'R'; x++) // Result
					;
				x += 8;
				b = (TricksLost[13] - '0');
				if (b <= 3) {
					Pbn[x++] = '1';
					for (y = 281; y > x; y--)
						Pbn[y] = Pbn[y-1];
					Pbn[x] = (3 - b) + '0';
				}
				else
					Pbn[x] = b + '0';
			}
			for ( ; (x < 282) && (Pbn[x] != 'A'); x++)
				;
			x += 9;
			Pbn[x] = Pbn[130]; // Auction = Dealer = Deal (it's W)
			x += 5; // past ' ]\r\n
			for (BidLoc = x, w = 1, z = 0; Bid[z][0]; w++, z++) {
				Pbn[x++] = Bid[z][0];
				if ((Bid[z][0] == 'P')) {
					Pbn[x++] = Bid[z][1];
					Pbn[x++] = Bid[z][2];
					Pbn[x++] = Bid[z][3];
				}
				if ((Bid[z][0] != 'P') && (Bid[z][0] != 'D') && (Bid[z][0] != 'R'))
					Pbn[x++] = Bid[z][2];
				if (Bid[z][2] == 'N')
					Pbn[x++] = 'T';
				for (BidLoc += 10; x < BidLoc; )
					Pbn[x++] = ' ';
				if ((w%4) == 0) {
					Pbn[x++] = '\r';
					Pbn[x++] = '\n';
					BidLoc = x;
				}
			}
			if ((Pbn[x-2] != '\r') && (Pbn[x-1] != '\n')) {
					Pbn[x++] = '\r';
					Pbn[x++] = '\n';
			}
			for (y = 0; y < 12; x++, y++) // [Play] Declarer = S
				Pbn[x] = Play[y];
			if (SavedPlays[0][0]) {
				for (y = 0; y < 13; y++) { // plays
					for (z = 0; SavedPlays[y][z]; x++, z++)
						Pbn[x] = SavedPlays[y][z];
				}
			}
			fileSize = x;
			if (fromx) { // Pbn is in memory
				fromx = FALSE;
//				if (pbn)
//					VirtualFree(pbn, 0, MEM_RELEASE);
//				pbn = (char*)VirtualAlloc(NULL, fileSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
//				for (x = 0; x < (int)fileSize; x++)
//					pbn[x] = Pbn[x];
//				goto there2;
			}
			else if (GetOpenFileName(&ofn)) {
				hFile = CreateFile(FullFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
				if (hFile != INVALID_HANDLE_VALUE) {
					WriteFile(hFile, &Pbn, fileSize, &dwBytesWritten, NULL);
					CloseHandle(hFile);
				}
				else {
					MessageBox(hwnd, "bug", "", MB_OK);
					break;
				}
			}
			break;

		case ID_LOADGAME: // (pbn files use SHDC and Bridge2 uses SHCD)
			DestroyWindow(hwndOK);
			if (GetOpenFileName(&ofn)) {
//there:;
				hFile = CreateFile(FullFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
				if (hFile != INVALID_HANDLE_VALUE) {
					fileSize = GetFileSize(hFile, NULL);
					if (fileSize) {
						if (pbn)
							VirtualFree(pbn, 0, MEM_RELEASE);
						pbn = (char*)VirtualAlloc(NULL, fileSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
						ReadFile(hFile, pbn, fileSize, &dwBytesRead, NULL);
						CloseHandle(hFile);

//there2:;
						for (x = 0; x < 13; x++) {
							west[x].number = 0;
							*(WORD*)&west[x].card = 0;
							north[x].number = 0;
							*(WORD*)&north[x].card = 0;
							east[x].number = 0;
							*(WORD*)&east[x].card = 0;
							south[x].number = 0;
							*(WORD*)&south[x].card = 0;
						}
						////////
						Deal1();
						////////
						pbnsuit = 0;
						w = n = e = s = 0;
						for (x = 0; x < (int)fileSize; x++) { // ended with break at end of if ((pbn[x]...
							if ((pbn[x] == '[') && (pbn[x+1] == 'D') && (pbn[x+2] == 'e') && (pbn[x+3] == 'a') && (pbn[x+4] == 'l') && (pbn[x+5] == ' ')) {
								x += 7;
								for (y = 0; y < 4; y++) { // WNES
									if (pbn[x] == Deal[y])
										break;
								}
								x += 2; // to first spade or .
								Dealer = y;
								Bidder = 0;
								y = x;								
								for (v = 0; v < 4; v++) { // swap diamonds and clubs
									for (z = 0; pbn[y] != '.'; y++, z++)
										;
									for (y++, z = 0; pbn[y] != '.'; y++, z++)
										;
									DiamondsLoc = y+1;
									for (y++, z = 0; pbn[y] != '.'; y++, z++)
										pbnDiamonds[z] = pbn[y];
									pbnDiamondSize = z;
									for (y++, z = 0; (pbn[y] != ' ') && (pbn[y] != '"'); y++, z++)
										pbnClubs[z] = pbn[y];
									pbnClubSize = z;
									for (y = DiamondsLoc, z = 0; z < pbnClubSize; y++, z++)
										pbn[y] = pbnClubs[z];
									pbn[y++] = '.';
									for (z = 0; z < pbnDiamondSize; y++, z++)
										pbn[y] = pbnDiamonds[z];
									pbn[y++] = ' ';
								}
								pbn[y-1] = '"';

								if (Dealer == 0) xBid = 10;
								else if (Dealer == 1) xBid = 90;
								else if (Dealer == 2) xBid = 170;
								else if (Dealer == 3) xBid = 250;
								for (z = 0; z < 4; z++) {
									for (y = 0; y < 4; y++) {
										SuitLengths[z][y] = 0;
									}
								}
								pbnplayer = Dealer;
								pbnsuit = 0;
								for ( ; (x < (int)fileSize) && (pbn[x] != '"'); x++) {
									if (pbn[x] == '.') {
										pbnsuit++;
									}
									else if (pbn[x] == ' ') {
										pbnsuit = 0;
										pbnplayer++;
										if (pbnplayer == 4)
											pbnplayer = 0;
									}
									else { // convert card names to numbers
										z = 0;
										for (y = 0; y < 13; y++) {
											if (Suit[y] == pbn[x]) {
												if (pbnplayer == 0) {
													west[w].number = y + (13*pbnsuit);
													west[w].card[0] = Suits[pbnsuit];
													west[w].card[1] = Suit[west[w].number % 13];
													w++;
													SuitLengths[0][pbnsuit]++;
												}
												else if (pbnplayer == 1) {
													north[n].number = 13 + y + (13*pbnsuit);
													north[n].card[0] = Suits[pbnsuit];
													north[n].card[1] = Suit[north[n].number % 13];
													n++;
													SuitLengths[1][pbnsuit]++;
												}
												else if (pbnplayer == 2) {
													east[e].number = 26 + y + (13*pbnsuit);
													east[e].card[0] = Suits[pbnsuit];
													east[e].card[1] = Suit[east[e].number % 13];
													e++;
													SuitLengths[2][pbnsuit]++;
												}
												else if (pbnplayer == 3) {
													south[s].number = 39 + y + (13*pbnsuit);
													south[s].card[0] = Suits[pbnsuit];
													south[s].card[1] = Suit[south[s].number % 13];
													s++;
													SuitLengths[3][pbnsuit]++;
												}
												break;
											}
										}
									}
								}
								SaveX = x;
								////////
								Deal2();
								////////
								if (IDYES == MessageBox(hwnd, "See how game was bid and played?\n(press any key to go thru it)", "", MB_YESNO|MB_DEFBUTTON2)) {
									x = SaveX;
									for ( ; x < (int)fileSize; x++) { // get Declarer
										if ((pbn[x] == '[') && (pbn[x+1] == 'D') && (pbn[x+2] == 'e') && (pbn[x+3] == 'c') && (pbn[x+4] == 'l') && (pbn[x+5] == 'a')) {
											x += 11; // to W, N, E, or S
											for (y = 0; y < 4; y++) {
												if (pbn[x] == Deal[y]) {
													Declarer = y;
													break;
												}
											}
											x++;
											break;
										}
									}
									for ( ; x < (int)fileSize; x++) { // get BidSuit
										if ((pbn[x] == '[') && (pbn[x+1] == 'C') && (pbn[x+2] == 'o') && (pbn[x+3] == 'n') && (pbn[x+4] == 't') && (pbn[x+5] == 'r')) {
											x += 11;
											BidSuit = pbn[x+1];
											for (y = 5; y < 12; y++)
												LastBid[y] = 0;
											LastBid[5] = pbn[x];
											LastBid[6] = pbn[x+1];
											break;
										}
										x++;
									}
									for ( ; x < (int)fileSize; x++) { // get Bids
										if ((pbn[x] == '[') && (pbn[x+1] == 'A') && (pbn[x+2] == 'u') && (pbn[x+3] == 'c') && (pbn[x+4] == 't') && (pbn[x+5] == 'i')) {
											x += 13;
											break;
										}
									}
									b = 0;
									for (w = 0; w < 13; w++)
										*(WORD*)&Bids[w] = 0;
									for (z = 0; (pbn[x] != '[') && (passes < 4); x++) {
										if (pbn[x] == 13)
											x++;
										else if ((pbn[x] == 'P') || (pbn[x] == 'D') || (pbn[x] == 'R')) {
											Bids[z][0] = pbn[x];
											Bids[z][1] = ' ';
											z++;
											passes++;
											x += 4;
										}
										else if (pbn[x] != ' ') {
											Bids[z][0] = pbn[x++];
											Bids[z][1] = pbn[x++];
											z++;
											passes = 0;
										}
									}
									for ( ; pbn[x] != '['; x++)
										;
									for ( ; pbn[x] != ']'; x++)
										;
									x += 3; // to first spade
									for (z = 0; z < 13; z++) {
										for (w = 0; (w < 14) && (x < (int)fileSize); w++, x++)
											Plays[z][w] = pbn[x];
									}
									FillRect(hdcMem, &rect, (HBRUSH)hGreenBrush);
									SetTextColor(hdcMem, 0xFFFFFF);
									TextOut(hdcMem, 10, 10, West, 4);
									TextOut(hdcMem, 90, 10, North, 5);
									TextOut(hdcMem, 170, 10, East, 4);
									TextOut(hdcMem, 250, 10, South, 5);
									if (Dealer == 0) x = 10;
									else if (Dealer == 1) x = 90;
									else if (Dealer == 2) x = 170;
									else if (Dealer == 3) x = 250;
									for (y = 30, z = 0; Bids[z][0]; z++) {
										TextOut(hdcMem, x, y, Bids[z], strlen(Bids[z]));
										x += 80;
										if (x == 330) {
											x = 10;
											y += 30;
										}
									}
									hdc = GetDC(hwnd);
									BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
									ReleaseDC(hwnd, hdc);
									UpdateWindow(hwnd);
									first = FALSE;
									bidding = FALSE;
									showbid = FALSE;
									cardsloaded = TRUE;
									showallcards = TRUE;
									pl = 0; // for Plays[pl]
									loaded = TRUE;
								} // end of if (IDYES ==
								else {
									loaded = FALSE;
									InvalidateRect(hwnd, &rect, FALSE);
								}
								showallcards = TRUE;
								break; // done
							} // end of if ((pbn[x] == '[')
						} // end of big for loop
					} // end of if (fileSize)
					else
						MessageBox(hwnd, "bad file", ERROR, MB_OK);
					hFile = NULL;
				} // end of if (hFile != INVALID_HANDLE_VALUE)
				else
					MessageBox(hwnd, "bad file", FullFilename, MB_OK);
				trick = true;
			} // end of if (GetOpenFileName(&ofn)) (in case LOADGAME:)
			break;

		case ID_FILES_EXIT:
			DestroyWindow(hwnd);
			break;

		case ID_NEWDEAL:
			DestroyWindow(hwndOK);
			fromagain = FALSE;
			NewDeal();
			InvalidateRect(hwnd, &rect, FALSE);
			break;
/*
		case ID_AGAIN_BID:
			if (loaded)
				break;
			for (x = 0; x < 282; x++)
				Pbn[x] = templatePbn[x];
			DestroyWindow(hwndOK);
			DestroyWindow(hwndBid);
			opener = responder = rebidder = responderrebidder = FALSE;
			Dealer = OrigDealer; // DealerCopy;
			Bidder = 0;
			passes = 0;
			for (x = 0; x < 20; x++)
				Bid[x][0] = 0;
			LastBid[5] = 0;
			yBid = 30;
			if (Dealer == 0) xBid = 10;
			else if (Dealer == 1) xBid = 90;
			else if (Dealer == 2) xBid = 170;
			else xBid = 250;
			bidagain = TRUE;
			// fall thru...
//		case ID_AGAIN_PLAY:
			fromagain = TRUE;
			if (loaded)
				break;
			if (!cardsloaded)
				showallcards = FALSE;
			if ((bidagain == TRUE) || (bidding == FALSE)) {
				sp = 0;
				bidding = first = TRUE;
				firstplay = FALSE;
				cardsplayed = 0;
				currentcard = 0;
				tricksplayed = 0;
				TricksLost[13] = '0';
				for (x = 0; x < 4; x++)
					Playing[x].player = 0xFF;

				if (cardsloaded)
					goto there;

				for (x = 0; x < 13; x++) {
					west[x] = westcopy[x];
					north[x] = northcopy[x];
					east[x] = eastcopy[x];
					south[x] = southcopy[x];
				}
				for (x = 0; x < 4; x++) {
					*(WORD*)&Played[x].card = 0x2020;
					SuitLengths[0][x] = WestSuitsCopy[x];
					SuitLengths[1][x] = NorthSuitsCopy[x];
					SuitLengths[2][x] = EastSuitsCopy[x];
					SuitLengths[3][x] = SouthSuitsCopy[x];
				}
				if (bidagain) {
					bidagain = FALSE;
					InvalidateRect(hwnd, &rect, FALSE);
				}
				else
					SendMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0);
			}
			break;
*/
		case ID_SHOWALLCARDS:
			if (showallcards) {
				showallcards = FALSE;
				InvalidateRect(hwnd, &rect, FALSE);
			}
			else {
				showallcards = TRUE;
				InvalidateRect(hwnd, &rect, FALSE);
			}
			break;

		case HELP_USING:
			MessageBox(hwnd, "Use Enter and the Arrow keys","", MB_OK);
			if (bidding)
				SetFocus(hwndBid);
			break;
		case HELP_OPENING:
			if (INVALID_HANDLE_VALUE != (hFile = CreateFile("Opening.txt", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))) {
				HelpType = 1;
				Help();
			}
			else
				MessageBox(hwnd, "'Opening.txt'\nisn't in this folder", ERROR, MB_OK);
			SetFocus(hwndBid);
			break;
		case ID_HELP_RESPONDING:
			if (INVALID_HANDLE_VALUE != (hFile = CreateFile("Responding.txt", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))) {
				HelpType = 2;
				Help();
			}
			else
				MessageBox(hwnd, "'Responding.txt'\nisn't in this folder", ERROR, MB_OK);
			SetFocus(hwndBid);
			break;
		case ID_HELP_RESPONDINGTO1NT:
			if (INVALID_HANDLE_VALUE != (hFile = CreateFile("Responding to 1 NT.txt", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))) {
				HelpType = 3;
				Help();
			}
			else
				MessageBox(hwnd, "'Responding to 1 NT.txt'\nisn't in this folder", ERROR, MB_OK);
			SetFocus(hwndBid);
			break;
		case ID_HELP_OPENERSREBID:
			if (INVALID_HANDLE_VALUE != (hFile = CreateFile("Opener Rebid.txt", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))) {
				HelpType = 4;
				Help();
			}
			else
				MessageBox(hwnd, "'Opener Rebid.txt'\nisn't in this folder", ERROR, MB_OK);
			SetFocus(hwndBid);
			break;
		case ID_HELP_RESPONDERSREBID:
			if (INVALID_HANDLE_VALUE != (hFile = CreateFile("Responder Rebid.txt", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))) {
				HelpType = 5;
				Help();
			}
			else
				MessageBox(hwnd, "'Responder Rebid.txt'\nisn't in this folder", ERROR, MB_OK);
			SetFocus(hwndBid);
			break;
		case HELP_ABOUT:
			MessageBox(hwnd, "by Doug Cox\njdmcox.com", "Bridge2", MB_OK);
			break;
		}
		return 0;

	case WM_KEYDOWN:
		if ((bidding) && (!loaded))
			SetFocus(hwndBid);
		if (loaded) {
			bidding = FALSE;
			DestroyWindow(hwndBid);
			wParam = VK_RETURN;
		}
play:	if ((bidding) && (((LastBid[5]) && (passes == 3)) || (passes == 4))) {
			int x, y, turns;

			if (passes == 4) {
				fromagain = FALSE;
				NewDeal();
			}
			else {
				bidding = FALSE;
				for (x = Bidder-1; x >= 0; x--) {
					if ((Bid[x][0] >= '1') && (Bid[x][0] <= '7'))
						break;
				}
				if (!loaded)
					BidSuit = Bid[x][2];
				if (x & 1) y = 1; else y = 0;
				for ( ; y <= x; y += 2) {
					if ((Bid[y][0] != 'P') && (Bid[y][2] == BidSuit)) {
						Declarer = (Dealer+y) % 4;
						for (turns = 0, x = Declarer; x != 3; turns++) { // make Declarer South
							for (y = 0; y < 13; y++) {
								temp[y] = north[y];
								north[y] = west[y];
								west[y] = south[y];
								south[y] = east[y];
								east[y] = temp[y];
							}
							for (y = 0; y < 4; y++) {
								tempSuits[y] = SuitLengths[1][y];
								SuitLengths[1][y] = SuitLengths[0][y];
								SuitLengths[0][y] = SuitLengths[3][y];
								SuitLengths[3][y] = SuitLengths[2][y];
								SuitLengths[2][y] = tempSuits[y];
							}
							x++;
							if (x == 4) x = 0;
						}
						Dealer += turns;
						if (Dealer > 3)
							Dealer -= 3;
						DealerCopy = Dealer;
						for (x = 0; x < 13; x++) {
							westcopy[x] = west[x];
							northcopy[x] = north[x];
							eastcopy[x] = east[x];
							southcopy[x] = south[x];
						}
						for (x = 0; x < 4; x++) {
							WestSuitsCopy[x] = SuitLengths[0][x];
							NorthSuitsCopy[x] = SuitLengths[1][x];
							EastSuitsCopy[x] = SuitLengths[2][x];
							SouthSuitsCopy[x] = SuitLengths[3][x];
						}
						break;
					}
				}
			}
			cardsplayed = 0;
			player = west;
			InvalidateRect(hwnd, &rect, FALSE);
		} // end of if (bidding)

		else if (!bidding) { // PLAYING
			int x;

			if (wParam == VK_RIGHT) {
				if ((player == west) || (player == east)) {
					if (player[currentcard+1].card[0] == player[currentcard].card[0]) {// same suit
						currentcard++;
					}
				}
				else if (player == north) {
					for (x = currentcard; x < 12; x++) {
						if ((player[x+1].card[0] != player[x].card[0]) && (player[x+1].card[0] != 0x7F)) {
							currentcard = x+1;
							break; // next suit
						}
					}
				}
				else if (player == south) {
					if ((currentcard < 12) && (player[currentcard+1].card[0] != 0x7F)) {
						currentcard++;
					}
				}
			}
			else if (wParam == VK_DOWN) {
				if ((player == west) || (player == east)) {
					for (x = currentcard; x < 12; x++) {
						if ((player[x+1].card[0] != player[x].card[0]) && (player[x+1].card[0] != 0x7F)) {
							currentcard = x+1;
							break; // next suit
						}
					}
				}
				else if (player == north) {
					if (player[currentcard+1].card[0] == player[currentcard].card[0]) {// same suit
						currentcard++;
					}
				}
			}
			else if (wParam == VK_LEFT) {
				if ((player == west) || (player == east)) {
					if ((currentcard) && (player[currentcard-1].card[0] == player[currentcard].card[0])) {// same suit
						currentcard--;
					}
				}
				else if (player == north) {
					for (x = currentcard; (x > 0) && (player[x-1].card[0] == player[x].card[0]); x--)
						;
					if (x) {
						for (x--; player[x-1].card[0] == player[x].card[0]; x--)
							;
					}
					currentcard = x;
				}
				else if (player == south) {
					if (currentcard) {
						currentcard--;
					}
				}
			}
			else if (wParam == VK_UP) {
				if ((player == west) || (player == east)) {
					for (x = currentcard; (x > 0) && (player[x-1].card[0] == player[x].card[0]); x--)
						;
					if (x) {
						for (x--; player[x-1].card[0] == player[x].card[0]; x--)
							;
					}
					currentcard = x;
				}
				else if (player == north) {
					if ((currentcard) && (player[currentcard-1].card[0] == player[currentcard].card[0])) {// same suit
						currentcard--;
					}
				}
			}
			else if (wParam == VK_RETURN) { // !bidding
				if (loaded) {
					if (Plays[0][0]) {
						if ((pl == 13) || (Plays[pl][0] == 0)) 
							return 0;
						if (Declarer != 0xFF) {
							player = west; // opening play
							for (currentcard = 0; currentcard < 13; currentcard++) {
								if (*(WORD*)&west[currentcard].card == *(WORD*)&Plays[pl][0]) {
									break; // currentcard
								}
							}
							Declarer = 0xFF; // flag
						}
						else {
							if (player == west) {
								for (currentcard = 0; currentcard < 13; currentcard++) {
									if (*(WORD*)&west[currentcard].card == *(WORD*)&Plays[pl][0])
										break; // currentcard
								}
							}
							else if (player == north) {
								for (currentcard = 0; currentcard < 13; currentcard++) {
									if (*(WORD*)&north[currentcard].card == *(WORD*)&Plays[pl][3])
										break; // currentcard
								}
							}
							else if (player == east) {
								for (currentcard = 0; currentcard < 13; currentcard++) {
									if (*(WORD*)&east[currentcard].card == *(WORD*)&Plays[pl][6])
										break; // currentcard
								}
							}
							else if (player == south) {
								for (currentcard = 0; currentcard < 13; currentcard++) {
									if (*(WORD*)&south[currentcard].card == *(WORD*)&Plays[pl][9])
										break; // currentcard
								}
							}
						}
					}
					else {
//						loaded = FALSE;
						MessageBox(hwnd, "No plays", "", MB_OK);
					}
				} // end of if (loaded)

				if (tricksplayed < 52) {
					if (cardsplayed == 0) {
						suitled = player[currentcard].card[0]; // player is west,north,east,or south AND current card is the number of card played in that hand
					}
					else if ((player[currentcard].card[0] != suitled) && (!loaded)) {
						for (x = 0; (x < 13) && (player[x].number != 0xFF); x++) {
							if (player[x].card[0] == suitled) {
								return 0;
							}
						}
					}
					if (player == west) { // VK_RETURN
						Played[0] = west[currentcard];
						Red[cp] = TRUE;
						CardsPlayed[cp++] = Played[0];
						for (x = 0; west[currentcard].card[0] != Suits[x]; x++)
							;
						if (SuitLengths[0][x])
							SuitLengths[0][x]--;
						Playing[cardsplayed].card = west[currentcard].card[1];
						Playing[cardsplayed].x = WestCard;
						Playing[cardsplayed].y = EWPlayedTop;
						Playing[cardsplayed].player = 0;
						Playing[cardsplayed].suitnum = x;
						for (x = currentcard; x < 12; x++)
							west[x] = west[x+1]; // remove card played
						west[x].card[0] = 0x7F;
						player = north;
					}
					else if (player == north) {
						Played[1] = north[currentcard];
						CardsPlayed[cp++] = Played[1];
						for (x = 0; north[currentcard].card[0] != Suits[x]; x++)
							;
						if (SuitLengths[1][x])
							SuitLengths[1][x]--;
						Playing[cardsplayed].card = north[currentcard].card[1];
						Playing[cardsplayed].x = NorthCard;
						Playing[cardsplayed].y = NorthCardTop;
						Playing[cardsplayed].player = 1;
						Playing[cardsplayed].suitnum = x;
						for (x = currentcard; x < 12; x++)
							north[x] = north[x+1]; // remove card played
						north[x].card[0] = 0x7F;
						player = east;
					}
					else if (player == east) {
						Played[2] = east[currentcard];
						Green[cp] = TRUE;
						CardsPlayed[cp++] = Played[2];
						for (x = 0; east[currentcard].card[0] != Suits[x]; x++)
							;
						if (SuitLengths[2][x])
							SuitLengths[2][x]--;
						Playing[cardsplayed].card = east[currentcard].card[1];
						Playing[cardsplayed].x = EastCard;
						Playing[cardsplayed].y = EWPlayedTop;
						Playing[cardsplayed].player = 2;
						Playing[cardsplayed].suitnum = x;
						for (x = currentcard; x < 12; x++)
							east[x] = east[x+1]; // remove card played
						east[x].card[0] = 0x7F;
						player = south;
					}
					else if (player == south) {
						Played[3] = south[currentcard];
						CardsPlayed[cp++] = Played[3];
						for (x = 0; south[currentcard].card[0] != Suits[x]; x++)
							;
						if (SuitLengths[3][x])
							SuitLengths[3][x]--;
						Playing[cardsplayed].card = south[currentcard].card[1];
						Playing[cardsplayed].x = SouthCard;
						Playing[cardsplayed].y = SouthCardTop;
						Playing[cardsplayed].player = 3;
						Playing[cardsplayed].suitnum = x;
						for (x = currentcard; x < 12; x++)
							south[x] = south[x+1]; // remove card played
						south[x].card[0] = 0x7F;
						player = west;
					}

					cardsplayed++;
					if (cardsplayed == 4) { // round played
						if (loaded)
							pl++;
//						else {
//							fromx = true;
//							SendMessage(hwnd, WM_COMMAND, ID_FILES_SAVEGAME, 0);
//						}
						y = 0;
						*(WORD*)&SavedPlays[sp][y] = *(WORD*)&Played[0].card;
						y += 2;
						SavedPlays[sp][y++] = ' ';
						*(WORD*)&SavedPlays[sp][y] = *(WORD*)&Played[1].card;
						y += 2;
						SavedPlays[sp][y++] = ' ';
						*(WORD*)&SavedPlays[sp][y] = *(WORD*)&Played[2].card;
						y += 2;
						SavedPlays[sp][y++] = ' ';
						*(WORD*)&SavedPlays[sp][y] = *(WORD*)&Played[3].card;
						y += 2;
						SavedPlays[sp][y++] = ' ';
						SavedPlays[sp][y++] = '\r';
						SavedPlays[sp][y++] = '\n';
						sp++;
						cardsplayed = 0;
						highcard = 14;
						hightrump = 14;
						for (x = 0; x < 4; x++)
							Playing[x].player = 0xFF;

						if ((Played[0].number%13 < highcard) && (Played[0].card[0] == suitled) && (hightrump == 14)) {
							player = west;
							highcard = Played[0].number%13;
						}
						else if ((Played[0].card[0] != suitled) && (BidSuit != 'N') && (Played[0].card[0] == BidSuit)) {
							player = west;
							hightrump = Played[0].number%13;
						}

						if ((Played[1].number%13 < highcard) && (Played[1].card[0] == suitled) && (hightrump == 14)) {
							player = north;
							highcard = Played[1].number%13;
						}
						else if ((Played[1].card[0] != suitled) && (BidSuit != 'N') && (Played[1].card[0] == BidSuit) && (Played[1].number%13 < hightrump)) {
							player = north;
							hightrump = Played[1].number%13;
						}

						if ((Played[2].number%13 < highcard) && (Played[2].card[0] == suitled) && (hightrump == 14)) {
							player = east;
							highcard = Played[2].number%13;
						}
						else if ((Played[2].card[0] != suitled) && (BidSuit != 'N') && (Played[2].card[0] == BidSuit) && (Played[2].number%13 < hightrump)) {
							player = east;
							hightrump = Played[2].number%13;
						}

						if ((Played[3].number%13 < highcard) && (Played[3].card[0] == suitled) && (hightrump == 14)) {
							player = south;
							highcard = Played[3].number%13;
						}
						else if ((Played[3].card[0] != suitled) && (BidSuit != 'N') && (Played[3].card[0] == BidSuit) && (Played[3].number%13 < hightrump)) {
							player = south;
							hightrump = Played[3].number%13;
						}
						if ((player == west) || (player == east))
							TricksLost[13]++;
						if (player == west)
							winner[W++] = 'W';
						else if (player == north)
							winner[W++] = 'N';
						else if (player == east)
							winner[W++] = 'E';
						else if (player == south)
							winner[W++] = 'S';
					} // end of if (cardsplayed == 4)
					tricksplayed++;
					currentcard = 0; // for next hand
				}
				if (!firstplay)
					firstplay = TRUE;
			} // end of else if (wParam == VK_RETURN)
			InvalidateRect(hwnd, &rect, FALSE);
		}
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		FillRect(hdcMem, &rect, (HBRUSH)hGreenBrush);
		SetBkMode(hdcMem, TRANSPARENT);
		if (bidding) {
			player = NULL;
			highcardpoints[0] = highcardpoints[1] = highcardpoints[2] = highcardpoints[3] = 0;
			for (x = 0; x < 13; x++)
			{//get high card points
				highcardpoints[0] += pts[(west[x].number) % 13];
				highcardpoints[1] += pts[(north[x].number) % 13];
				highcardpoints[2] += pts[(east[x].number) % 13];
				highcardpoints[3] += pts[(south[x].number) % 13];
			}
			SetTextColor(hdcMem, 0xFFFFFF);
			TextOut(hdcMem, 10, 10, West, 4);
			TextOut(hdcMem, 90, 10, North, 5);
			TextOut(hdcMem, 170, 10, East, 4);
			TextOut(hdcMem, 250, 10, South, 5);
			hOldFont = SelectObject(hdcMem, hFont);
			SelectObject(hdcMem, hOldFont);

			if (((LastBid[5] == 0) && (passes == 3)) || (passes < 3)) {
				if (((Dealer+Bidder)%4) == 0) {
					Bidding[0] = ' ';
					for (x = 1, y = 0; x < 5; x++, y++)
						Bidding[x] = West[y];
					TextOut(hdcMem, WestLeft, EWCardTop-20, Bidding, 11); // WEST
				}
				else if (((Dealer+Bidder)%4) == 1) {
					for (x = 0; x < 5; x++)
						Bidding[x] = North[x];
					TextOut(hdcMem, HandLeft, 10+CardHeight+10, Bidding, 11); // NORTH
				}
				else if (((Dealer+Bidder)%4) == 2) {
					Bidding[0] = ' ';
					for (x = 1, y = 0; x < 5; x++, y++)
						Bidding[x] = East[y];
					TextOut(hdcMem, EastBiddingLeft, EWCardTop-20, Bidding, 11); // EAST
				}
				else if (((Dealer+Bidder)%4) == 3) {
					for (x = 0; x < 5; x++)
						Bidding[x] = South[x];
					TextOut(hdcMem, HandLeft, HandTop-20, Bidding, 11); // SOUTH
				}
			}

			if (showallcards) {
				for (v = 0, x = WestLeft, y = EWCardTop, w = 0; w < 4; w++) {
					for (z = 0; z < SuitLengths[0][w]; v++, x += 25, z++)
						ShowCard(west, x, y, v);
				}
				ShowPoints(0);
				for (v = 0, x = HandLeft, y = 10, w = 0; w < 4; w++) {
					for (z = 0; z < SuitLengths[1][w]; v++, x += 25, z++)
						ShowCard(north, x, y, v);
				}
				ShowPoints(1);
				for (v = 0, x = EastBiddingLeft, y = EWCardTop, w = 0; w < 4; w++) {
					for (z = 0; z < SuitLengths[2][w]; v++, x += 25, z++)
						ShowCard(east, x, y, v);
				}
				ShowPoints(2);
				for (v = 0, x = HandLeft, y = HandTop, w = 0; w < 4; w++) {
					for (z = 0; z < SuitLengths[3][w]; v++, x += 25, z++)
						ShowCard(south, x, y, v);
				}
				ShowPoints(3);
			} // end of if (showallcards)

			else { // begin here by showing Dealer cards
				if (((Dealer+Bidder)%4) == 0) {
					for (v = 0, x = WestLeft, y = EWCardTop, w = 0; w < 4; w++) {
						for (z = 0; z < SuitLengths[0][w]; v++, x += 25, z++)
							ShowCard(west, x, y, v);
					}
					ShowPoints(0);
				}
				else if (((Dealer+Bidder)%4) == 1) {
					for (v = 0, x = HandLeft, y = 10, w = 0; w < 4; w++) {
						for (z = 0; z < SuitLengths[1][w]; v++, x += 25, z++)
							ShowCard(north, x, y, v);
					}
					ShowPoints(1);
				}

				else if (((Dealer+Bidder)%4) == 2) {
					for (v = 0, x = EastBiddingLeft, y = EWCardTop, w = 0; w < 4; w++) {
						for (z = 0; z < SuitLengths[2][w]; v++, x += 25, z++)
							ShowCard(east, x, y, v);
					}
					ShowPoints(2);
				}

				else if (((Dealer+Bidder)%4) == 3) {
					for (v = 0, x = HandLeft, y = HandTop, w = 0; w < 4; w++) {
						for (z = 0; z < SuitLengths[3][w]; v++, x += 25, z++)
							ShowCard(south, x, y, v);
					}
					ShowPoints(3);
				}
			}

			if (first) {
				one = -1;
				first = FALSE;
				hwndBid = CreateWindow("EDIT", NULL,
					WS_CHILD | WS_VISIBLE,
					xBid, yBid, 50, 20,
					hwnd, (HMENU)1, hInst, NULL);
				pBidProc = (WNDPROC)SetWindowLong(hwndBid, GWL_WNDPROC, (LONG)BidProc);
				SetFocus(hwndBid);
			}
			SetTextColor(hdcMem, 0xFFFFFF);
			if (Dealer == 0) x = 10;
			else if (Dealer == 1) x = 90;
			else if (Dealer == 2) x = 170;
			else if (Dealer == 3) x = 250;
			for (y = 30, z = 0; z <= Bidder; z++) {
				if (Bid[z][0])
					TextOut(hdcMem, x, y, Bid[z], strlen(Bid[z]));
				x += 80;
				if (x == 330) {
					x = 10;
					y += 30;
				}
			}
			if (showbid) {
				showbid = FALSE;
				if (((LastBid[5]) && (passes == 3)) || (passes == 4)) {
					DestroyWindow(hwndBid);
					SetFocus(hwnd);
//					fromx = true;
//					SendMessage(hwnd, WM_COMMAND, ID_FILES_SAVEGAME, 0);
					goto play; // BID ENDED
				}
			}
		} // end of if (bidding)

		else { // if playing
			SetTextColor(hdcMem, 0xFFFFFF);
			Y = 40;
			for (y = 0; Bid[y][0] != 0; y++) {
				if (y%4)
					x = y%4;
				else {
					x = 0;
					Y += 20;
				}
				TextOut(hdcMem, x*80, Y, Bid[y], lstrlen(Bid[y]));
			}
			TextOut(hdcMem, 0, 10, LastBid, strlen(LastBid));
			TextOut(hdcMem, 0, 30, TricksLost, 14);
			Y = (rect.bottom-180);
			TextOut(hdcMem, 280, Y, "Spades", 6);
			TextOut(hdcMem, 280, Y+20, "Hearts", 6);
			TextOut(hdcMem, 280, Y+40, "Clubs", 5);
			TextOut(hdcMem, 280, Y+60, "Diamonds", 8);
			for (y = 0; y < 4; y++) {
				for (z = 150, x = 0; x < 13; z++, x++)
					TextOut(hdcMem, 150+(10*x), Y+(20*y), "_", 1);
			}
			for (x = 0; x < cp; x++) { // show all cards played
				Char = numbers[CardsPlayed[x].number];
				TextOut(hdcMem, 150+(10*(CardsPlayed[x].number%13)), Y+(20*(CardsPlayed[x].number/13)), &Char, 1);
			}
			Y = rect.bottom - 280;
			TextOut(hdcMem, 5, Y+20, "W", 1);
			for (X = 0; winner[X] != 0; X++)
				TextOut(hdcMem, 5, Y+40+(X*20), &winner[X], 1);
			for (x = 0, y = 25; x < 52; x++, y += 30) {
				if (0 == (x%4)) {
					y = 25;
					Y += 20;
				}
				if (Red[x]) SetTextColor(hdcMem, 0x6060F0);
				else if (Green[x]) SetTextColor(hdcMem, 0x60D060);
				else SetTextColor(hdcMem, 0xF0F0F0);
				TextOut(hdcMem, y, Y, CardsPlayed[x].card, 2);
			}
			for (z = 0; z < 4; z++) { // show played cards
				if (Playing[z].player != 0xFF) {
					x = Playing[z].x;
					y = Playing[z].y;
					v = 0xFF; // flag
					w = Playing[z].suitnum;
					card[0] = Playing[z].card;
					ShowCard(player, x, y, v);
				}
			}

			if (showallcards) {
				y = WestTop;
				for (v = 0, w = 0; w < 4; w++, y += (CardHeight/3)) {
					for (x = WestLeft, z = 0; z < SuitLengths[0][w]; x += 25, z++, v++) { // WEST
						if (loaded) {
							currentcard = 0xFF; // trick
							if ((west[v].card[0] == Plays[pl][0]) && (west[v].card[1] == Plays[pl][1])) {
								currentcard = v; // to highlight card to play
							}
						}
						ShowCard(west, x, y, v);
					}
				}
				y = EastTop;
				for (v = 0, w = 0; w < 4; w++, y += (CardHeight/3)) {
					for (x = EastLeft, z = 0; z < SuitLengths[2][w]; x += 25, z++, v++) { // EAST
						if (loaded) {
							currentcard = 0xFF; // trick
							if ((east[v].card[0] == Plays[pl][6]) && (east[v].card[1] == Plays[pl][7])) {
								currentcard = v;
							}
						}
						ShowCard(east, x, y, v);
					}
				}
				y = HandTop;
				for (v = 0, x = HandLeft, w = 0; w < 4; w++) {
					for (y = HandTop, z = 0; z < SuitLengths[3][w]; v++, x += 25, z++) { // SOUTH
						if (loaded) {
							currentcard = 0xFF; // trick
							if ((south[v].card[0] == Plays[pl][9]) && (south[v].card[1] == Plays[pl][10])) {
								currentcard = v;
							}
						}
						ShowCard(south, x, y, v);
					}
				}
				y = 10;
				for (v = 0, x = DummyLeft, w = 0; w < 4; w++, x += (CardWidth + 20)) {
					for (y = 10, z = 0; z < SuitLengths[1][w]; v++, y += 28, z++)  { // NORTH
						if (loaded) {
							currentcard = 0xFF; // trick
							if ((north[v].card[0] == Plays[pl][3]) && (north[v].card[1] == Plays[pl][4])) {
								currentcard = v;
							}
						}
						ShowCard(north, x, y, v);
					}
				}
			} // end of if (showallcards)

			else {
				if ((player == west) || (showallcards)) {
					y = WestTop;
					for (v = 0, w = 0; w < 4; w++, y += (CardHeight/3)) {
						for (x = WestLeft, z = 0; z < SuitLengths[0][w]; x += 25, z++, v++) { // WEST
							if (loaded) {
								currentcard = 0xFF; // trick
								if ((west[v].card[0] == Plays[pl][0]) && (west[v].card[1] == Plays[pl][1])) {
									currentcard = v;
								}
							}
							ShowCard(west, x, y, v);
						}
					}
				}
				if ((player == east) || (showallcards)) {
					y = EastTop;
					for (v = 0, w = 0; w < 4; w++, y += (CardHeight/3)) {
						for (x = EastLeft, z = 0; z < SuitLengths[2][w]; x += 25, z++, v++) { // EAST
							if (loaded) {
								currentcard = 0xFF; // trick
								if ((east[v].card[0] == Plays[pl][6]) && (east[v].card[1] == Plays[pl][7])) {
									currentcard = v;
								}
							}
							ShowCard(east, x, y, v);
						}
					}
				}

				if (((player != west) && (player != east))  || (showallcards)) {
					y = HandTop;
					for (v = 0, x = HandLeft, w = 0; w < 4; w++) {
						for (y = HandTop, z = 0; z < SuitLengths[3][w]; v++, x += 25, z++) { // SOUTH
							if (loaded) {
								currentcard = 0xFF; // trick
								if ((south[v].card[0] == Plays[pl][9]) && (south[v].card[1] == Plays[pl][10])) {
									currentcard = v;
								}
							}
							ShowCard(south, x, y, v);
						}
					}
				}
				if (firstplay) {
					y = 10;
					for (v = 0, x = DummyLeft, w = 0; w < 4; w++, x += (CardWidth + 20)) {
						for (y = 10, z = 0; z < SuitLengths[1][w]; v++, y += 28, z++) // NORTH
							ShowCard(north, x, y, v);
					}
				}
			}
		}
		BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
		EndPaint(hwnd, &ps);
		return 0;

	case WM_DESTROY:
		if (pbn)
			VirtualFree(pbn, 0, MEM_RELEASE);
		if (dwRandomBytesRead)
			free(RandomBytes);
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}
/*
void ParseLin(struct Hands *ptr)
{
	z = 0;
	y++;

	for ( ; (lin[y] != 'H') && (lin[y] != 'D') && (lin[y] != 'C') && (lin[y] != End); y++) {
		ptr[z].card[0] = 'S';
		ptr[z].card[1] = lin[y];
		ptr[z].number = y-x;
		z++;
		SuitLengths[0][0]++;
	}
	for (y++; (lin[y] != 'D') && (lin[y] != 'C') && (lin[y] != End); y++) {
		ptr[z].card[0] = 'H';
		ptr[z].card[1] = lin[y];
		ptr[z].number = y-x+13;
		z++;
		SuitLengths[0][0]++;
	}
	for (y++; (lin[y] != 'C') && (lin[y] != End); y++) {
		ptr[z].card[0] = 'D';
		ptr[z].card[1] = lin[y];
		ptr[z].number = y-x+26;
		z++;
		SuitLengths[0][0]++;
	}
	for (y++; (lin[y] != End); y) {
		ptr[z].card[0] = 'C';
		ptr[z].card[1] = lin[y++];
		ptr[z].number = y-x+39;
		z++;
		SuitLengths[0][0]++;
	}
	y++; // past End
}

 case ID_LOADGAME: for lin files
			hFile = CreateFile("C:\\62368_lin.txt", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
			if (hFile != INVALID_HANDLE_VALUE) {
				fileSize = GetFileSize(hFile, NULL);
				if (fileSize) {
					if (lin)
						VirtualFree(lin, 0, MEM_RELEASE);
					lin = (char*)VirtualAlloc(NULL, fileSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
					ReadFile(hFile, lin, fileSize, &dwBytesRead, NULL);
					CloseHandle(hFile);
					for (x = 0; x < (int)fileSize; x++) { // parse .lin file
						if ((lin[x] == 'm') && (lin[x+1] == 'd') && (lin[x+2] == '|')) { // bid begin
							x += 3;
							Dealer = lin[x++];
							for (z = 0; z < 13; z++) {
								*(WORD*)&south[z].card = 0;
								*(WORD*)&west[z].card = 0;
								*(WORD*)&north[z].card = 0;
								*(WORD*)&east[z].card = 0;
							}
							z = 0;
							y = x;
							End = ',';
							// put cards in hands
							ParseLin(south);
							ParseLin(west);
							ParseLin(north);
							End = '|';
							ParseLin(east);
							x=x;

							// get bids
							for (w = 0; w < 13; w++) {
								Bids[w][0] = 0;
								Bids[w][1] = 0;
							}
							linbidding = TRUE;
							for (w = 0; w < 12; w++) {
								for ( ; (lin[y] != 'm') && (lin[y+1] != 'b'); y++) {
									if ((lin[y] == 'p') && (lin[y+1] == 'c')) {
										linbidding = FALSE;
										break;
									}
								}
								if (!linbidding)
									break;
								y += 3; // to first bid
								Bids[w][0] = lin[y++];
								if (lin[y] != '|')
									Bids[w][1] = lin[y++];

							}
						}
					}
					// get plays
					y += 3;
					for (w = 0; w < 13; w++) {
						Plays[w][0] = 0;
						Plays[w][1] = 0;
					}
					linplaying = TRUE;
					for (w = 0; (w < 52); w++) {
						Plays[w][0] = lin[y++];
						Plays[w][1] = lin[y++];
						for ( ; ; y++) {
							if ((lin[y] == 'p') && (lin[y+1] == 'c'))
								break;
							if ((lin[y] == 'p') && (lin[y+1] == 'g')) {
								y += 5;
								continue;
							}
							if ((lin[y] == 'm') && (lin[y+1] == 'c')) {
								linplaying = FALSE;
								break;
							}
						}
						if (linplaying == FALSE)
							break;
						y += 3;
					}
					x=x;
			}
*/