home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cset21v1.zip
/
IBMCPP
/
WKFRAME
/
MAHJONGG
/
MAHJONGG.C
< prev
next >
Wrap
Text File
|
1993-02-28
|
66KB
|
1,517 lines
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ │*/
/*│ PROGRAM NAME: MAHJONGG │*/
/*│ ------------- │*/
/*│ A PM version of a Chinese game similar to 'concentration' but without │*/
/*│ the background puzzle. │*/
/*│ │*/
/*│ COPYRIGHT: │*/
/*│ ---------- │*/
/*│ Copyright (C) International Business Machines Corp., 1991,1992,1993. │*/
/*│ │*/
/*│ DISCLAIMER OF WARRANTIES: │*/
/*│ ------------------------- │*/
/*│ The following [enclosed] code is sample code created by IBM Corporation.│*/
/*│ This sample code is not part of any standard IBM product and is provided│*/
/*│ to you solely for the purpose of assisting you in the development of │*/
/*│ your applications. The code is provided "AS IS", without warranty of │*/
/*│ any kind. IBM shall not be liable for any damages arising out of your │*/
/*│ use of the sample code, even if they have been advised of the │*/
/*│ possibility of such damages. │*/
/*│ │*/
/*│ REVISION LEVEL: 1.0 │*/
/*│ --------------- │*/
/*│ │*/
/*│ WHAT THIS PROGRAM DOES: │*/
/*│ ----------------------- │*/
/*│ This program displays a board with 144 tiles on it. Each tile has a │*/
/*│ symbol on it that must be matched with another tile with either the │*/
/*│ same symbol in most cases or with a similar symbol in other cases. │*/
/*│ │*/
/*│ WHAT THIS PROGRAM DEMONSTRATES: │*/
/*│ ------------------------------- │*/
/*│ This program demonstrates how to create, display and manipulate windows │*/
/*│ in order to perform the necessary actions needed to run the game. │*/
/*│ │*/
/*│ WHAT YOU NEED TO COMPILE THIS PROGRAM: │*/
/*│ -------------------------------------- │*/
/*│ │*/
/*│ REQUIRED FILES: │*/
/*│ --------------- │*/
/*│ │*/
/*│ MAHJONGG C - main source including the main window procedure │*/
/*│ MAHJONGG H - Mahjongg header file │*/
/*│ TILE C - source for tile window procedure & related functions │*/
/*│ MAHJONGG RC - resource file for Mahjongg │*/
/*│ MAHJONGG DEF - definition file for Mahjongg │*/
/*│ MAHJONGG ICO - icon file for Mahjongg │*/
/*│ MAHJONGG IPF - documentation file for Mahjongg │*/
/*│ MAHJONGG MAK - make file for Mahjongg generated by utility │*/
/*│ MAHJONGG DEP - dependancy for Mahjongg generated by utility │*/
/*│ MAKEFILE - make file for Mahjongg (hand written) │*/
/*│ TILE_B_1 BMP ┐ │*/
/*│ TILE_B_2 BMP │ │*/
/*│ TILE_B_3 BMP │ │*/
/*│ TILE_B_4 BMP │ │*/
/*│ TILE_B_5 BMP ├ Bamboo suit bitmaps for tiles │*/
/*│ TILE_B_6 BMP │ │*/
/*│ TILE_B_7 BMP │ │*/
/*│ TILE_B_8 BMP │ │*/
/*│ TILE_B_9 BMP ┘ │*/
/*│ TILE_C_1 BMP ┐ │*/
/*│ TILE_C_2 BMP │ │*/
/*│ TILE_C_3 BMP │ │*/
/*│ TILE_C_4 BMP │ │*/
/*│ TILE_C_5 BMP ├ Character suit bitmaps for tiles │*/
/*│ TILE_C_6 BMP │ │*/
/*│ TILE_C_7 BMP │ │*/
/*│ TILE_C_8 BMP │ │*/
/*│ TILE_C_9 BMP ┘ │*/
/*│ TILE_D_1 BMP ┐ │*/
/*│ TILE_D_2 BMP │ │*/
/*│ TILE_D_3 BMP │ │*/
/*│ TILE_D_4 BMP │ │*/
/*│ TILE_D_5 BMP ├ Dots suit bitmaps for tiles │*/
/*│ TILE_D_6 BMP │ │*/
/*│ TILE_D_7 BMP │ │*/
/*│ TILE_D_8 BMP │ │*/
/*│ TILE_D_9 BMP ┘ │*/
/*│ TILE_F_1 BMP ┐ │*/
/*│ TILE_F_2 BMP ├ Flowers suit bitmaps for tiles │*/
/*│ TILE_F_3 BMP │ │*/
/*│ TILE_F_4 BMP ┘ │*/
/*│ TILE_R_1 BMP ┐ │*/
/*│ TILE_R_2 BMP ├ Dragons suit bitmaps for tiles │*/
/*│ TILE_R_3 BMP ┘ │*/
/*│ TILE_S_1 BMP ┐ │*/
/*│ TILE_S_2 BMP ├ Seasons suit bitmaps for tiles │*/
/*│ TILE_S_3 BMP │ │*/
/*│ TILE_S_4 BMP ┘ │*/
/*│ TILE_W_E BMP ┐ │*/
/*│ TILE_W_N BMP ├ Winds suit bitmaps for tiles │*/
/*│ TILE_W_S BMP │ │*/
/*│ TILE_W_W BMP ┘ │*/
/*│ TILE_N_0 BMP ┐ │*/
/*│ TILE_N_1 BMP │ │*/
/*│ TILE_N_2 BMP │ │*/
/*│ TILE_N_3 BMP │ │*/
/*│ TILE_N_4 BMP │ │*/
/*│ TILE_N_5 BMP ├ Number bitmaps for tiles │*/
/*│ TILE_N_6 BMP │ │*/
/*│ TILE_N_7 BMP │ │*/
/*│ TILE_N_8 BMP │ │*/
/*│ TILE_N_9 BMP ┘ │*/
/*│ CONGRAT BMP - congratulations bitmap │*/
/*│ ABOUT BMP - about bitmap │*/
/*│ BACKVGA BMP - background bitmap (VGA, 16 color) │*/
/*│ BACKBGA BMP - background bitmap (BGA, 256 color) │*/
/*│ │*/
/*│ REQUIRED LIBRARIES: │*/
/*│ ------------------- │*/
/*│ │*/
/*│ OS2386.LIB - OS/2 API library │*/
/*│ │*/
/*│ REQUIRED PROGRAMS: │*/
/*│ ------------------ │*/
/*│ │*/
/*│ IBM C Set/2 Compiler (icc.exe) │*/
/*│ IBM Linker (link386.exe) │*/
/*│ Resource Compiler (rc.exe) │*/
/*│ │*/
/*│ EXPECTED INPUT: │*/
/*│ --------------- │*/
/*│ │*/
/*│ You can start the program minimized by using the /MIN option. │*/
/*│ │*/
/*│ EXPECTED OUTPUT: │*/
/*│ ---------------- │*/
/*│ │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ MAHJONGG.C │*/
/*│ │*/
/*│ Mahjongg Game main source file │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ local constants │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
#define DEFAULT_BGA_DX 3L
#define DEFAULT_VGA_DX 2L
#define TILE_CX 17
#define TILE_CY 22
#define TILE_BW 2 /* border width */
#define TILE_LD 2 /* level distance */
#define BOARD_FR_CX 5 /* frame arround the board */
#define BOARD_FR_CY 5 /* frame arround the board */
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Includes │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
#define INCL_BASE
#define DEFINE_VARIABLES
#include "mahjongg.h"
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ local variables │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
BOOL bMinAfterStart = FALSE;
SHORT sMaxAdjx = 0L; /* center adjustement for maximized window */
SHORT sMaxAdjy = 0L; /* center adjustement for maximized window */
USHORT idb_back;
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ local help variables │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
HELPINIT hmiHelpData; /* Help initialization structure */
HWND hwndHelpInstance; /* Handle to Help window */
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ local function declarations │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID InitializeDefaultTiles(VOID);
VOID InitializeDefaultGame(VOID);
VOID ExplodeStar(HPS hps,
PPOINTL center,
INT dr,
INT itr,
INT substars
);
#define UNDO_SIZE (NBR_OF_TILES/2)+1
static struct {
INT Tile1;
INT Tile2;
} UndoBuffer[UNDO_SIZE];
static INT UndoTop = 0;
static INT UndoCurrent = 0;
static INT UndoBottom = 0;
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ local macro declarations │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
#define absm(A) ((A) < 0 ? (-(A)) : (A))
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Memory Allocation / Deallocation │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
void *MemAlloc(USHORT size)
{
void *p;
if ((p = malloc(size)) == NULL) {
WinMessageBox(HWND_DESKTOP,
HWND_DESKTOP,
(PSZ)"Error: Could not allocate memory",
(PSZ)Game.pszTitle,
0,
MB_CUAWARNING | MB_OK | MB_MOVEABLE);
} /* endif */
return(p);
}
BOOL MemFree(void *p)
{
if (p) free(p);
return(TRUE);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ local variables for options saving and loading │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
static CHAR szMahjongg[] = {"MAHJONGG"};
static CHAR szSound[] = {"Sound"};
static CHAR szX[] = {"X"};
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Save Options into the OS2INI file │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
static VOID SaveOptions(VOID)
{
CHAR szText[64];
sprintf(szText, "%d", bSound);
PrfWriteProfileString(hab, szMahjongg, szSound, szText);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Load Options from the OS2INI file │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
static VOID LoadOptions(VOID)
{
CHAR szText[64];
PrfQueryProfileString(hab, szMahjongg, szSound, szX, szText, sizeof(szText));
if (szText[0] != szX[0]) bSound = atoi(szText);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ main │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
main(int argc, char *argv[])
{
HMQ hmq = NULLH;
QMSG qmsg;
ULONG ctlData;
SHORT i;
SWP swp;
CHAR szTemp[256];
INT rc = 0;
if (!(hab=WinInitialize(0))) return(1);
if (!(hmq=WinCreateMsgQueue(hab, 1000))) return(2);
/* parse arguments */
for (i=1; i<argc; i++) {
if (strncmp(strupr(argv[i]), "/MIN", 4) == 0)
bMinAfterStart = TRUE;
} /* endfor */
/* intialize strings */
for (i=IDS_FIRST_STRING; i<=IDS_LAST_STRING; i++) {
WinLoadString(hab, 0, i, sizeof(szTemp), (PSZ)szTemp);
if (pszStringTab[i] = MemAlloc(strlen(szTemp)+1)) {
strcpy(pszStringTab[i], szTemp);
} else {
/* ??? not enough memory */
} /* endif */
} /* endfor */
if (!WinRegisterClass( hab,
pszStringTab[IDS_CLASS_MAHJONGG],
(PFNWP)MainWndProc,
CS_SIZEREDRAW | CS_MOVENOTIFY,
0)) {
rc = 3;
goto MainExit;
} /* endif */
if (!WinRegisterClass( hab,
pszStringTab[IDS_CLASS_TILE],
(PFNWP)TileWndProc,
CS_CLIPSIBLINGS,
0)) {
rc = 4;
goto MainExit;
} /* endif */
InitializeDefaultTiles();
LoadOptions(); /* read the user saved options from the OS2.INI file */
InitializeDefaultGame();
hptrArrow = WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
hptrWait = WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE);
GpiLoadFonts(hab, "C:\\OS2\\DLL\\HELV.FON");
/* IPF Initialization Structure */
hmiHelpData.cb = sizeof(HELPINIT);
hmiHelpData.ulReturnCode = 0;
hmiHelpData.pszTutorialName = NULL;
hmiHelpData.phtHelpTable = (PVOID)(0xffff0000 | IDH_MAIN_TABLE);
/* action bar is not tailored */
hmiHelpData.hmodAccelActionBarModule = 0;
hmiHelpData.idAccelTable = 0;
hmiHelpData.idActionBar = 0;
hmiHelpData.pszHelpWindowTitle = "Mahjongg Help Window";
hmiHelpData.hmodHelpTableModule = 0;
hmiHelpData.fShowPanelId = 0;
hmiHelpData.pszHelpLibraryName = "MAHJONGG.HLP";
/* Create Instance of IPF */
hwndHelpInstance = WinCreateHelpInstance(hab, &hmiHelpData);
if (!hwndHelpInstance) {
WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
(PSZ) "Help Not Available",
(PSZ) "Help Creation Error",
1,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
} else {
if (hmiHelpData.ulReturnCode) {
WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
(PSZ) "Help Terminated Due to Error",
(PSZ) "Help Creation Error",
1,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
WinDestroyHelpInstance(hwndHelpInstance);
} /* endif */
} /* endif */
ctlData = FCF_STANDARD;
hwndFrame = WinCreateStdWindow(HWND_DESKTOP,
FS_STANDARD,
&ctlData,
pszStringTab[IDS_CLASS_MAHJONGG],
(PSZ)NULL,
0L,
NULLH,
ID_WINDOW,
(PHWND)&hwndBoard );
if (!hwndFrame) { rc = 5; goto MainExit; } /* endif */
oldFrameProc = WinSubclassWindow(hwndFrame, FrameSubClass);
swcntrl.hwnd = hwndFrame;
swcntrl.hwndIcon = NULLH;
swcntrl.hprog = NULLH;
swcntrl.idProcess = (USHORT)0;
swcntrl.idSession = (USHORT)0;
swcntrl.uchVisibility = SWL_VISIBLE;
swcntrl.fbJump = SWL_JUMPABLE;
hSwitch = WinAddSwitchEntry((PSWCNTRL)&swcntrl);
WinSetWindowText(hwndFrame, swcntrl.szSwtitle);
// make sure that inital window is inside screen
WinQueryTaskSizePos(hab, 0, &swp);
swp.cx = (SHORT)deltaX * Board.cx
+ 2*(SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER);
swp.cy = (SHORT)deltaX * Board.cy
+ 2*(SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER)
+ (SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR)
+ (SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CYMENU);
if (swp.x+swp.cx > WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN))
swp.x = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)-swp.cx;
if (swp.x < 0) swp.x = 0; // align to left border of screen
if (swp.y < 0) swp.y = 0; // align to top border of screen
if (swp.y+swp.cy > WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN))
swp.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - swp.cy;
if (bMinAfterStart) {
WinSetWindowPos(hwndFrame, HWND_TOP, 0,0,0,0, SWP_MINIMIZE | SWP_SHOW);
WinSetWindowUShort(hwndFrame, QWS_XRESTORE, swp.x);
WinSetWindowUShort(hwndFrame, QWS_YRESTORE, swp.y);
WinSetWindowUShort(hwndFrame, QWS_CXRESTORE, swp.cx);
WinSetWindowUShort(hwndFrame, QWS_CYRESTORE, swp.cy);
} else {
WinSetWindowPos(hwndFrame, HWND_TOP,
swp.x, swp.y, swp.cx, swp.cy,
SWP_SIZE | SWP_ACTIVATE | SWP_SHOW |
SWP_MOVE | SWP_ZORDER);
} /* endif */
/* Associate Instance of IPF */
if (hwndHelpInstance) WinAssociateHelpInstance (hwndHelpInstance, hwndFrame);
while(WinGetMsg(hab, (PQMSG)&qmsg, (HWND)NULL, 0, 0)) {
WinDispatchMsg(hab, (PQMSG)&qmsg);
} /* endwhile */
MainExit:
/* Destroy Instance of IPF */
if (hwndHelpInstance)
WinDestroyHelpInstance (hwndHelpInstance);
GpiUnloadFonts(hab, "C:\\OS2\\DLL\\HELV.FON");
/* deallocate strings */
for (i=IDS_FIRST_STRING; i<=IDS_LAST_STRING; i++) {
MemFree(pszStringTab[i]);
} /* endfor */
WinRemoveSwitchEntry(hSwitch);
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
return(rc);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Initialize the Default Mahjongg Game │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID InitializeDefaultGame(VOID)
{
INT i,j,x,y;
Game.pszTitle = strdup("Mahjongg Solitaire");
Game.pszHelpFile = strdup("MAHJONGG.HLP");
Board.cx = 2*BOARD_FR_CX + 16*(TILE_CX-TILE_BW) + TILE_BW;
Board.cy = 2*BOARD_FR_CY + 8*(TILE_CY-TILE_BW) + TILE_BW;
Board.cxt = TILE_CX;
Board.cyt = TILE_CY;
/* bottom level */
x = BOARD_FR_CX + 12*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 7*(TILE_CY-TILE_BW);
for (i=0; i<12; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
x = BOARD_FR_CX + 10*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 6*(TILE_CY-TILE_BW);
for (i=12; i<20; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
x = BOARD_FR_CX + 11*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 5*(TILE_CY-TILE_BW);
for (i=20; i<30; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
x = BOARD_FR_CX + 14*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 3*(TILE_CY-TILE_BW) + TILE_CY/2;
TilePos[30][0] = x;
TilePos[30][1] = y;
x -= (TILE_CX-TILE_BW);
TilePos[31][0] = x;
TilePos[31][1] = y;
x -= (TILE_CX-TILE_BW);
y = BOARD_FR_CY + 4*(TILE_CY-TILE_BW);
for (i=32; i<44; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
x = BOARD_FR_CX + 12*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 3*(TILE_CY-TILE_BW);
for (i=44; i<56; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
y += TILE_CY/2;
TilePos[56][0] = x;
TilePos[56][1] = y;
x = BOARD_FR_CX + 11*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 2*(TILE_CY-TILE_BW);
for (i=57; i<67; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
x = BOARD_FR_CX + 10*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 1*(TILE_CY-TILE_BW);
for (i=67; i<75; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
x = BOARD_FR_CX + 12*(TILE_CX-TILE_BW);
y = BOARD_FR_CY + 0*(TILE_CY-TILE_BW);
for (i=75; i<87; i++) {
TilePos[i][0] = x;
TilePos[i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
/* level 2 */
y = BOARD_FR_CY + 6*(TILE_CY-TILE_BW) + TILE_LD;
for (j=0; j<6; j++) {
x = BOARD_FR_CX + 9*(TILE_CX-TILE_BW) + TILE_LD;
for (i=0; i<6; i++) {
TilePos[87+j*6+i][0] = x;
TilePos[87+j*6+i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
y -= (TILE_CY-TILE_BW);
} /* endfor */
/* level 3 */
y = BOARD_FR_CY + 5*(TILE_CY-TILE_BW) + 2*TILE_LD;
for (j=0; j<4; j++) {
x = BOARD_FR_CX + 8*(TILE_CX-TILE_BW) + 2*TILE_LD;
for (i=0; i<4; i++) {
TilePos[123+j*4+i][0] = x;
TilePos[123+j*4+i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
y -= (TILE_CY-TILE_BW);
} /* endfor */
/* level 4 */
y = BOARD_FR_CY + 4*(TILE_CY-TILE_BW) + 3*TILE_LD;
for (j=0; j<2; j++) {
x = BOARD_FR_CX + 7*(TILE_CX-TILE_BW) + 3*TILE_LD;
for (i=0; i<2; i++) {
TilePos[139+j*2+i][0] = x;
TilePos[139+j*2+i][1] = y;
x -= (TILE_CX-TILE_BW);
} /* endfor */
y -= (TILE_CY-TILE_BW);
} /* endfor */
/* level 5 */
TilePos[143][0] = BOARD_FR_CX + 6*(TILE_CX-TILE_BW) + TILE_CX/2 + 4*TILE_LD;
TilePos[143][1] = BOARD_FR_CY + 3*(TILE_CY-TILE_BW) + TILE_CY/2 + 4*TILE_LD;
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Initialize the default tiles │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID InitializeDefaultTiles(VOID)
{
INT i;
for (i=0; i<NBR_OF_TILES; i++) {
Tiles[i].iTxt = DefTiles[i].iTxt;
Tiles[i].suit = DefTiles[i].suit;
Tiles[i].value = DefTiles[i].value;
Tiles[i].bSelected = DefTiles[i].bSelected;
Tiles[i].bRemoved = DefTiles[i].bRemoved;
} /* endfor */
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ create tiles │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID CreateTiles(HWND hwndParent)
{
SHORT cx,cy;
INT i;
cx = Board.cxt*(SHORT)deltaX;
cy = Board.cyt*(SHORT)deltaX;
for (i=0; i<NBR_OF_TILES; i++) {
Tiles[i].hwnd = WinCreateWindow(hwndParent, /* parent */
pszStringTab[IDS_CLASS_TILE], /* class */
(PSZ)NULL, /* title */
WS_VISIBLE, /* style */
TilePos[i][0]*(SHORT)deltaX, /* x */
TilePos[i][1]*(SHORT)deltaX, /* y */
cx, /* cx */
cy, /* cy */
hwndParent, /* owner */
HWND_TOP, /* behind */
i, /* id */
(PVOID)NULL, /* ctlDat */
(PVOID)NULL); /* reserv */
if (Tiles[i].hwnd == NULLH) {
WinMessageBox(HWND_DESKTOP,
hwndFrame,
(PSZ)"Error: while creating the tiles !",
(PSZ)Game.pszTitle,
0,
MB_CUAWARNING | MB_OK | MB_MOVEABLE);
break;
} /* endif */
} /* endfor */
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Shuffle Tile Indices │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID ShuffleTiles(VOID)
{
short i,j,r,cellcount,hold,save,cyclestart;
int k;
unsigned multiplier;
/* intialize to sorted order */
for (i=0; i<NBR_OF_TILES; i++) {
Shuffled[i] = i;
} /* endfor */
{ LONG ulTime;
time(&ulTime);
srand((USHORT)ulTime);
}
cellcount = NBR_OF_TILES;
cyclestart = -1;
while (1) {
do {
++cyclestart;
if (cyclestart >= NBR_OF_TILES)
break;;
} while (Shuffled[cyclestart]<0); /* enddo */
if (cyclestart >= NBR_OF_TILES)
break;
j = cyclestart;
save = Shuffled[j];
do {
hold = save;
frexp((double)cellcount, &k); /* which power of 2 is cellcount? */
multiplier = 0x0001 << (15-k); /* form the multiplier */
while (multiplier * cellcount - 1 <= (r=rand()));
if (cellcount)
r %= cellcount;
for (++r; r>0; r--) { /* the number of cells to skip */
do {
(j==(NBR_OF_TILES-1))?(j=0):(j++); /* seek an uncanceled cell */
} while (Shuffled[j]<0); /* enddo */
} /* endfor */
save = Shuffled[j];
Shuffled[j] = hold | 0x8000; /* mark the cell with the sign bit */
cellcount--;
}
while (j!=cyclestart);
}
for (i=0; i<NBR_OF_TILES; i++)
Shuffled[i] = Shuffled[i] & 0x7fff;
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Clear Message Queue │*/
/*│ INPUT : NONE │*/
/*│ RETURNS: TRUE if all messages were cleared │*/
/*│ FALSE if a WM_COMMAND or WM_BUTTONx message is pending│*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
BOOL ClearMsgQueue(void)
{
QMSG qmsg;
while (WinPeekMsg(hab, (PQMSG)&qmsg, NULLH, 0, 0,
PM_REMOVE)) {
switch (qmsg.msg) {
case WM_QUIT:
WinPostMsg(hwndBoard, WM_CLOSE, (MPARAM)0, (MPARAM)0);
return(FALSE);
break;
case WM_COMMAND:
case WM_BUTTON1DOWN:
case WM_BUTTON2DOWN:
case WM_CLOSE:
WinPostMsg(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
return(FALSE);
break;
default:
WinDispatchMsg(hab, (PQMSG)&qmsg);
} /* endswitch */
} /* endwhile */
return(TRUE);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Adjust the frame window size on creation of a patience game │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID CreationAdjustment(VOID)
{
SWP swp;
RECTL rectl;
if (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN) > 640L) {
idb_back = IDB_BACKBGA;
deltaX = DEFAULT_BGA_DX;
} else {
idb_back = IDB_BACKVGA;
deltaX = DEFAULT_VGA_DX;
} /* endif */
WinQueryWindowPos(hwndFrame, &swp);
if (swp.fl & SWP_MAXIMIZE) {
WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, 0, 0,
SWP_MAXIMIZE | SWP_SHOW | SWP_ZORDER);
} else {
rectl.xLeft = 0;
rectl.yBottom = 0;
rectl.xRight = (LONG)Board.cx*deltaX;
rectl.yTop = (LONG)Board.cy*deltaX;
WinCalcFrameRect(hwndFrame, &rectl, FALSE);
swp.cx = (SHORT)(rectl.xRight-rectl.xLeft);
swp.cy = (SHORT)(rectl.yTop-rectl.yBottom);
WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, swp.cx, swp.cy,
SWP_SIZE | SWP_SHOW | SWP_ZORDER);
} /* endif */
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ deal tiles │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID DealTiles(VOID)
{
INT i;
for (i=0; i<NBR_OF_TILES; i++) {
WinSetWindowPos(Tiles[Shuffled[i]].hwnd, HWND_TOP,
0, 0, 0, 0, SWP_HIDE);
} /* endfor */
for (i=0; i<NBR_OF_TILES; i++) {
Tiles[Shuffled[i]].bSelected = FALSE;
Tiles[Shuffled[i]].bRemoved = FALSE;
Tiles[Shuffled[i]].iPos = i;
WinSetWindowPos(Tiles[Shuffled[i]].hwnd, HWND_TOP,
sMaxAdjx + TilePos[i][0]*(SHORT)deltaX,
sMaxAdjy + TilePos[i][1]*(SHORT)deltaX,
0, 0,
SWP_MOVE | SWP_SHOW | SWP_ZORDER);
} /* endfor */
UndoTop = 0;
UndoCurrent = 0;
UndoBottom = 0;
NbrOfTilesRemaining = NBR_OF_TILES;
SelectedTile = NO_TILE;
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Main Window Procedure │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
MRESULT MainWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch (msg) {
case WM_CREATE:
{ HPS hps;
/* dirty tricks !!! (since these variables normally get */
/* set when the creation is complete) */
hwndBoard = hwnd;
hps = WinGetPS(hwnd);
GpiQueryRealColors(hps, LCOLOPT_REALIZED, 0L, 256L, ColorTable);
WinReleasePS(hps);
CreationAdjustment();
CreateTiles(hwnd);
WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(IDM_NEW_G), (MPARAM)0);
/* change title */
strncpy(swcntrl.szSwtitle, Game.pszTitle, MAXNAMEL);
WinChangeSwitchEntry(hSwitch, (PSWCNTRL)&swcntrl);
return((MRESULT)FALSE);
} break;
case WM_CLOSE:
WinPostMsg(hwnd, WM_QUIT, (MPARAM)0, (MPARAM)0);
break;
case WM_INITMENU:
switch (LOUSHORT(mp1)) {
case IDA_MOVES:
if (UndoCurrent != UndoBottom) {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_UNDO, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
} else {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_UNDO, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
} /* endif */
if (UndoCurrent != UndoTop) {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_REDO, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
} else {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_REDO, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
} /* endif */
break;
case IDA_OPTIONS:
if (bSound) {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_SOUND, TRUE),
MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
} else {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_SOUND, TRUE),
MPFROM2SHORT(MIA_CHECKED, 0));
} /* endif */
break;
case IDA_HELP:
if (hwndHelpInstance) {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_HELP, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_EXTENDED, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_KEYS, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_INDEX, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
} else {
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_HELP, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_EXTENDED, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_KEYS, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
WinSendMsg(WinWindowFromID(hwndFrame, FID_MENU), MM_SETITEMATTR,
MPFROM2SHORT(IDM_HELP_INDEX, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
} /* endif */
break;
} /* endswitch */
break;
case WM_COMMAND:
switch (SHORT1FROMMP(mp1)) {
case IDM_EXIT:
WinPostMsg(hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0);
break;
case IDM_NEW_G:
if (!bDealing) { /* don't allow reentrant new games */
bDealing = TRUE;
WinSetPointer(HWND_DESKTOP, hptrWait);
ShuffleTiles();
DealTiles();
WinSetPointer(HWND_DESKTOP, hptrArrow);
bDealing = FALSE;
} /* endif */
break;
case IDM_UNDO:
if (UndoCurrent != UndoBottom) {
INT t1,t2;
UndoCurrent--;
t1 = UndoBuffer[UndoCurrent].Tile1;
t2 = UndoBuffer[UndoCurrent].Tile2;
Tiles[t1].bRemoved = FALSE;
Tiles[t2].bRemoved = FALSE;
NbrOfTilesRemaining += 2;
WinSetWindowPos(Tiles[t1].hwnd, HWND_TOP, 0,0,0,0, SWP_SHOW);
WinSetWindowPos(Tiles[t2].hwnd, HWND_TOP, 0,0,0,0, SWP_SHOW);
if (SelectedTile != NO_TILE) {
WinSendMsg(Tiles[SelectedTile].hwnd, MJ_DESELECT, NULL, NULL);
} /* endif */
WinSendMsg(hwndBoard, MJ_INFORM_SELECTED, MPFROMSHORT(NO_TILE), NULL);
WinSendMsg(hwndBoard, MJ_DRAW_STATUS, NULL, NULL);
} /* endif */
break;
case IDM_REDO:
if (UndoCurrent != UndoTop) {
INT t1,t2;
t1 = UndoBuffer[UndoCurrent].Tile1;
t2 = UndoBuffer[UndoCurrent].Tile2;
WinSendMsg(Tiles[t1].hwnd, MJ_REMOVE, NULL, NULL);
WinSendMsg(Tiles[t2].hwnd, MJ_REMOVE, NULL, NULL);
if (SelectedTile != NO_TILE) {
WinSendMsg(Tiles[SelectedTile].hwnd, MJ_DESELECT, NULL, NULL);
} /* endif */
WinSendMsg(hwndBoard, MJ_INFORM_SELECTED, MPFROMSHORT(NO_TILE), NULL);
WinSendMsg(hwndBoard, MJ_DRAW_STATUS, NULL, NULL);
UndoCurrent++;
} /* endif */
break;
case IDM_SHOW:
/* show all possible moves */
{ short oldTile,i,j,f;
oldTile = SelectedTile;
if (SelectedTile != NO_TILE) {
/* deselect this tile first */
WinSendMsg(Tiles[SelectedTile].hwnd, MJ_DESELECT, NULL, NULL);
} /* endif */
f = 0;
for (i=0; i<NBR_OF_TILES; i++) {
if (IsTileSelectable(i)) {
for (j=i+1; j<NBR_OF_TILES; j++) {
if (IsTileSelectable(j)) {
if ((Tiles[i].suit == Tiles[j].suit) &&
(Tiles[i].value == Tiles[j].value)) {
/* flash the tiles */
WinSendMsg(Tiles[i].hwnd, MJ_SELECT, NULL, NULL);
WinSendMsg(Tiles[j].hwnd, MJ_SELECT, NULL, NULL);
DosSleep(600L);
WinSendMsg(Tiles[i].hwnd, MJ_DESELECT, NULL, NULL);
WinSendMsg(Tiles[j].hwnd, MJ_DESELECT, NULL, NULL);
f++;
} else {
} /* endif */
} /* endif */
} /* endfor */
} /* endif */
} /* endfor */
SelectedTile = oldTile;
if (SelectedTile != NO_TILE) {
/* reselect this tile */
WinSendMsg(Tiles[SelectedTile].hwnd, MJ_SELECT, NULL, NULL);
} /* endif */
if (f == 0) {
/* no more moves possible */
WinDlgBox(HWND_DESKTOP,
hwnd,
NoMoreWindowProc,
0,
IDD_NOMORE,
NULL);
} /* endif */
} break;
case IDM_SOUND:
bSound = !bSound;
break;
case IDM_SAVEOPT:
SaveOptions();
break;
case IDM_HELP_HELP:
WinSendMsg(hwndHelpInstance, HM_DISPLAY_HELP, NULL, NULL);
break;
case IDM_HELP_EXTENDED:
WinSendMsg(hwndHelpInstance, HM_DISPLAY_HELP,
MPFROMSHORT(ID_WINDOW), HM_RESOURCEID);
break;
case IDM_HELP_KEYS:
WinSendMsg(hwndHelpInstance, HM_DISPLAY_HELP,
MPFROMSHORT(IDM_HELP_KEYS), HM_RESOURCEID);
break;
case IDM_HELP_INDEX:
WinSendMsg(hwndHelpInstance, HM_HELP_CONTENTS, NULL, NULL);
break;
break;
case IDM_ABOUT:
WinDlgBox(HWND_DESKTOP, hwnd, AboutWindowProc, 0, IDD_ABOUT, NULL);
break;
} /* endswitch */
break;
case WM_BUTTON2DBLCLK:
if (!bDealing) {
WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(IDM_UNDO), NULL);
} /* endif */
break;
case HM_ERROR:
if ((hwndHelpInstance && (ULONG)mp1) == HMERR_NO_MEMORY) {
WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
(PSZ)"Help Terminated Due to Memory Error",
(PSZ)Game.pszTitle,
1,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
WinDestroyHelpInstance(hwndHelpInstance);
} else {
CHAR szErr[64];
sprintf(szErr, "Help Error %lx Occurred", (ULONG)mp1);
WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
(PSZ) "Help Error Occurred",
(PSZ)Game.pszTitle,
1,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
} /* endif */
break;
case WM_ERASEBACKGROUND:
return((MRESULT)FALSE);
break;
case WM_PAINT:
{ RECTL rectl;
HPS hps;
HBITMAP hbm;
hps = WinBeginPaint(hwnd, NULLH, &rectl);
WinQueryWindowRect(hwnd, &rectl);
hbm = GpiLoadBitmap(hps, NULLH, idb_back, 0L, 0L);
WinDrawBitmap(hps, hbm, NULL, (PPOINTL)&rectl, 0L, 0L,
DBM_NORMAL | DBM_STRETCH);
GpiDeleteBitmap(hbm);
WinEndPaint(hps);
} /* no break here! thee MJ_DRAW_STATUS should be the next case! */
case MJ_DRAW_STATUS:
{ RECTL rectl;
HPS hps;
CHAR szNbr[12];
HBITMAP hbm;
INT i,j;
static LastLength=3;
hps = WinGetPS(hwnd);
WinQueryWindowRect(hwnd, &rectl);
rectl.xRight -= BOARD_FR_CX*deltaX;
rectl.xLeft = rectl.xRight - (2L*TILE_CX*deltaX)/3L;
rectl.yTop -= BOARD_FR_CY + (9L*(TILE_CY-TILE_BW)*deltaX)/4L;
rectl.yBottom = rectl.yTop-(2L*TILE_CY*deltaX)/3L;
if (NbrOfTilesRemaining > 0) {
_itoa(NbrOfTilesRemaining, szNbr, 10);
j = strlen(szNbr)-1;
for (i=j; i>=0; i--) {
hbm = GpiLoadBitmap(hps, NULLH, IDB_TILE_N_0+szNbr[i]-'0', 0L, 0L);
WinDrawBitmap(hps, hbm, NULL, (PPOINTL)&rectl, 0L, 0L,
DBM_NORMAL | DBM_STRETCH);
GpiDeleteBitmap(hbm);
rectl.xRight -= (2L*TILE_CX*deltaX)/3L;
rectl.xLeft -= (2L*TILE_CX*deltaX)/3L;
} /* endfor */
} else {
j = -1;
} /* endif */
if (j<LastLength) {
WinInvalidateRect(hwnd, &rectl, FALSE);
} /* endif */
LastLength = j;
WinReleasePS(hps);
} break;
case MJ_PUSH_UNDOCMD:
UndoBuffer[UndoCurrent].Tile1 = SHORT1FROMMP(mp1);
UndoBuffer[UndoCurrent].Tile2 = SHORT2FROMMP(mp1);
UndoCurrent++;
UndoTop = UndoCurrent;
break;
case MJ_INFORM_SELECTED:
SelectedTile = SHORT1FROMMP(mp1);
break;
case MJ_QUERY_SELECTED:
return(MRFROMSHORT(SelectedTile));
break;
case MJ_ADJUST_TILES:
{ INT i;
SHORT cx,cy;
cx = Board.cxt*(SHORT)deltaX;
cy = Board.cyt*(SHORT)deltaX;
for (i=0; i<NBR_OF_TILES; i++) {
WinSetWindowPos(Tiles[Shuffled[i]].hwnd, HWND_TOP,
sMaxAdjx + TilePos[i][0]*(SHORT)deltaX,
sMaxAdjy + TilePos[i][1]*(SHORT)deltaX,
cx, cy,
SWP_MOVE | SWP_SIZE | SWP_ZORDER);
} /* endfor */
} break;
case MJ_SUCCESS:
{ POINTL ptl;
RECTL rectl, rectl2;
HPS hps;
LONG ldx,ldy;
INT i,j,m,s,r;
HBITMAP hbm;
BITMAPINFOHEADER hbmInfo;
BOOL success;
#if defined(SUCC_LOG)
printf("%u\n", usStart);
#endif
hps = WinGetPS(hwnd);
GpiCreateLogColorTable(hps, LCOL_REALIZABLE, LCOLF_CONSECRGB,
0L, 256L, ColorTable);
hbm = GpiLoadBitmap(hps, 0, IDB_CONGRATULATION, 0L, 0L);
success=WinQueryWindowRect(hwnd, &rectl);
GpiSetMix(hps, FM_XOR);
/* use a do...while(0) "loop" to simplify the logic of this block */
/* this allows us to break instead of nesting if...then statments */
success = FALSE;
do {
for (j=0; j<3; j++) {
ptl.x = (rectl.xLeft+rectl.xRight)/2L;
ptl.y = (rectl.yBottom+rectl.yTop)/2L;
for (i=0; i<5; i++) {
s = !(rand()%3); /* 0,1 */
r = 1+rand()%3; /* 1..3 */
m = 1+rand()%3; /* 1..3 */
ExplodeStar(hps, &ptl, m, r, s);
ExplodeStar(hps, &ptl, m, r, s);
ptl.x += (LONG)((rand()%2 ? 1 : -1)*(rand()%50));
ptl.y += (LONG)((rand()%2 ? 1 : -1)*(rand()%30));
if (!ClearMsgQueue()) {
success = TRUE;
break;
}
} /* endfor */
if (success)
break;
} /* endfor */
if (success)
break;
GpiQueryBitmapParameters(hbm, &hbmInfo);
ptl.x = (rectl.xLeft+rectl.xRight)/2L;
ptl.y = (rectl.yBottom+rectl.yTop)/2L;
for (i=1; i<=15; i++) {
ldx = (LONG)((i*hbmInfo.cx)/15);
ldy = (LONG)((i*hbmInfo.cy)/15);
rectl2.xLeft = ptl.x - ldx/2;
rectl2.yBottom = ptl.y - ldy/2;
rectl2.xRight = rectl2.xLeft + ldx;
rectl2.yTop = rectl2.yBottom + ldy;
WinDrawBitmap(hps, hbm, NULL, (PPOINTL)&rectl2, 0L, 0L,
DBM_NORMAL | DBM_STRETCH);
s = rand()%2; /* 0,1 */
r = 1+rand()%3; /* 1..3 */
m = 1+rand()%3; /* 1..3 */
ExplodeStar(hps, &ptl, m, r, s);
ExplodeStar(hps, &ptl, m, r, s);
if (!ClearMsgQueue()) {
success = TRUE;
break;
}
} /* endfor */
if (success)
break;
for (j=0; j<5; j++) {
ptl.x = (rectl.xLeft+rectl.xRight)/2L;
ptl.y = (rectl.yBottom+rectl.yTop)/2L;
for (i=0; i<10; i++) {
s = rand()%2; /* 0,1 */
r = 1+rand()%4; /* 1..4 */
m = 1+rand()%3; /* 1..3 */
ExplodeStar(hps, &ptl, m, r, s);
ExplodeStar(hps, &ptl, m, r, s);
ptl.x += (LONG)((rand()%2 ? 1 : -1)*(rand()%50));
ptl.y += (LONG)((rand()%2 ? 1 : -1)*(rand()%30));
if (!ClearMsgQueue()) {
success = TRUE;
break;
}
} /* endfor */
if (success)
break;
} /* endfor */
} while (0);
GpiDeleteBitmap(hbm);
ptl.x = rectl.xLeft;
ptl.y = (rectl.yBottom+rectl.yTop)/2L;
ptl.y -= (LONG)(hbmInfo.cy/2);
rectl.xLeft = ptl.x;
rectl.yBottom = ptl.y;
rectl.yTop = ptl.y + (LONG)hbmInfo.cy + 20L;
WinInvalidateRect(hwnd, &rectl, TRUE);
WinReleasePS(hps);
} break;
default:
return(WinDefWindowProc(hwnd, msg, mp1, mp2));
break;
} /* endswitch */
return((MRESULT)NULL);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Draw Lines │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID DrawLines(HPS hps,
PPOINTL pC, /* draw relativ to this center */
POINTL Ptl[], /* points (first quadrant only) */
LONG mult, /* multiplicator */
INT n) /* nbr of lines (=nbr of points/2) */
{
INT i;
POINTL p11,p12,p21,p22,p31,p32,p41,p42;
for (i=0; i<n; i++) {
p11.x = pC->x + mult*Ptl[2*i].x; p11.y = pC->y + mult*Ptl[2*i].y;
p12.x = pC->x + mult*Ptl[2*i+1].x; p12.y = pC->y + mult*Ptl[2*i+1].y;
p21.x = pC->x - mult*Ptl[2*i].x; p21.y = pC->y - mult*Ptl[2*i].y;
p22.x = pC->x - mult*Ptl[2*i+1].x; p22.y = pC->y - mult*Ptl[2*i+1].y;
p31.x = pC->x - mult*Ptl[2*i].y; p31.y = pC->y + mult*Ptl[2*i].x;
p32.x = pC->x - mult*Ptl[2*i+1].y; p32.y = pC->y + mult*Ptl[2*i+1].x;
p41.x = pC->x + mult*Ptl[2*i].y; p41.y = pC->y - mult*Ptl[2*i].x;
p42.x = pC->x + mult*Ptl[2*i+1].y; p42.y = pC->y - mult*Ptl[2*i+1].x;
GpiMove(hps, &p11);
GpiLine(hps, &p12);
GpiMove(hps, &p21);
GpiLine(hps, &p22);
GpiMove(hps, &p31);
GpiLine(hps, &p32);
GpiMove(hps, &p41);
GpiLine(hps, &p42);
} /* endfor */
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ Draw an exploding star │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
VOID ExplodeStar(HPS hps,
PPOINTL pC, /* pC of the star */
INT dr, /* multiplicator */
INT itr, /* nbr of iterations */
INT substars /* 0 = none, 1 = stars, 2 = circles */
)
{
static POINTL ptl0[2] = { { 0L, 0L}, { 4L, 0L}
};
static POINTL ptl1[4] = { { 4L, 0L}, { 9L, 0L},
{ 3L, 3L}, { 6L, 6L},
};
static POINTL ptl2[8] = { { 9L, 0L}, {15L, 0L},
{ 8L, 3L}, {14L, 6L},
{ 6L, 6L}, {11L,11L},
{ 3L, 8L}, { 6L,14L},
};
static POINTL ptl3[16] = { {15L, 0L}, {22L, 0L},
{15L, 3L}, {22L, 5L},
{14L, 6L}, {21L, 9L},
{12L, 8L}, {19L,12L},
{11L,11L}, {16L,16L},
{ 8L,12L}, {12L,19L},
{ 6L,14L}, { 9L,21L},
{ 3L,15L}, { 5L,22L},
};
static POINTL ptl4[32] = { {22L, 0L}, {30L, 0L},
{22L, 2L}, {30L, 3L},
{22L, 5L}, {29L, 6L},
{21L, 7L}, {29L, 9L},
{21L, 9L}, {28L,12L},
{19L,10L}, {27L,14L},
{19L,12L}, {25L,16L},
{17L,14L}, {23L,19L},
{16L,16L}, {22L,22L},
{14L,17L}, {19L,23L},
{12L,19L}, {16L,25L},
{10L,19L}, {14L,27L},
{ 9L,21L}, {12L,28L},
{ 7L,21L}, { 9L,29L},
{ 5L,22L}, { 6L,29L},
{ 2L,22L}, { 3L,30L},
};
INT i;
POINTL p1,p2,p3,p4;
LONG mult, mult2;
mult = (LONG)dr;
mult2= (LONG)max(dr/4,1);
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,0,0)));
DrawLines(hps, pC, ptl0, mult, 1);
if (itr > 1) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,160,0)));
DrawLines(hps, pC, ptl1, mult, 2);
} else {
return;
} /* endif */
if (itr > 2) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,255,0)));
DrawLines(hps, pC, ptl2, mult, 4);
} else {
if (substars) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,255,255)));
for (i=0; i<2; i++) {
p1.x = pC->x + mult*ptl1[2*i+1].x; p1.y = pC->y + mult*ptl1[2*i+1].y;
p2.x = pC->x - mult*ptl1[2*i+1].x; p2.y = pC->y - mult*ptl1[2*i+1].y;
p3.x = pC->x - mult*ptl1[2*i+1].y; p3.y = pC->y + mult*ptl1[2*i+1].x;
p4.x = pC->x + mult*ptl1[2*i+1].y; p4.y = pC->y - mult*ptl1[2*i+1].x;
DrawLines(hps, &p1, ptl1, mult2, 2);
DrawLines(hps, &p2, ptl1, mult2, 2);
DrawLines(hps, &p3, ptl1, mult2, 2);
DrawLines(hps, &p4, ptl1, mult2, 2);
} /* endfor */
} else {
} /* endif */
return;
} /* endif */
if (itr > 3) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,255,160)));
DrawLines(hps, pC, ptl3, mult, 8);
} else {
if (substars) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,0,0)));
for (i=0; i<4; i++) {
p1.x = pC->x + mult*ptl2[2*i+1].x; p1.y = pC->y + mult*ptl2[2*i+1].y;
p2.x = pC->x - mult*ptl2[2*i+1].x; p2.y = pC->y - mult*ptl2[2*i+1].y;
p3.x = pC->x - mult*ptl2[2*i+1].y; p3.y = pC->y + mult*ptl2[2*i+1].x;
p4.x = pC->x + mult*ptl2[2*i+1].y; p4.y = pC->y - mult*ptl2[2*i+1].x;
DrawLines(hps, &p1, ptl2, mult2, 4);
DrawLines(hps, &p2, ptl2, mult2, 4);
DrawLines(hps, &p3, ptl2, mult2, 4);
DrawLines(hps, &p4, ptl2, mult2, 4);
} /* endfor */
} else {
} /* endif */
return;
} /* endif */
if (itr > 4) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(255,255,255)));
DrawLines(hps, pC, ptl4, mult,16);
if (substars) {
for (i=0; i<16; i++) {
p1.x = pC->x + mult*ptl4[2*i+1].x; p1.y = pC->y + mult*ptl4[2*i+1].y;
p2.x = pC->x - mult*ptl4[2*i+1].x; p2.y = pC->y - mult*ptl4[2*i+1].y;
p3.x = pC->x - mult*ptl4[2*i+1].y; p3.y = pC->y + mult*ptl4[2*i+1].x;
p4.x = pC->x + mult*ptl4[2*i+1].y; p4.y = pC->y - mult*ptl4[2*i+1].x;
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(0,0,255)));
DrawLines(hps, &p1, ptl1, mult2, 2);
DrawLines(hps, &p2, ptl1, mult2, 2);
DrawLines(hps, &p3, ptl1, mult2, 2);
DrawLines(hps, &p4, ptl1, mult2, 2);
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(0,160,255)));
DrawLines(hps, &p1, ptl2, mult2, 4);
DrawLines(hps, &p2, ptl2, mult2, 4);
DrawLines(hps, &p3, ptl2, mult2, 4);
DrawLines(hps, &p4, ptl2, mult2, 4);
if (mult2 > 2) {
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(160,180,255)));
DrawLines(hps, &p1, ptl3, mult2, 8);
DrawLines(hps, &p2, ptl3, mult2, 8);
DrawLines(hps, &p3, ptl3, mult2, 8);
DrawLines(hps, &p4, ptl3, mult2, 8);
} else {
} /* endif */
} /* endfor */
} else {
} /* endif */
} else {
if (substars) {
for (i=0; i<8; i++) {
p1.x = pC->x + mult*ptl3[2*i+1].x; p1.y = pC->y + mult*ptl3[2*i+1].y;
p2.x = pC->x - mult*ptl3[2*i+1].x; p2.y = pC->y - mult*ptl3[2*i+1].y;
p3.x = pC->x - mult*ptl3[2*i+1].y; p3.y = pC->y + mult*ptl3[2*i+1].x;
p4.x = pC->x + mult*ptl3[2*i+1].y; p4.y = pC->y - mult*ptl3[2*i+1].x;
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(0,255,0)));
DrawLines(hps, &p1, ptl1, mult2, 2);
DrawLines(hps, &p2, ptl1, mult2, 2);
DrawLines(hps, &p3, ptl1, mult2, 2);
DrawLines(hps, &p4, ptl1, mult2, 2);
GpiSetColor(hps, GpiQueryColorIndex(hps, LCOLOPT_REALIZED,
LONGFromRGB(0,255,160)));
DrawLines(hps, &p1, ptl2, mult2, 4);
DrawLines(hps, &p2, ptl2, mult2, 4);
DrawLines(hps, &p3, ptl2, mult2, 4);
DrawLines(hps, &p4, ptl2, mult2, 4);
} /* endfor */
} else {
} /* endif */
} /* endif */
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ About Window Procedure │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
MRESULT AboutWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch(msg) {
case WM_CHAR:
if ((LOUSHORT(mp2)&0x00FF) == 27) { /* ESC */
return((MRESULT)WinDismissDlg(hwnd, TRUE));
} /* endif */
return(WinDefDlgProc(hwnd, msg, mp1, mp2));
break;
case WM_COMMAND:
switch (SHORT1FROMMP(mp1)) {
case IDD_OK:
WinDismissDlg(hwnd, TRUE);
break;
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
} /* endswitch */
break;
default:
return(WinDefDlgProc(hwnd, msg, mp1, mp2));
} /* endswitch */
return((MRESULT)NULL);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ No more moves Dlg Procedure │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
MRESULT NoMoreWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch(msg) {
case WM_CHAR:
if ((LOUSHORT(mp2)&0x00FF) == 27) { /* ESC */
return((MRESULT)WinDismissDlg(hwnd, FALSE));
} /* endif */
return(WinDefDlgProc(hwnd, msg, mp1, mp2));
break;
case WM_COMMAND:
switch (SHORT1FROMMP(mp1)) {
case IDD_OK:
WinDismissDlg(hwnd, FALSE);
break;
case IDD_NEW:
WinPostMsg(hwndBoard, WM_COMMAND, MPFROMSHORT(IDM_NEW_G), (MPARAM)0);
WinDismissDlg(hwnd, TRUE);
break;
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
} /* endswitch */
break;
default:
return(WinDefDlgProc(hwnd, msg, mp1, mp2));
} /* endswitch */
return((MRESULT)NULL);
}
/*┌──────────────────────────────────────────────────────────────────────────┐*/
/*│ frame subclass procedure │*/
/*└──────────────────────────────────────────────────────────────────────────┘*/
MRESULT FrameSubClass(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch(msg) {
case WM_ADJUSTWINDOWPOS:
{ MRESULT rc;
rc = oldFrameProc(hwnd, msg, mp1, mp2);
if (WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MINIMIZED) {
/* the window is minimized, so ignore this case */
} else {
PSWP pswp;
pswp = (PSWP)PVOIDFROMMP(mp1);
if (pswp->fl & SWP_MAXIMIZE) {
deltaX = (LONG)min(pswp->cx/Board.cx, pswp->cy/Board.cy);
sMaxAdjx = (pswp->cx - Board.cx*(SHORT)deltaX)/2;
sMaxAdjy = (pswp->cy - Board.cy*(SHORT)deltaX
- (SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR)
- (SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CYMENU))/2;
WinPostMsg(hwndBoard, MJ_ADJUST_TILES, NULL, NULL);
} else if (pswp->fl & SWP_MINIMIZE) {
// ignore this case
} else if (pswp->fl & SWP_RESTORE) {
deltaX = (LONG)min(pswp->cx/Board.cx, pswp->cy/Board.cy);
sMaxAdjx = sMaxAdjy = 0;
WinPostMsg(hwndBoard, MJ_ADJUST_TILES, NULL, NULL);
} else if ((pswp->fl & SWP_SIZE) &&
!(WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MAXIMIZED)) {
LONG dXold;
dXold = deltaX;
deltaX = (LONG)min(pswp->cx/Board.cx, pswp->cy/Board.cy);
if (dXold != deltaX)
WinPostMsg(hwndBoard, MJ_ADJUST_TILES, NULL, NULL);
} else {
} /* endif */
} /* endif */
return(rc);
} break;
case WM_QUERYTRACKINFO:
{ MRESULT rc;
/*┌──────────────────────────────────────────────────────────────────┐*/
/*│ Invoke the normal frame-window procedure first in order │*/
/*│ to update the tracking rectangle to the new position. │*/
/*└──────────────────────────────────────────────────────────────────┘*/
rc = oldFrameProc(hwnd, msg, mp1, mp2);
if (WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MINIMIZED) {
// the window is minimized, so ignore this case
} else {
LONG dx, dy;
PTRACKINFO ptrack;
RECTL rcl;
ptrack = (PTRACKINFO)mp2;
/*┌────────────────────────────────────────────────────────────────┐*/
/*│ Limit the size of the bounding rectangle only if the │*/
/*│ window is being sized. │*/
/*│ fs and rclBoundary are tracking information structure │*/
/*│ elements. │*/
/*└────────────────────────────────────────────────────────────────┘*/
if((( ptrack->fs & TF_MOVE ) != TF_MOVE ) &&
(( ptrack->fs & TF_LEFT ) ||
( ptrack->fs & TF_TOP ) ||
( ptrack->fs & TF_RIGHT ) ||
( ptrack->fs & TF_BOTTOM ) ||
( ptrack->fs & TF_SETPOINTERPOS ))) {
WinQueryWindowRect(hwndBoard, (PRECTL)&rcl);
dx = (rcl.xRight - rcl.xLeft)/Board.cx;
dy = (rcl.yTop - rcl.yBottom)/Board.cy;
deltaX = min(dx, dy);
ptrack->rclTrack.yBottom = rcl.yBottom;
ptrack->rclTrack.yTop = rcl.yBottom + deltaX*Board.cy;
ptrack->rclTrack.xLeft = rcl.xLeft;
ptrack->rclTrack.xRight = rcl.xLeft + deltaX*Board.cx;
/*┌──────────────────────────────────────────────────────────────┐*/
/*│ Convert client boundary coordinates to screen │*/
/*│ coordinates. │*/
/*└──────────────────────────────────────────────────────────────┘*/
WinMapWindowPoints(hwndBoard, HWND_DESKTOP,
(PPOINTL)&ptrack->rclTrack, 2);
/*┌──────────────────────────────────────────────────────────────┐*/
/*│ Calculate equivalent frame boundary from client │*/
/*│ boundary data. │*/
/*└──────────────────────────────────────────────────────────────┘*/
WinCalcFrameRect(hwnd, (PRECTL)&ptrack->rclTrack, FALSE);
ptrack->cxGrid = Board.cx;
ptrack->cyGrid = Board.cy;
ptrack->fs |= TF_GRID;
} /* endif */
} /* endif */
return((MRESULT)rc);
} break;
default:
/*┌───────────────────────────────────────────────────────────────────┐*/
/*│ Return via the normal frame window procedure. │*/
/*└───────────────────────────────────────────────────────────────────┘*/
return(oldFrameProc(hwnd, msg, mp1, mp2));
break;
} /* endswitch */
return((MRESULT)NULL);
}