home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame Game Cube 5: Strategy
/
aztechhalloffamegamecubedisc5-
/
flip
/
install
/
flipit.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-15
|
36KB
|
1,339 lines
//REGEN_FILEHEADING
#include <commdlg.h>
#include <windowsx.h>
#include <fstream.h>
#include <math.h>
//REGEN_FILEHEADING
/********************************************************************
* *
* Source File: Flipit.cpp *
* Description: C++ Source file for Flipit application *
* Date: Sat Jun 25 15:12:28 1994 *
* *
********************************************************************/
#include <owl.h>
#include <edit.h>
#include <listbox.h>
#include <combobox.h>
#include <scrollba.h>
#include <dialog.h>
#include <bwcc.h>
#include "FlipitID.h"
#include "Flipit.h"
#include "FlipiCls.h"
//REGEN_VARIABLES
int Player = 0,nPass = 0,Player1 = 1, Player2 = 2;
int NumPlayers = 2;
int BoardSize = 8,OldBoardSize = 8;
POINT LastMove;
char SaveFile[255] = "";
int nSize,nSquare,nXmargin,nYmargin;
int Difficulty=MEDIUM, OldDifficulty=MEDIUM;
int nStatusBar;
BOOL bDefault=FALSE, bReFresh=FALSE;
class TUndo
{ public:
char UndoArr[12][12];
int UndoPlayer,nUndoPass;
int nUndoWhiteScore,nUndoBlackScore;
POINT UndoLastMove;
friend istream& operator >> ( istream&, TUndo& );
// reads a Board from a stream. The
// format used must match the format used
// by operator <<.
friend ostream& operator << ( ostream&, TUndo& );
// writes a Board to a stream. The
// format used must match the format used
// by operator >>.
friend istream& operator >> ( istream&, POINT& );
// reads a Point from a stream. The
// format used must match the format used
// by operator <<.
friend ostream& operator << ( ostream&, POINT& );
// writes a POINT to a stream. The
// format used must match the format used
// by operator >>.
};
struct WEIGHTTAG
{
long double Mult;
int x,y;
};
class TBoard
{ public:
char BoardArr[12][12];
WEIGHTTAG Weight[100];
BOOL bFlip,bCheat;
POINT Vectors[8];
TBoard();
int nWhiteScore,nBlackScore;
virtual void TBoard::InitBoard(BOOL bFirst);
virtual void DrawBoard(HDC PaintDC);
virtual void FlipBoard(HDC PaintDC);
virtual BOOL ValidMove(POINT p);
virtual void MakeMove(POINT p);
virtual void DrawSquare(HDC PaintDC, RECT r, int Shadow);
virtual void PlacePiece(HDC PaintDC, RECT r, int nRow, int nCol);
virtual int ChkVector(HDC PaintDC, int Col, int Row, int Vector,
int Other, int Player, BOOL Flip);
virtual void UpdScore(HDC PaintDC);
virtual long double GoComputer(int Player, int Level);
friend istream& operator >> ( istream&, TBoard& );
// reads a Board from a stream. The
// format used must match the format used
// by operator <<.
friend ostream& operator << ( ostream&, TBoard& );
// writes a Board to a stream. The
// format used must match the format used
// by operator >>.
friend istream& operator >> ( istream&, POINT& );
// reads a Point from a stream. The
// format used must match the format used
// by operator <<.
friend ostream& operator << ( ostream&, POINT& );
// writes a POINT to a stream. The
// format used must match the format used
// by operator >>.
};
TBoard Board;
TUndo Undo;
void Undo2Board( TUndo& , TBoard& );
void Board2Undo( TBoard& , TUndo& );
HINSTANCE ghInstance;
HWND ghWindow;
//REGEN_VARIABLES
// Define application class derived from TApplication
class TFlipit : public TApplication
{
public:
TFlipit(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
: TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {};
virtual void InitMainWindow();
virtual void InitInstance();
//REGEN_APPCLASS
//REGEN_APPCLASS
};
void TFlipit::InitInstance()
{
TApplication::InitInstance();
HAccTable = LoadAccelerators(hInstance, "Flipit");
}
// Declare TMainWindow, a TWindow descendant
class TMainWindow : public TWindow
{
public:
TMainWindow(PTWindowsObject AParent, LPSTR ATitle);
~TMainWindow();
virtual void NEW(RTMessage Msg) = [CM_FIRST + IDM_NEW];
virtual void OPEN(RTMessage Msg) = [CM_FIRST + IDM_OPEN];
virtual void SAVEAS(RTMessage Msg) = [CM_FIRST + IDM_SAVEAS];
virtual void EXIT(RTMessage Msg) = [CM_FIRST + IDM_EXIT];
virtual void UNDO(RTMessage Msg) = [CM_FIRST + IDM_UNDO];
virtual void HINT(RTMessage Msg) = [CM_FIRST + IDM_HINT];
virtual void CHEAT(RTMessage Msg) = [CM_FIRST + IDM_CHEAT];
virtual void PREFERENCES(RTMessage Msg) = [CM_FIRST + IDM_PREFERENCES];
virtual void CONTENTS(RTMessage Msg) = [CM_FIRST + IDM_CONTENTS];
virtual void ABOUT(RTMessage Msg) = [CM_FIRST + IDM_ABOUT];
//REGEN_MAINCLASS
virtual void Paint(HDC PaintDC, PAINTSTRUCT &PaintInfo);
virtual void WMLButtonDown(RTMessage Msg) = [WM_FIRST+WM_LBUTTONDOWN];
virtual void WMSize(RTMessage Msg) = [WM_FIRST + WM_SIZE];
virtual void WMMouseMove(RTMessage Msg) = [WM_FIRST + WM_MOUSEMOVE];
virtual void WMTimer(RTMessage Msg) = [WM_FIRST + WM_TIMER];
virtual int WMSetFocus(RTMessage Msg) = [WM_FIRST + WM_SETFOCUS];
virtual int WMKillFocus(RTMessage Msg) = [WM_FIRST + WM_KILLFOCUS];
virtual void WMInitMenu(RTMessage Msg) = [WM_FIRST + WM_INITMENU];
virtual int WMMenuSelect(RTMessage Msg) = [WM_FIRST + WM_MENUSELECT];
virtual void SetupWindow();
virtual void OpenFiFile( LPSTR lpstrFile );
virtual void SaveFiFile( LPSTR lpstrFile );
private:
HBRUSH hMainBrush;
//REGEN_MAINCLASS
protected:
virtual void GetWindowClass(WNDCLASS _FAR & AWndClass);
virtual LPSTR GetClassName();
};
/****************************************************
* TMainWindow implementations:
****************************************************/
// Define TMainWindow, a TWindow constructor
TMainWindow::TMainWindow(PTWindowsObject AParent, LPSTR ATitle)
: TWindow(AParent, ATitle)
{
AssignMenu("Flipit");
//REGEN_MAINCONSTRUCT
Attr.W = 400;
Attr.H = 400;
NumPlayers = Player = 1;
OldBoardSize = BoardSize = GetPrivateProfileInt("Preferences", "BoardSize", 8, "FLIPIT.INI");
nSize = nSquare = nXmargin = nYmargin = 0;
Board2Undo(Board,Undo);
//REGEN_MAINCONSTRUCT
}
// Define TMainWindow destructor
TMainWindow::~TMainWindow()
{
//REGEN_MAINDESTRUCT
KillTimer(HWindow,10);
DeleteBrush(hMainBrush);
//REGEN_MAINDESTRUCT
}
LPSTR TMainWindow::GetClassName()
{
return "MainWindow";
}
void TMainWindow::GetWindowClass(WNDCLASS _FAR & AWndClass)
{
TWindow::GetWindowClass(AWndClass);
AWndClass.hIcon = LoadIcon(AWndClass.hInstance, "FLIPIT");
//REGEN_CLASSINFO
hMainBrush = CreateSolidBrush(RGB(0,128,0));
AWndClass.hbrBackground = hMainBrush;
AWndClass.hCursor = NULL;
//REGEN_CLASSINFO
}
void TMainWindow::NEW(RTMessage)
{
//REGEN_NEW_EXEC
Board.InitBoard(FALSE);
InvalidateRect(HWindow,NULL,TRUE);
//REGEN_NEW_EXEC
}
void TMainWindow::OPEN(RTMessage Msg)
{
//REGEN_OPEN_EXEC
OPENFILENAME Ofn;
HFILE hFile;
OFSTRUCT FAR* lpOpenBuff;
int j;
char Filters[] = "Flip It Files (*.fi)\0*.fi\0"
"All Files (*.*)\0*.*\0";
WMInitMenu(Msg);
memset(&Ofn, 0, sizeof(OPENFILENAME));
Ofn.lpstrTitle = "Choose a File";
Ofn.hwndOwner = HWindow;
Ofn.lpstrFilter = (LPSTR) Filters;
Ofn.nFilterIndex = 1;
Ofn.lpstrFile = (LPSTR)SaveFile;
Ofn.nMaxFile = sizeof(SaveFile);
Ofn.Flags = OFN_FILEMUSTEXIST | \
OFN_HIDEREADONLY | \
OFN_PATHMUSTEXIST;
Ofn.lpstrDefExt = "fi";
Ofn.lStructSize = sizeof(OPENFILENAME);
GetOpenFileName(&Ofn);
OpenFiFile( Ofn.lpstrFile );
WMSize(Msg);
WMSetFocus(Msg);
InvalidateRect(HWindow,NULL,FALSE);
//REGEN_OPEN_EXEC
}
void TMainWindow::SAVEAS(RTMessage Msg)
{
//REGEN_SAVEAS_EXEC
OPENFILENAME Ofn;
HFILE hFile;
OFSTRUCT FAR* lpOpenBuff;
int j;
char Filters[] = "Flip It Files (*.fi)\0*.fi\0"
"All Files (*.*)\0*.*\0";
WMInitMenu(Msg);
memset(&Ofn, 0, sizeof(OPENFILENAME));
Ofn.lpstrTitle = "Save File As";
Ofn.hwndOwner = HWindow;
Ofn.lpstrFilter = (LPSTR) Filters;
Ofn.nFilterIndex = 1;
Ofn.lpstrFile = (LPSTR)SaveFile;
Ofn.nMaxFile = sizeof(SaveFile);
Ofn.Flags = OFN_FILEMUSTEXIST | \
OFN_HIDEREADONLY | \
OFN_PATHMUSTEXIST;
Ofn.lpstrDefExt = "fi";
Ofn.lStructSize = sizeof(OPENFILENAME);
GetSaveFileName(&Ofn);
SaveFiFile( Ofn.lpstrFile );
WMSetFocus(Msg);
//REGEN_SAVEAS_EXEC
}
void TMainWindow::EXIT(RTMessage)
{
//REGEN_EXIT_EXEC
CloseWindow();
//REGEN_EXIT_EXEC
}
void TMainWindow::UNDO(RTMessage)
{
//REGEN_UNDO_EXEC
Undo2Board(Undo,Board);
InvalidateRect(HWindow,NULL,FALSE);
//REGEN_UNDO_EXEC
}
void TMainWindow::HINT(RTMessage)
{
//REGEN_HINT_EXEC
SetCursor(LoadCursor(NULL,IDC_WAIT));
Board2Undo(Board,Undo);
Board.GoComputer(Player,1);
SetCursor(LoadCursor(NULL,IDC_ARROW));
//REGEN_HINT_EXEC
}
void TMainWindow::CHEAT(RTMessage)
{
//REGEN_CHEAT_EXEC
Board.bCheat = TRUE;
//REGEN_CHEAT_EXEC
}
void TMainWindow::PREFERENCES(RTMessage Msg)
{
// Execute modal dialog
if (GetModule()->ExecDialog(
new TPREFERDlg(this, "PREFER")) == IDOK )
{
//REGEN_PREFERENCES_EXEC
if (OldBoardSize != BoardSize || OldDifficulty != Difficulty)
{
NEW(Msg);
WMSize(Msg);
OldBoardSize = BoardSize;
}
if (bDefault)
{
if (Player1 == 1)
WritePrivateProfileString("Preferences", "Player1", "1", "FLIPIT.INI");
else
WritePrivateProfileString("Preferences", "Player1", "2", "FLIPIT.INI");
if (Player2 == 1)
WritePrivateProfileString("Preferences", "Player2", "1", "FLIPIT.INI");
else
WritePrivateProfileString("Preferences", "Player2", "2", "FLIPIT.INI");
switch ( BoardSize )
{
case 6:
WritePrivateProfileString("Preferences", "BoardSize", "6", "FLIPIT.INI");
break;
case 8:
WritePrivateProfileString("Preferences", "BoardSize", "8", "FLIPIT.INI");
break;
case 10:
WritePrivateProfileString("Preferences", "BoardSize", "10", "FLIPIT.INI");
break;
}
switch ( Difficulty )
{
case 1:
WritePrivateProfileString("Preferences", "Difficulty", "1", "FLIPIT.INI");
break;
case 2:
WritePrivateProfileString("Preferences", "Difficulty", "2", "FLIPIT.INI");
break;
case 3:
WritePrivateProfileString("Preferences", "Difficulty", "3", "FLIPIT.INI");
break;
}
}
InvalidateRect(HWindow,NULL,TRUE);
//REGEN_PREFERENCES_EXEC
}
}
void TMainWindow::CONTENTS(RTMessage)
{
//REGEN_CONTENTS_EXEC
WinHelp( ghWindow, "FLIPIT.HLP", HELP_CONTENTS, 0L );
//REGEN_CONTENTS_EXEC
}
void TMainWindow::ABOUT(RTMessage)
{
// Execute modal dialog
if (GetModule()->ExecDialog(
new TDIALOG_1Dlg(this, "DIALOG_1")) == IDOK )
{
//REGEN_ABOUT_EXEC
//REGEN_ABOUT_EXEC
}
}
/***************************************************
* TFlipitApp method implementations:
***************************************************/
// Construct the TFlipit's MainWindow of type TMainWindow
void TFlipit::InitMainWindow()
{
MainWindow = new TMainWindow(NULL, Name);
//REGEN_MAINCREATE
ghInstance = hInstance;
//REGEN_MAINCREATE
}
// Main program
int PASCAL WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HINSTANCE hBorLibrary;
hBorLibrary = LoadLibrary("bwcc.dll");
if((UINT)hBorLibrary <= 32)
MessageBox(NULL, "Unable to load Borland Controls", "System Error", MB_OK | MB_ICONHAND);
//REGEN_INIT
//REGEN_INIT
TFlipit Flipit ("Flip it", hInstance, hPrevInstance,
lpCmdLine, nCmdShow);
Flipit.Run();
if((UINT)hBorLibrary > 32)
FreeLibrary(hBorLibrary);
//REGEN_CLEANUP
//REGEN_CLEANUP
return Flipit.Status;
}
//REGEN_CUSTOMCODE
void TMainWindow::SetupWindow()
{
TWindow::SetupWindow();
SetTimer(HWindow,10,1500,NULL);
}
#pragma argsused
void TMainWindow::Paint(HDC PaintDC, PAINTSTRUCT &PaintInfo)
{
ghWindow = HWindow;
if (bReFresh)
Board.UpdScore(PaintDC);
Board.DrawBoard(PaintDC);
}
void TMainWindow::WMLButtonDown(RTMessage Msg)
{
POINT p;
HCURSOR hCursor;
p.x = Msg.LP.Lo; p.y = Msg.LP.Hi;
if ( Board.ValidMove(p) )
{
Board2Undo(Board,Undo);
Board.MakeMove(p);
InvalidateRect(HWindow,NULL,FALSE);
}
}
void TMainWindow::WMSize(RTMessage)
{
RECT r;
bReFresh = TRUE;
GetClientRect(HWindow,&r);
nStatusBar = GetSystemMetrics(SM_CYMENU); // Height of Horz Scroll Bar
if ( r.right < r.bottom )
nSize = r.right;
else
nSize = r.bottom;
nSquare = nSize/(BoardSize+2);
nXmargin = (r.right-nSquare*BoardSize)/2;
nYmargin = (r.bottom-nSquare*BoardSize-nStatusBar)/2;
}
void TMainWindow::WMMouseMove(RTMessage Msg)
{
// determine board coordinates
POINT p;
HCURSOR hCursor;
p.x = Msg.LP.Lo; p.y = Msg.LP.Hi;
if ( Board.ValidMove(p) )
SetCursor(LoadCursor(NULL,IDC_CROSS));
else
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
TBoard::TBoard()
{
InitBoard(TRUE);
}
#pragma argsused
void TBoard::InitBoard(BOOL bFirst)
{
int nRow,nCol,nLevel,i,j,Max;
WEIGHTTAG Temp;
if (bFirst)
{
BoardSize = GetPrivateProfileInt("Preferences", "BoardSize", 8, "FLIPIT.INI");
Difficulty = GetPrivateProfileInt("Preferences", "Difficulty", 2, "FLIPIT.INI");
Player1 = GetPrivateProfileInt("Preferences", "Player1", 1, "FLIPIT.INI");
Player2 = GetPrivateProfileInt("Preferences", "Player2", 2, "FLIPIT.INI");
}
Player = 1;
bCheat = FALSE;
memset(&BoardArr, 0, sizeof(BoardArr));
BoardArr[BoardSize/2][BoardSize/2] = \
BoardArr[BoardSize/2+1][BoardSize/2+1] = 1;
BoardArr[BoardSize/2+1][BoardSize/2] = \
BoardArr[BoardSize/2][BoardSize/2+1] = 2;
LastMove.x = BoardSize/2+1; LastMove.y = BoardSize/2;
nWhiteScore = nBlackScore = 2;
Vectors[0].x = 0; Vectors[0].y = -1; //North
Vectors[1].x = 1; Vectors[1].y = -1; //Northeast
Vectors[2].x = 1; Vectors[2].y = 0; //East
Vectors[3].x = 1; Vectors[3].y = 1; //Southeast
Vectors[4].x = 0; Vectors[4].y = 1; //South
Vectors[5].x = -1; Vectors[5].y = 1; //Southwest
Vectors[6].x = -1; Vectors[6].y = 0; //West
Vectors[7].x = -1; Vectors[7].y = -1; //Northwest
bFlip = FALSE;
for (i=0;i<100;i++)
{
Weight[i].Mult= Weight[i].x = Weight[i].y = 0;
}
if (Difficulty == 0)
Difficulty = MEDIUM;
for (nCol=1;nCol<=BoardSize;nCol++)
for (nRow=1;nRow<=BoardSize;nRow++)
{
i=(nRow-1)*BoardSize+nCol-1;
Weight[i].x = nCol;
Weight[i].y = nRow;
if ((nCol == 1 || nCol == BoardSize) \
&& (nRow == 1 || nRow == BoardSize))
Weight[i].Mult = 5000;
else if (nCol == 1 || nCol == BoardSize \
|| nRow == 1 || nRow == BoardSize)
Weight[i].Mult = 30;
else if ((nCol == 3 || nCol == BoardSize-2) \
&& (nRow == 3 || nRow == BoardSize-2))
Weight[i].Mult = 20;
else if (((nCol == 3 || nCol == BoardSize-2) \
&& nRow > 3 && nRow < BoardSize-2) \
|| ((nRow == 10 || nRow == BoardSize-2)\
&& nCol > 3 && nCol < BoardSize-2))
Weight[i].Mult = 5;
else if ((nCol == 2 || nCol == BoardSize-1) \
&& (nRow == 2 || nRow == BoardSize-1))
Weight[i].Mult = 1;
else
Weight[i].Mult = 3;
}
for (i=0;i<BoardSize*BoardSize-1;i++)
{
Max=i;
for (j=i+1;j<BoardSize*BoardSize;j++)
if (Weight[j].Mult > Weight[Max].Mult)
Max=j;
else if (Weight[j].Mult == Weight[Max].Mult)
if (Weight[j].x > Weight[Max].x)
Max=j;
else if (Weight[j].x == Weight[Max].x && Weight[j].y > Weight[Max].y)
Max=j;
if (Max != i)
{
Temp = Weight[i];
Weight[i] = Weight[Max];
Weight[Max] = Temp;
}
}
OldDifficulty = Difficulty;
}
void TBoard::DrawBoard(HDC PaintDC)
{
RECT r,rSquare,rBoard;
int nRow,nCol,nOther,nVect;
BOOL bGameOver;
rBoard.left = nXmargin-2;
rBoard.top = nYmargin-2;
rBoard.right = nXmargin+nSquare*BoardSize+2;
rBoard.bottom = nYmargin+nSquare*BoardSize+2;
if (!bReFresh && bFlip)
{
rSquare.left = nXmargin+(LastMove.x-1)*nSquare+1;
rSquare.top = nYmargin+(LastMove.y-1)*nSquare+1;
rSquare.right = rSquare.left+nSquare-2;
rSquare.bottom = rSquare.top+nSquare-2;
PlacePiece(PaintDC,rSquare,LastMove.x,LastMove.y);
FlipBoard(PaintDC);
UpdScore(PaintDC);
// See if we have any valid moves left.
nOther = (Player == 1) ? 2 : 1;
bGameOver = TRUE;
nPass=0;
for (nCol=1;nCol<=BoardSize;nCol++)
for (nRow=1;nRow<=BoardSize;nRow++)
{
if (BoardArr[nCol][nRow] == 0)
{
for ( nVect=0;nVect<8;nVect++ )
if (ChkVector(NULL,nCol,nRow,nVect,nOther,Player,FALSE) > 0)
{
bGameOver = FALSE;
}
}
}
if (bGameOver == TRUE)
{
for (nCol=1;nCol<=BoardSize;nCol++)
for (nRow=1;nRow<=BoardSize;nRow++)
{
if (BoardArr[nCol][nRow] == 0)
{
for ( nVect=0;nVect<8;nVect++ )
if (ChkVector(NULL,nCol,nRow,nVect,Player,nOther,FALSE) > 0)
{
bGameOver = FALSE;
}
}
}
if (bGameOver == TRUE)
BWCCMessageBox(NULL,"Game Over.","Flip It Message",MB_OK | MB_ICONEXCLAMATION );
else if (Player == 1)
BWCCMessageBox(NULL,"White must pass, Black's turn.","Flip It Message",MB_OK | MB_ICONEXCLAMATION );
else
BWCCMessageBox(NULL,"Black must pass, White's turn.","Flip It Message",MB_OK | MB_ICONEXCLAMATION );
Player = nOther;
}
}
else
{
bReFresh = FALSE;
Rectangle(PaintDC,rBoard.left-1,rBoard.top-1,
rBoard.right+1,rBoard.bottom+1);
DrawSquare(PaintDC,rBoard,1);
MoveTo(PaintDC,nXmargin-1,nYmargin+nSquare*BoardSize+1);
for (nCol=1;nCol<=BoardSize;nCol++)
for (nRow=1;nRow<=BoardSize;nRow++)
{
rSquare.left = nXmargin+(nCol-1)*nSquare+1;
rSquare.top = nYmargin+(nRow-1)*nSquare+1;
rSquare.right = rSquare.left+nSquare-2;
rSquare.bottom = rSquare.top+nSquare-2;
DrawSquare(PaintDC,rSquare,-1);
PlacePiece(PaintDC,rSquare,nCol,nRow);
}
if (bFlip==TRUE)
InvalidateRect(ghWindow,NULL,FALSE);
}
}
void TBoard::DrawSquare(HDC PaintDC,RECT r,int Shadow)
{
HPEN hWhitePen, hGrayPen, hOldPen;
HBRUSH hGrayBrush,hOldBrush;
hGrayPen = CreatePen(PS_SOLID, 1, RGB(96,96,96));
hWhitePen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
hOldPen = SelectPen(PaintDC,hGrayPen);
hGrayBrush = GetStockBrush(LTGRAY_BRUSH);
hOldBrush = SelectBrush(PaintDC,hGrayBrush);
Rectangle(PaintDC,r.left,r.top,r.right,r.bottom);
SelectPen(PaintDC,hWhitePen);
if ( Shadow > 0 )
{
MoveTo(PaintDC,r.left,r.bottom-1);
LineTo(PaintDC,r.left,r.top);
LineTo(PaintDC,r.right-1,r.top);
}
else
{
MoveTo(PaintDC,r.left,r.bottom-1);
LineTo(PaintDC,r.right-1,r.bottom-1);
LineTo(PaintDC,r.right-1,r.top);
}
SelectPen(PaintDC,hOldPen);
SelectBrush(PaintDC,hOldBrush);
DeletePen(hWhitePen);
DeletePen(hGrayPen);
}
void TBoard::PlacePiece(HDC PaintDC, RECT r, int nCol, int nRow)
{
HDC hCompatDC;
HBITMAP hBitmap, hOldBitmap;
BITMAP BM;
int i;
// Get handle to the bitmap
switch (BoardArr[nCol][nRow])
{
case 1:
case 2:
HBRUSH hBrush,hOldBrush;
if (BoardArr[nCol][nRow] == 1)
hBrush = GetStockBrush(WHITE_BRUSH);
else
hBrush = GetStockBrush(BLACK_BRUSH);
hOldBrush = SelectBrush(PaintDC,hBrush);
Ellipse(PaintDC,r.left+1,r.top+1,r.right-1,r.bottom-1);
SelectBrush(PaintDC,hOldBrush);
return;
case 3: hBitmap = LoadBitmap(ghInstance, "BFLIP"); break;
case 4: hBitmap = LoadBitmap(ghInstance, "VERT" ); break;
case 5: hBitmap = LoadBitmap(ghInstance, "WFLIP"); break;
default: return;
}
// Get dimensions of bitmap
GetObject(hBitmap, sizeof(BM), &BM);
// Create compatible display context
hCompatDC = CreateCompatibleDC(PaintDC);
// Select bitmap into the compataible DC
hOldBitmap = SelectBitmap(hCompatDC, hBitmap);
// Display bitmap in client area
StretchBlt(PaintDC, r.left+1, r.top+1, r.right-r.left-2, r.bottom-r.top-2,
hCompatDC, 0, 0, BM.bmWidth, BM.bmHeight,
SRCCOPY);
// De-select the bitmap
SelectBitmap(hCompatDC, hOldBitmap);
// Clean up after we are done
DeleteDC(hCompatDC);
DeleteBitmap(hBitmap);
}
BOOL TBoard::ValidMove(POINT p)
{
int x,y,nRow,nCol,nVect, nOther;
if ( p.x <= nXmargin | p.y <= nYmargin ) return FALSE;
if ( p.x >= nXmargin + nSquare*BoardSize |
p.y >= nYmargin + nSquare*BoardSize ) return FALSE;
// see if current square is occupied
x=p.x-nXmargin;
y=p.y-nYmargin;
nCol = x/nSquare+1;
nRow = y/nSquare+1;
if ( bCheat )
{
if (BoardArr[nCol][nRow] == Player ) return FALSE;
}
else
if ( BoardArr[nCol][nRow] != 0 ) return FALSE;
// check board for adjacent pieces of the opposite color
// if opposite color found, see if the current color is
// on the other side
nOther = (Player==1) ? 2 : 1;
for ( nVect=0;nVect<8;nVect++ )
{
if (ChkVector(NULL,nCol,nRow,nVect,nOther,Player,FALSE) > 0)
return TRUE;
}
// if no opposite colors are found, then return false
return FALSE;
}
void TBoard::MakeMove(POINT p)
{
int x,y,nCol,nRow;
x=p.x-nXmargin;
y=p.y-nYmargin;
nCol = x/nSquare+1;
nRow = y/nSquare+1;
BoardArr[nCol][nRow] = Player;
LastMove.x = nCol; LastMove.y = nRow;
bFlip = TRUE;
bCheat = FALSE;
}
void TBoard::FlipBoard(HDC PaintDC)
{
int nOther,nVect;
nOther = (Player==1) ? 2 : 1;
for ( nVect=0;nVect<8;nVect++ )
ChkVector(PaintDC,LastMove.x,LastMove.y,nVect,nOther,Player,TRUE);
bFlip = FALSE;
Player = nOther;
}
int TBoard::ChkVector(HDC PaintDC,int NewCol, int NewRow, int nVect,int nChkPiece,\
int nFlipto, BOOL Flipit)
{ // This routine uses recursion to count the number of pieces that would be
// flipped if a piece were placed at the specified row & col.
// To see how this works, try walking through this code with a
// piece of paper and make a sample move.
int nFlipCount=0;
RECT rSquare;
NewCol += Vectors[nVect].x; NewRow += Vectors[nVect].y;
if (BoardArr[NewCol][NewRow] == nChkPiece)
{
nFlipCount++;
nFlipCount += ChkVector(PaintDC,NewCol,NewRow,nVect,nChkPiece,nFlipto,Flipit);
}
else if (BoardArr[NewCol][NewRow] == nFlipto) return 0;
else return -10;
if (Flipit && nFlipCount > 0)
{
if (PaintDC == NULL) // Flip piece but don't display it...
BoardArr[NewCol][NewRow] = Player;
else
{
rSquare.left = nXmargin+(NewCol-1)*nSquare+1;
rSquare.top = nYmargin+(NewRow-1)*nSquare+1;
rSquare.right = rSquare.left+nSquare-2;
rSquare.bottom = rSquare.top+nSquare-2;
switch (Player)
{
case 1: //White
BoardArr[NewCol][NewRow]=3;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
BoardArr[NewCol][NewRow]=4;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
BoardArr[NewCol][NewRow]=5;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
BoardArr[NewCol][NewRow]=1;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
break;
case 2: //Black
BoardArr[NewCol][NewRow]=5;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
BoardArr[NewCol][NewRow]=4;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
BoardArr[NewCol][NewRow]=3;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
BoardArr[NewCol][NewRow]=2;
PlacePiece(PaintDC,rSquare,NewCol,NewRow);
break;
}
}
}
return nFlipCount;
}
void TBoard::UpdScore(HDC PaintDC)
{
RECT r,rMessage,rWhiteScoreBmp,rWhiteScore,rBlackScoreBmp,rBlackScore;
HPEN hWhitePen, hGrayPen, hOldPen;
HDC hCompatDC;
HBITMAP hBitmap, hOldBitmap;
BITMAP BM;
WORD wScoreWidth;
char cszWhite[6],cszBlack[6];
int nOrigWhite;
nOrigWhite = nWhiteScore;
nWhiteScore = nBlackScore = 0;
int nCol,nRow;
for (nCol=1;nCol<=BoardSize;nCol++)
for (nRow=1;nRow<=BoardSize;nRow++)
switch (BoardArr[nCol][nRow])
{
case 1: nWhiteScore++; break;
case 2: nBlackScore++; break;
}
hGrayPen = CreatePen(PS_SOLID, 1, RGB(96,96,96));
hWhitePen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
memset(cszWhite,0,sizeof(cszWhite));
memset(cszBlack,0,sizeof(cszBlack));
GetClientRect(ghWindow,&r);
r.top = r.bottom-nStatusBar;
if ( bReFresh || nOrigWhite == Board.nWhiteScore )
DrawSquare(PaintDC,r,1);
wScoreWidth = LOWORD((GetTextExtent(PaintDC,"999",3)+nStatusBar+15)*2);
rMessage.left = 1;
rMessage.top = r.top+1;
rMessage.right = r.right-wScoreWidth;
rMessage.bottom = r.bottom-1;
rWhiteScoreBmp.left = r.right-wScoreWidth+10;
rWhiteScoreBmp.top = r.top+2;
rWhiteScoreBmp.bottom = r.bottom-2;
rWhiteScoreBmp.right = rWhiteScoreBmp.left+r.bottom-r.top-4;
rWhiteScore.left = rWhiteScoreBmp.right+2;
rWhiteScore.top = rMessage.top;
rWhiteScore.bottom = rMessage.bottom;
rWhiteScore.right = rWhiteScore.left
+ LOWORD(GetTextExtent(PaintDC,"999",3));
rBlackScore.right = r.right-2;
rBlackScore.left = rBlackScore.right
-LOWORD(GetTextExtent(PaintDC,"999",3))-2;
rBlackScore.top = rMessage.top;
rBlackScore.bottom = rMessage.bottom;
rBlackScoreBmp.right = rBlackScore.left-2;
rBlackScoreBmp.top = r.top+2;
rBlackScoreBmp.bottom = r.bottom-2;
rBlackScoreBmp.left = rBlackScoreBmp.right-r.bottom+r.top+4;
SetBkColor(PaintDC,RGB(192,192,192));
if ( bReFresh || nOrigWhite == Board.nWhiteScore )
{
hOldPen = SelectPen(PaintDC,hGrayPen);
MoveTo(PaintDC,rMessage.right,rMessage.top);
LineTo(PaintDC,rMessage.right,rMessage.bottom+1);
SelectPen(PaintDC,hWhitePen);
MoveTo(PaintDC,rMessage.right+1,rMessage.top);
LineTo(PaintDC,rMessage.right+1,rMessage.bottom+1);
SelectPen(PaintDC,hOldPen);
hBitmap = LoadBitmap(ghInstance, "WHITE");
// Get dimensions of bitmap
GetObject(hBitmap, sizeof(BM), &BM);
// Create compatible display context
hCompatDC = CreateCompatibleDC(PaintDC);
// Select bitmap into the compataible DC
hOldBitmap = SelectBitmap(hCompatDC, hBitmap);
// Display bitmap in client area
StretchBlt(PaintDC, rWhiteScoreBmp.left, rWhiteScoreBmp.top,
rWhiteScoreBmp.right-rWhiteScoreBmp.left,
rWhiteScoreBmp.bottom-rWhiteScoreBmp.top,
hCompatDC, 0, 0, BM.bmWidth, BM.bmHeight,
SRCCOPY);
SelectBitmap(hCompatDC, hOldBitmap);
DeleteDC(hCompatDC);
DeleteBitmap(hBitmap);
hBitmap = LoadBitmap(ghInstance, "BLACK");
GetObject(hBitmap, sizeof(BM), &BM);
hCompatDC = CreateCompatibleDC(PaintDC);
// Select bitmap into the compataible DC
hOldBitmap = SelectBitmap(hCompatDC, hBitmap);
// Display bitmap in client area
StretchBlt(PaintDC, rBlackScoreBmp.left, rBlackScoreBmp.top,
rBlackScoreBmp.right-rBlackScoreBmp.left,
rBlackScoreBmp.bottom-rBlackScoreBmp.top,
hCompatDC, 0, 0, BM.bmWidth, BM.bmHeight,
SRCCOPY);
// De-select the bitmap
SelectBitmap(hCompatDC, hOldBitmap);
// Clean up after we are done
DeleteDC(hCompatDC);
DeleteBitmap(hBitmap);
}
if (Player == 1)
DrawText(PaintDC,"White's Turn ",14,&rMessage,DT_SINGLELINE | DT_BOTTOM | DT_LEFT);
else
DrawText(PaintDC,"Black's Turn ",14,&rMessage,DT_SINGLELINE | DT_BOTTOM | DT_LEFT);
DrawSquare(PaintDC,rWhiteScore,-1);
DrawSquare(PaintDC,rBlackScore,-1);
SetBkMode(PaintDC,TRANSPARENT);
itoa(Board.nWhiteScore,cszWhite,10);
DrawText(PaintDC,cszWhite,strlen(cszWhite),
&rWhiteScore,DT_SINGLELINE | DT_BOTTOM | DT_CENTER);
itoa(Board.nBlackScore,cszBlack,10);
DrawText(PaintDC,cszBlack,strlen(cszBlack),
&rBlackScore,DT_SINGLELINE | DT_BOTTOM | DT_CENTER);
SetBkMode(PaintDC,OPAQUE);
DeletePen(hWhitePen);
DeletePen(hGrayPen);
}
void TMainWindow::WMTimer(RTMessage)
{
if ( (Player == 1 && Player1 == 2) || (Player == 2 && Player2 == 2) )
{
SetCursor(LoadCursor(NULL,IDC_WAIT));
Board.GoComputer(Player,1);
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
}
#pragma argsused
long double TBoard::GoComputer(int Player, int Level)
{
int nCol, nRow;
int nOther,nVect,j,k,nVectCnt;
long double MoveVal, MoveCnt, nOldMult, MaxVal=-100000000;
BOOL ValMove=FALSE;
TUndo SaveBoard,MoveBoard;
POINT MaxMove;
Board2Undo(Board,SaveBoard);
nOther = (Player==1) ? 2 : 1;
nOldMult = 0;
j=0;
do
{
if ( Weight[j].Mult==0 ) { j++; continue; }
if ( MaxVal > 10*Weight[j].Mult
&& ValMove==TRUE && nOldMult != Weight[j].Mult )
break;
nOldMult = Weight[j].Mult;
do
{
nCol = Weight[j].x;
nRow = Weight[j].y;
if ( BoardArr[nCol][nRow] == 0 )
{
MoveCnt = 0;
MoveVal = 0;
for ( nVect=0;nVect<8;nVect++ )
{
nVectCnt = ChkVector(NULL,nCol,nRow,nVect,nOther,Player,TRUE);
MoveCnt += (nVectCnt > 0) ? nVectCnt : 0 ;
}
if ( MoveCnt > 0 )
{
MoveVal = MoveCnt*Weight[j].Mult;
//MoveVal = powl(MoveVal,Weight[j].Mult);
BoardArr[nCol][nRow] = Player;
if (Level < Difficulty*2-2 )
MoveVal -= GoComputer(nOther,Level+1);
if ( MoveVal > MaxVal || (MoveVal == MaxVal && random(10) > 4 ))
{
MaxVal = MoveVal;
MaxMove.x = nCol; MaxMove.y = nRow;
ValMove=TRUE;
}
}
}
Undo2Board(SaveBoard,Board);
j++;
} while (j<BoardSize*BoardSize && nOldMult == Weight[j].Mult);
} while (j<BoardSize*BoardSize);
//See if the computer could move...
if ( ValMove == FALSE )
{
MaxVal = 0;
Player = nOther;
bFlip = FALSE;
}
else
if (Level == 1)
{
BoardArr[MaxMove.x][MaxMove.y] = Player;
LastMove.x = MaxMove.x ; LastMove.y = MaxMove.y;
bFlip = TRUE;
nPass = 0;
InvalidateRect(ghWindow,NULL,FALSE);
}
return MaxVal;
}
void Board2Undo( TBoard& b, TUndo& u)
{
int i,j;
memcpy(u.UndoArr,b.BoardArr,sizeof(b.BoardArr));
u.UndoPlayer = Player;
u.nUndoPass = nPass;
u.nUndoWhiteScore = b.nWhiteScore;
u.nUndoBlackScore = b.nBlackScore;
u.UndoLastMove.x = LastMove.x;
u.UndoLastMove.y = LastMove.y;
}
void Undo2Board( TUndo& u, TBoard& b)
{
int i,j;
memcpy(b.BoardArr,u.UndoArr,sizeof(b.BoardArr));
Player = u.UndoPlayer;
nPass = u.nUndoPass;
b.nWhiteScore = u.nUndoWhiteScore;
b.nBlackScore = u.nUndoBlackScore;
LastMove.x = u.UndoLastMove.x;
LastMove.y = u.UndoLastMove.y;
}
istream& operator >> ( istream& is, TBoard& bd )
{
int i,j;
for (i=0;i<12;i++)
for (j=0;j<12;j++)
is >> bd.BoardArr[i][j];
is >> bd.bFlip;
for (i=0;i<8;i++)
is >> bd.Vectors[i];
for (j=0;j<100;j++)
{
is >> bd.Weight[j].Mult;
is >> bd.Weight[j].x;
is >> bd.Weight[j].y;
}
is >> bd.nWhiteScore;
is >> bd.nBlackScore;
return is;
}
ostream& operator << ( ostream& os, TBoard& bd )
{
int i,j;
for (i=0;i<12;i++)
for (j=0;j<12;j++)
os << bd.BoardArr[i][j];
os << bd.bFlip;
os << ' ';
for (i=0;i<8;i++)
os << bd.Vectors[i];
for (j=0;j<100;j++)
{
os << bd.Weight[j].Mult << ' ';
os << bd.Weight[j].x << ' ';
os << bd.Weight[j].y << ' ';
}
os << bd.nWhiteScore;
os << ' ';
os << bd.nBlackScore;
os << ' ';
return os;
}
istream& operator >> ( istream& is, TUndo& u )
{
int i,j;
for (i=0;i<12;i++)
for (j=0;j<12;j++)
is >> u.UndoArr[i][j];
is >> u.UndoPlayer;
is >> u.nUndoPass;
is >> u.nUndoWhiteScore;
is >> u.nUndoBlackScore;
is >> u.UndoLastMove;
return is;
}
ostream& operator << ( ostream& os, TUndo& u )
{
int i,j;
for (i=0;i<12;i++)
for (j=0;j<12;j++)
os << u.UndoArr[i][j];
os << u.UndoPlayer;
os << ' ';
os << u.nUndoPass;
os << ' ';
os << u.nUndoWhiteScore;
os << ' ';
os << u.nUndoBlackScore;
os << ' ';
os << u.UndoLastMove;
return os;
}
istream& operator >> ( istream& is, POINT& pt )
{
int x,y;
is >> x;
is >> y;
pt.x = x;
pt.y = y;
return is;
}
ostream& operator << ( ostream& os, POINT& pt )
{
int x,y;
x = pt.x;
y = pt.y;
os << x;
os << ' ';
os << y;
os << ' ';
return os;
}
int TMainWindow::WMSetFocus(RTMessage)
{
KillTimer(ghWindow,10);
SetTimer(ghWindow,10,1500,NULL);
bReFresh=TRUE;
return 0;
}
int TMainWindow::WMKillFocus(RTMessage Msg)
{
WMInitMenu(Msg);
return 0;
}
void TMainWindow::WMInitMenu(RTMessage)
{
KillTimer(ghWindow,10);
}
int TMainWindow::WMMenuSelect(RTMessage Msg)
{
if (Msg.LP.Hi == 0)
WMSetFocus(Msg);
return 0;
}
void TMainWindow::OpenFiFile( LPSTR lpstrFile )
{
ifstream in( lpstrFile ); // open the input file
in >> Board; // read the Todo list
in >> Undo;
in >> Player;
in >> Player1;
in >> Player2;
in >> nPass;
in >> NumPlayers;
in >> BoardSize;
in >> LastMove;
in >> Difficulty;
in.close();
}
void TMainWindow::SaveFiFile( LPSTR lpstrFile )
{
ofstream out( lpstrFile );
out << Board;
out << Undo;
out << Player << ' ';
out << Player1 << ' ';
out << Player2 << ' ';
out << nPass << ' ';
out << NumPlayers << ' ';
out << BoardSize << ' ';
out << LastMove;
out << Difficulty;
out.close();
}
//REGEN_CUSTOMCODE