home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
PMCSR102.ZIP
/
PMCHESS.C
< prev
next >
Wrap
Text File
|
1990-12-17
|
23KB
|
809 lines
//
// Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
// Copyright (c) 1988, 1989, 1990 John Stanback
//
// Project: OS/2 PM Port of GNU CHESS 3.1 (PmChess)
//
// Version: 1.02 1990-12-17
//
// Module: Main Module (PmChess.c)
//
// Porter: Ported to Windows 3.0 by Darly Baker
//
// Porter: Ported to OS/2 1.2+ by Kent Cedola
//
// Update: Fixes and enhancements by Benny N. Ormson
//
// System: OS2 1.2 using Microsoft C 6.0
//
// Remarks: For the most part the port to OS/2 PM was a hard port with
// very little cleaning up of the old code. Sections with the
// double slash '//' is my doing.
//
// License:
//
// CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY. No author or distributor accepts responsibility to anyone for
// the consequences of using it or for whether it serves any particular
// purpose or works at all, unless he says so in writing. Refer to the
// CHESS General Public License for full details.
//
// Everyone is granted permission to copy, modify and redistribute CHESS,
// but only under the conditions described in the CHESS General Public
// License. A copy of this license is supposed to have been given to you
// along with CHESS so you can know your rights and responsibilities. It
// should be in a file named COPYING. Among other things, the copyright
// notice and this notice must be preserved on all copies.
//
#define INCL_DOS
#define INCL_GPI
#define INCL_WIN
#include <os2.h>
#include <string.h>
#include <time.h>
#include "PmChess.h"
#include "GnuChess.h"
#include "Defs.h"
#include "Resource.h"
//
// Define global variables.
//
HAB hab; // Primary thread anchor block.
HMQ hmq; // Message queue handle.
HWND hwndFrame; // Frame window handle.
HWND hwndClient; // Client window handle.
HPS hpsClient;
HWND hwndMenu; // Menu window handle.
short cyClient; // Height of client area.
char szAppName[] = "PmChess"; // Application name.
short boarddraw[64]; /* Display copies of the board */
short colordraw[64]; /* Needed because while computer is calculating*/
/* moves it updates board and color thus you can*/
/* not repaint the screen accuratly */
ULONG clrBackGround; /* color index for various colors */
ULONG clrBlackSquare;
ULONG clrWhiteSquare;
ULONG clrBlackPiece;
ULONG clrWhitePiece;
ULONG clrText;
short xchar, ychar;
short coords = 1;
//
// Define local variables.
//
static BOOL FirstSq = -1; // Flag is a square is selected
static int GotFirst = FALSE;
static int EditActive = FALSE; /* Edit mode? */
int User_Move = TRUE; /* User or computer's turn */
static char szClass[] = "PmChess"; // Class name of main window procedure.
static HPS hpsPieces; // Memory PS of all chess pieces.
//
// Define prototypes of local routines.
//
void cdecl main(short argc, char **argv);
MRESULT EXPENTRY ChessProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
static void WndCreate(HWND hWnd);
static void WndPaint(HWND hWnd);
static void WndButton(HWND hWnd, USHORT msg, MPARAM mp1);
static void WndDestroy(void);
MRESULT EXPENTRY AboutProc(HWND hDlg, USHORT msg, MPARAM mp1, MPARAM mp2);
//***************************************************************************
//
// Routine: main(In, In)
//
// Remarks: This routine is then entry-point called by the OS/2 executive.
//
// Returns: None.
//
void cdecl main(short argc, char **argv)
{
QMSG qmsg;
ULONG ctlData;
POINTL ptl;
//
// Allocate an anchor block and message queue to use PM services.
//
hab = WinInitialize(0);
hmq = WinCreateMsgQueue(hab, 0);
//
// Register the main window procedure.
//
if (!WinRegisterClass(NULL, szClass, ChessProc, CS_SIZEREDRAW, 0))
{
//
// This should never happen...
//
WinMessageBox(HWND_DESKTOP, NULL, "Register Class Failure", szAppName, 0,
MB_OK);
goto Error;
}
//
// Compute the idea client height.
//
QueryBoardSize(&ptl);
cyClient = (SHORT)(ptl.y + WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER)
* 2L+ WinQuerySysValue(HWND_DESKTOP, SV_CYMENU)+
WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR) +
(LONG)ychar * 2L);
//
// Define the control fields for creating a standard frame window.
//
ctlData = FCF_TITLEBAR | FCF_MINMAX | FCF_SIZEBORDER | FCF_SYSMENU |
FCF_MENU | FCF_TASKLIST | FCF_SHELLPOSITION | FCF_ICON |
FCF_PALETTE_NORMAL;
//
// Create our main frame window that makes us who we are.
//
hwndFrame = WinCreateStdWindow(HWND_DESKTOP,0,&ctlData, /* Ormson */
szClass, NULL, WS_VISIBLE, 0, IDR_PMCHESS, &hwndClient);
//
// Make sure the frame window creation was successful.
//
if (hwndFrame == NULL)
{
//
// This should almost never happen...
//
WinMessageBox(HWND_DESKTOP, NULL, "Window Create Failure", szAppName, 0,
MB_OK);
goto Error;
}
//
// Retrieve the menu handle to speed up future processing.
//
hwndMenu = WinWindowFromID(hwndFrame, FID_MENU);
//
// Size the frame window to our standard size.
//
QueryBoardSize(&ptl);
WinSetWindowPos(hwndFrame, NULL, 0, 0, /* Ormson 12/17/90 */
(SHORT)(ptl.x+WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER)*2L+90L),
(SHORT)(ptl.y+WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER)*2+
WinQuerySysValue(HWND_DESKTOP, SV_CYMENU)+
WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR) + (LONG)ychar * 3L),
SWP_SIZE | SWP_SHOW); /* Ormson 12/17/90 */
//
// Initialize the GNU Chess Logic...
//
init_main(hwndFrame);
player = opponent;
ShowSidetoMove();
//
// The heart of an event driven system, the message dispatch loop.
//
while (WinGetMsg(hab, &qmsg, NULL, 0, 0))
WinDispatchMsg(hab, &qmsg);
//
// Release the anchor block and message queue as we are terminating.
//
Error:
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
DosExit(EXIT_PROCESS, 0);
}
//***************************************************************************
//
// WndProc: ChessProc(In, In, In, In)
//
// Remarks: This routine is then entry-point called by the OS/2 executive.
//
// Returns: Depends on message processed.
//
MRESULT EXPENTRY ChessProc(HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2)
{
HWND hwndOldMenu;
CHAR szBuf[64];
SWP far *swp;
switch (msg)
{
case WM_CREATE:
WndCreate(hWnd);
return (0);
case WM_DESTROY:
WndDestroy();
break;
case WM_PAINT:
WndPaint(hWnd);
break;
case WM_MINMAXFRAME: /* Ormson 12/10/90 */
swp = PVOIDFROMMP(mp1);
if(swp->fs & SWP_MAXIMIZE || swp->fs & SWP_RESTORE)
DosSetPrty(PRTYS_PROCESSTREE,PRTYC_REGULAR,0,0);
else if(swp->fs & SWP_MINIMIZE)
DosSetPrty(PRTYS_PROCESSTREE,PRTYC_IDLETIME,0,0);
break;
case WM_ERASEBACKGROUND:
WinFillRect(PVOIDFROMMP(mp1), PVOIDFROMMP(mp2), clrBackGround);
break;
case WM_SIZE:
cyClient = SHORT2FROMMP(mp2);
break;
case WM_BUTTON1DOWN:
WndButton(hWnd, msg, mp1);
break;
case WM_INITMENU:
if ( User_Move ) { /*Abort thinklook ahead*/
flag.timeout = true;
flag.bothsides = false;
}
if (!EditActive)
Init_Menus(hWnd, mp1, mp2);
break;
case WM_COMMAND:
switch (SHORT1FROMMP(mp1))
{
case IDM_FILE_NEW:
NewGame(hWnd);
User_Move = TRUE; /* Ormson 12/13/90 */
player = opponent; /* Ormson 12/13/90 */
ShowSidetoMove (); /* Ormson 12/13/90 */
GetOpenings(hWnd);
break;
case IDM_FILE_OPEN:
GetGame(hWnd); /* Ormson 12/16/90 */
break;
case IDM_FILE_SAVE:
SaveGame(hWnd,0); /* Ormson 12/16/90 */
break;
case IDM_FILE_SAVEAS:
SaveGame(hWnd,1); /* Ormson 12/16/90 */
break;
case IDM_FILE_LIST:
ListGame(hWnd,"pmchess.lst"); /* Ormson 12/14/90 */
break;
case IDM_FILE_EXIT:
SaveColors(szAppName); /* Ormson 12/11/90 */
SaveOptions(); /* Ormson 12/11/90 */
WinPostMsg(NULL,WM_QUIT,0L,0L); /* Ormson 12/08/90 */
break;
case IDM_EDIT_BOARD:
EditActive = TRUE;
hwndOldMenu = WinWindowFromID(hwndFrame, FID_MENU);
WinLoadMenu(hwndFrame, 0, IDR_EDIT);
WinSendMsg(hwndFrame, WM_UPDATEFRAME, NULL, NULL);
WinDestroyWindow(hwndOldMenu);
break;
case IDM_EDIT_DONE:
EditActive = FALSE;
hwndOldMenu = WinWindowFromID(hwndFrame, FID_MENU);
WinLoadMenu(hwndFrame, 0, IDR_PMCHESS);
WinSendMsg(hwndFrame, WM_UPDATEFRAME, NULL, NULL);
WinDestroyWindow(hwndOldMenu);
GameCnt = 0;
Game50 = 1;
ZeroRPT ();
Sdepth = 0;
InitializeStats();
WinPostMsg(hWnd, UM_USER_MOVE, NULL, NULL);
break;
case IDM_EDIT_GAME:
//ReviewDialog(hWnd);
break;
case IDM_EDIT_UNDO:
if (GameCnt > 0)
Undo(hWnd);
break;
case IDM_EDIT_REMOVE:
if (GameCnt > 1)
{
Undo(hWnd);
Undo(hWnd);
}
break;
case IDM_EDIT_FORCE:
computer = opponent;
opponent = otherside[computer];
ShowPlayers();
WinPostMsg(hWnd, UM_COMPUTER_MOVE, NULL, NULL);
break;
case IDM_OPTIONS_TONE:
flag.beep = !flag.beep;
break;
case IDM_OPTIONS_COOR:
coords = !coords;
UpdateDisplay(hWnd, 0, 0, 1, 0);
break;
case IDM_OPTIONS_STATS:
if (flag.post)
{
WinSendMsg(hStats, WM_SYSCOMMAND, MPFROMSHORT(SC_CLOSE), NULL);
flag.post = false;
}
else
{
StatDialog(hWnd);
flag.post = TRUE;
}
break;
case IDM_OPTIONS_SPEED:
TestDialog(hWnd);
break;
case IDM_OPTIONS_HASH:
flag.hash = !flag.hash;
break;
case IDM_OPTIONS_BOTH:
flag.bothsides = !flag.bothsides;
flag.easy = true;
Sdepth = 0;
WinPostMsg(hWnd, UM_USER_MOVE, NULL, NULL);
break;
case IDM_OPTIONS_BOOK:
Book = NULL;
break;
case IDM_OPTIONS_AWINDOW:
WinLoadString(hab, 0, IDS_SETAWIN, sizeof(szBuf), szBuf);
Awindow = DoGetNumberDlg(hWnd, szBuf, Awindow);
break;
case IDM_OPTIONS_BWINDOW:
WinLoadString(hab, 0, IDS_SETBWIN, sizeof(szBuf), szBuf);
Bwindow = DoGetNumberDlg(hWnd, szBuf, Bwindow);
break;
case IDM_OPTIONS_CONTEMP:
WinLoadString(hab, 0, IDS_SETCONTEMPT, sizeof(szBuf), szBuf);
contempt = DoGetNumberDlg(hWnd, szBuf, contempt);
break;
case IDM_SKILL_TIME:
if (TimeControlDialog(hWnd))
{
TCflag = (TCmoves > 1);
SetTimeControl();
}
break;
case IDM_SKILL_RANDOM:
if (dither == 0)
dither = 6;
else
dither = 0;
break;
case IDM_SKILL_EASY:
flag.easy = !flag.easy;
break;
case IDM_SKILL_DEPTH:
WinLoadString(hab, 0, IDS_MAXSEARCH, sizeof(szBuf), szBuf);
MaxSearchDepth = DoGetNumberDlg(hWnd, szBuf, MaxSearchDepth);
break;
case IDM_SIDE_REVERSE:
flag.reverse = !flag.reverse;
ShowPlayers();
UpdateDisplay(hWnd, 0, 0, 1, 0);
break;
case IDM_SIDE_SWITCH:
computer = otherside[computer];
opponent = otherside[opponent];
flag.force = false;
Sdepth = 0;
ShowPlayers();
WinPostMsg(hWnd, UM_COMPUTER_MOVE, NULL, NULL);
break;
case IDM_SIDE_BLACK:
computer = black;
opponent = white;
flag.force = false;
Sdepth = 0;
ShowPlayers();
WinPostMsg(hWnd, UM_COMPUTER_MOVE, NULL, NULL);
break;
case IDM_SIDE_WHITE:
computer = white;
opponent = black;
flag.force = false;
Sdepth = 0;
ShowPlayers();
WinPostMsg(hWnd, UM_COMPUTER_MOVE, NULL, NULL);
break;
case IDM_COLORS_BACKGROUND:
case IDM_COLORS_BSQUARES:
case IDM_COLORS_WSQUARES:
case IDM_COLORS_BPIECES:
case IDM_COLORS_WPIECES:
case IDM_COLORS_TEXT:
if (ColorDialog(hWnd, (LONG)(SHORT1FROMMP(mp1))))
WinInvalidateRect(hWnd, NULL, TRUE);
break;
case IDM_COLORS_DEFAULT:
SetStandardColors ();
WinInvalidateRect(hWnd, NULL, TRUE);
break;
case IDM_HINT:
GiveHint(hWnd);
break;
case IDM_HELP_ABOUT:
WinDlgBox(HWND_DESKTOP, hWnd, AboutProc, 0, IDD_ABOUT, NULL);
break;
}
return (0);
case UM_EDITBOARD:
{
int Square, First;
if ( flag.reverse ) {
First = 63 - ((SHORT1FROMMP(mp1) >> 8) & 0xff);
Square = 63 - (SHORT1FROMMP(mp1) & 0xff);
} else {
First = (SHORT1FROMMP(mp1) >>8) & 0xff;
Square = SHORT1FROMMP(mp1) & 0xff;
}
board[Square] = board[First];
color[Square] = color[First];
board[First] = no_piece;
color[First] = neutral;
UpdateDisplay(hWnd, First, Square, false, false);
}
break;
case UM_USER_MOVE:
if ( flag.bothsides && !flag.mate ) {
SelectMove ( hWnd, opponent, 1);
if ( flag.beep ) WinAlarm(HWND_DESKTOP, WA_NOTE);
WinPostMsg( hWnd, UM_COMPUTER_MOVE, NULL, NULL);
} else if (!flag.mate) {
User_Move = TRUE;
ft = 0;
player = opponent;
ShowSidetoMove ();
{
/* Set up to allow computer to think while user takes move*/
int tmp; unsigned short mv; char s[10];
if ( hint>0 && !flag.easy && Book == NULL) {
time0 = time ( NULL);
algbr ( hint>>8, hint&0xff, false);
strcpy ( s, mvstr[0]);
tmp = epsquare;
if ( VerifyMove (hWnd, s,1, &mv) ) {
SelectMove ( hWnd, computer, 2);
VerifyMove ( hWnd, mvstr[0], 2, &mv);
if ( Sdepth>0 ) Sdepth --;
}
ft = time (NULL) - time0;
epsquare = tmp;
}
}
}
break;
case UM_USER_ENTERED_MOVE:
{
int temp; unsigned short mv; int Square,First; char str[10];
int algbr_flag;
User_Move = FALSE;
player = opponent;
/* Fix coord's if user "reversed" board */
if ( flag.reverse ) {
First = 63 - ((SHORT1FROMMP(mp1) >>8) & 0xff);
Square = 63 - (SHORT1FROMMP(mp1) & 0xff);
} else {
First = (SHORT1FROMMP(mp1) >>8) & 0xff;
Square = SHORT1FROMMP(mp1) & 0xff;
}
/* Logic to allow selection for pawn promotion */
if ( (board[First] == pawn) &&( (Square <8) || (Square>55)) ) {
algbr_flag = promote + PromoteDialog (hWnd);
} else algbr_flag = 0;
algbr ( First, Square, algbr_flag);
strcpy ( str, mvstr[0] );
temp = VerifyMove ( hWnd, str, 0, &mv);
if ( temp && (mv != hint)) {
Sdepth = 0;
ft = 0;
ElapsedTime (1);
WinPostMsg( hWnd, UM_COMPUTER_MOVE, NULL, NULL);
} else if ( temp == TRUE) {
ElapsedTime (1);
WinPostMsg ( hWnd, UM_COMPUTER_MOVE, NULL, NULL);
} else WinPostMsg ( hWnd, UM_USER_MOVE, NULL, NULL);
}
break;
case UM_COMPUTER_MOVE:
if ( !(flag.quit || flag.mate || flag.force) ) {
SelectMove ( hWnd, computer, 1);
if ( flag.beep ) WinAlarm(HWND_DESKTOP, WA_NOTE);
}
WinPostMsg( hWnd, UM_USER_MOVE, NULL, NULL);
break;
}
return (WinDefWindowProc(hWnd, msg, mp1, mp2));
}
//***************************************************************************
//
// Routine: WndCreate(In):Static
//
// Remarks: This routine processed the WM_CREATE message from the main
// client window.
//
// Returns: None.
//
static void WndCreate(HWND hWnd)
{
FONTMETRICS fm;
hpsClient = WinGetPS(hWnd);
//
// Load all the chess piece's bitmaps into a master memory ps for later.
//
hpsPieces = LoadChessPieces(hab);
//
// Load the diamensions of the default system font.
//
GpiQueryFontMetrics(hpsClient, sizeof(fm), &fm);
xchar = (SHORT)fm.lEmInc;
ychar = (SHORT)fm.lMaxBaselineExt+(SHORT)fm.lExternalLeading;
Create_Children(hWnd, xchar, ychar);
GetStartupColors(szAppName);
GetOptions();
}
//***************************************************************************
//
// Routine: WndDestroy():Static
//
// Remarks: This routine processed the WM_DESTROY message from the main
// client window.
//
// Returns: None.
//
static void WndDestroy()
{
//
// Save the current color settings for the next time.
//
SaveColors(szAppName);
WinReleasePS(hpsClient);
}
//***************************************************************************
//
// Routine: WndPaint(In):Static
//
// Remarks: This routine processed the WM_PAINT message from the main client
// client window.
//
// Returns: None.
//
static void WndPaint(HWND hWnd)
{
HPS hps;
RECTL rcl;
//
// Remember to properly repaint hi-lighted square.
//
if (FirstSq != -1)
{
POINTL ptl;
RECTL rcl;
QuerySqOrigin(FirstSq % 8, FirstSq / 8, &ptl);
rcl.xLeft = ptl.x;
rcl.xRight = ptl.x + 48;
rcl.yTop = ptl.y;
rcl.yBottom = ptl.y - 48;
WinInvalidateRect(hWnd, &rcl, FALSE);
}
//
// Retrieve the presentation space for drawing.
//
hps = WinBeginPaint(hWnd, NULL, &rcl);
//
// Clear the background.
//
WinFillRect(hps, &rcl, clrBackGround);
//
// Draw the chess board.
//
Draw_Board(hps, flag.reverse, clrBlackSquare, clrWhiteSquare);
//
// Draw the coordinates if that option has been selected by the user.
//
if (coords)
DrawCoords(hps, flag.reverse, clrBackGround, clrText);
//
// Draw in the pieces.
//
DrawAllPieces(hps, hpsPieces, flag.reverse, boarddraw, colordraw,
clrBlackPiece, clrWhitePiece);
//
// All done with painting the client area.
//
WinEndPaint(hps);
//
// If we have a selected square then hi-lighted it.
//
if (FirstSq != -1)
HiliteSquare(hWnd, FirstSq);
}
//***************************************************************************
//
// Routine: WndButton(In):Static
//
// Remarks: This routine processed the various mouse button message from the
// main client window.
//
// Returns: None.
//
static void WndButton(HWND hWnd, USHORT msg, MPARAM mp1)
{
POINTL ptl;
short Hit;
short x, y;
switch (msg)
{
case WM_BUTTON1DOWN:
/* If computer is thinking on human's time stop it at the first
button click. add test to ensure that "human" can't interupt
the computer from thinking through its turn. */
if (User_Move)
{
flag.timeout = true;
flag.bothsides = false;
}
/* Don't continue unless reason to */
if (!(EditActive || User_Move))
break;
ptl.x = SHORT1FROMMP(mp1);
ptl.y = SHORT2FROMMP(mp1);
CkdQueryHitCoords(hpsClient, &ptl, &x, &y);
if (x != -1 && y != -1)
Hit = y * 8 + x;
else
Hit = -1;
if ( Hit == -1 ){
if ( FirstSq != -1) {
UnHiliteSquare ( hWnd, FirstSq);
GotFirst = FALSE;
FirstSq = -1;
}
break;
}
if ( GotFirst ) {
UnHiliteSquare( hWnd, FirstSq);
GotFirst = FALSE;
if ( EditActive == TRUE) {
WinPostMsg(hWnd, UM_EDITBOARD, MPFROMSHORT((FirstSq<<8)|Hit), NULL);
} else if (User_Move == TRUE) {
WinPostMsg(hWnd, UM_USER_ENTERED_MOVE, MPFROMSHORT((FirstSq<<8)|Hit), NULL);
}
FirstSq = -1;
} else {
GotFirst = TRUE;
FirstSq = Hit;
HiliteSquare ( hWnd, Hit);
}
break;
}
}
MRESULT EXPENTRY AboutProc(HWND hDlg, USHORT msg, MPARAM mp1, MPARAM mp2)
{
switch (msg)
{
case WM_COMMAND:
switch (SHORT1FROMMP(mp1))
{
case IDC_OK:
WinDismissDlg(hDlg, TRUE);
break;
}
return (0);
}
return (WinDefDlgProc(hDlg, msg, mp1, mp2));
}