579 lines
9.7 KiB
C
579 lines
9.7 KiB
C
/****************************************************************************
|
||
|
||
PROGRAM: 3-D TicTacToe (a.k.a. Qubic, TicTactics)
|
||
|
||
****************************************************************************/
|
||
|
||
#define _WINDOWS
|
||
#include <windows.h>
|
||
#include <port1632.h>
|
||
|
||
#include "main.h"
|
||
#include "rtns.h"
|
||
#include "grafix.h"
|
||
#include "util.h"
|
||
#include "res.h"
|
||
#include "pref.h"
|
||
#include "sound.h"
|
||
#include "string.h"
|
||
#include "context.h"
|
||
#include "dos.h"
|
||
|
||
|
||
HANDLE hInst;
|
||
HWND hwndMain;
|
||
HMENU hMenu;
|
||
|
||
STATUS status = fstatusIcon;
|
||
BOOL fEGA;
|
||
|
||
extern fUpdateIni;
|
||
|
||
BOOL fButton1Down = fFalse;
|
||
|
||
extern BLK rgBlk[cBlkMax];
|
||
|
||
INT dxpWindow;
|
||
INT dypWindow;
|
||
INT dypCaption;
|
||
INT dypMenu;
|
||
INT dypAdjust;
|
||
INT dypBorder;
|
||
INT dxpBorder;
|
||
INT dxpGridOff;
|
||
|
||
INT dyBlkPlane;
|
||
INT dypPlane;
|
||
INT dxpPlane;
|
||
|
||
INT dxpGrid;
|
||
INT dypGrid;
|
||
|
||
|
||
BLK blkCurr;
|
||
|
||
CHAR szClass[cchNameMax];
|
||
#define szWindowTitle szClass
|
||
|
||
extern INT cBlkRow;
|
||
extern INT cBlkPlane;
|
||
extern INT cBlkMac;
|
||
extern INT cPlane;
|
||
|
||
extern BOOL f4;
|
||
|
||
extern PREF Preferences;
|
||
extern BOOL fUpdateIni;
|
||
|
||
|
||
|
||
/****** W I N M A I N ******/
|
||
|
||
MMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
|
||
/* { */
|
||
MSG msg;
|
||
HANDLE hAccel;
|
||
|
||
hInst = hInstance;
|
||
|
||
InitConst();
|
||
|
||
if (hPrevInstance)
|
||
{
|
||
HWND hwnd = FindWindow(szClass, NULL);
|
||
hwnd = GetLastActivePopup(hwnd);
|
||
BringWindowToTop(hwnd);
|
||
if (IsIconic(hwnd))
|
||
ShowWindow(hwnd, SW_RESTORE);
|
||
return fFalse;
|
||
}
|
||
|
||
|
||
#ifdef NOSERVER /* Not in final version */
|
||
{
|
||
CHAR szFile[256];
|
||
|
||
GetModuleFileName(hInst, szFile, 250);
|
||
if (szFile[0] > 'C')
|
||
{
|
||
szFile[0] = 'X';
|
||
if (!strcmp(szFile, "X:\\WINGAMES\\TICTACTO\\TIC.EXE"))
|
||
{
|
||
MessageBox(GetFocus(),
|
||
"Please copy tic.exe and aboutwep.dll to your machine and run it from there.",
|
||
"NO NO NO NO NO",
|
||
MB_OK);
|
||
return fFalse;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef EXPIRE /*** Not in final release ***/
|
||
{
|
||
struct dosdate_t ddt;
|
||
|
||
_dos_getdate(&ddt);
|
||
|
||
if ((ddt.month + ddt.year*12) > (10 + 1990*12))
|
||
{
|
||
MessageBox(GetFocus(),
|
||
"This game has expired. Please obtain an official copy from the Windows Entertainment Package.",
|
||
"SORRY",
|
||
MB_OK);
|
||
return fFalse;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
{
|
||
WNDCLASS wc;
|
||
|
||
wc.style = 0;
|
||
wc.lpfnWndProc = MainWndProc;
|
||
wc.cbClsExtra = 0;
|
||
wc.cbWndExtra = 0;
|
||
wc.hInstance = hInst;
|
||
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(ID_ICON_TIC2));
|
||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
|
||
wc.lpszMenuName = NULL;
|
||
wc.lpszClassName = szClass;
|
||
|
||
if (!RegisterClass(&wc))
|
||
return fFalse;
|
||
}
|
||
|
||
hMenu = LoadMenu(hInst, MAKEINTRESOURCE(ID_MENU));
|
||
hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(ID_MENU_ACCEL));
|
||
|
||
ReadPreferences();
|
||
|
||
AdjustWindow(fCalc);
|
||
|
||
hwndMain = CreateWindow(szClass, szWindowTitle,
|
||
WS_OVERLAPPED | WS_MINIMIZE | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU,
|
||
Preferences.xWindow-dxpBorder, Preferences.yWindow-dypAdjust,
|
||
dxpWindow+dxpBorder, dypWindow+dypAdjust,
|
||
NULL, NULL, hInst, NULL);
|
||
|
||
if (!hwndMain)
|
||
{
|
||
ReportErr(1000);
|
||
return (fFalse);
|
||
}
|
||
|
||
if (SetTimer(hwndMain, ID_TIME_FLASH, 500 , NULL) == 0)
|
||
{
|
||
ReportErr(ID_ERR_TIMER);
|
||
return fFalse;
|
||
}
|
||
|
||
if (!FInitLocal())
|
||
{
|
||
ReportErr(ID_ERR_MEM);
|
||
return fFalse;
|
||
}
|
||
|
||
SetMenuBar(Preferences.fMenu);
|
||
|
||
ShowWindow(hwndMain, SW_SHOWNORMAL);
|
||
UpdateWindow(hwndMain);
|
||
|
||
StartGame();
|
||
|
||
while (GetMessage(&msg, NULL, 0, 0))
|
||
{
|
||
if (!TranslateAccelerator(hwndMain, hAccel, &msg))
|
||
{
|
||
TranslateMessage(&msg);
|
||
DispatchMessage(&msg);
|
||
}
|
||
}
|
||
|
||
CleanUp();
|
||
|
||
if (fUpdateIni)
|
||
WritePreferences();
|
||
|
||
return (INT)(msg.wParam);
|
||
}
|
||
|
||
|
||
/****** B L K F R O M X Y ******/
|
||
|
||
/* Rewrite ! - just one return */
|
||
|
||
BLK BlkFromXY(INT x, INT y)
|
||
{
|
||
BLK blk = 0;
|
||
|
||
if (((x-=dxpGridOff) >= 0) &&
|
||
(x < dxpGrid) &&
|
||
((y-=(dypGridOff+dyBlkDiff-2)) >= 0) &&
|
||
(y < dypGrid) )
|
||
{
|
||
while (y >= dyBlkPlane)
|
||
{
|
||
if ((y -= (dyLevel+dypPlane)) < 0)
|
||
return iBlkNil; /* No allow hits between levels */
|
||
blk++;
|
||
}
|
||
|
||
x -= (dyBlkPlane-y);
|
||
if ((x >= 0) && (x < (cBlkRow*(dxBlk-1))) )
|
||
return (blk*cBlkPlane + cBlkRow*(y/dyBlk) + (x/(dxBlk-1)) );
|
||
}
|
||
|
||
return iBlkNil;
|
||
}
|
||
|
||
|
||
/****** F V A L I D M O V E ******/
|
||
|
||
BOOL FValidMove(BLK blk)
|
||
{
|
||
if (blk != iBlkNil)
|
||
if (rgBlk[blk] == iBallBlank)
|
||
return fTrue;
|
||
return fFalse;
|
||
}
|
||
|
||
|
||
/****** F I X M E N U S ******/
|
||
|
||
VOID FixMenus(VOID)
|
||
{
|
||
CheckEm(IDM_3x3, Preferences.iGameType == iGame3x3);
|
||
CheckEm(IDM_3x3x3, Preferences.iGameType == iGame3x3x3);
|
||
CheckEm(IDM_4x4x4, Preferences.iGameType == iGame4x4x4);
|
||
|
||
#ifdef NOISEY
|
||
CheckEm(IDM_SOUND, Preferences.fSound);
|
||
#endif
|
||
CheckEm(IDM_COLOR, Preferences.fColor);
|
||
|
||
CheckEm(IDM_RND, Preferences.iStart == iStartRnd);
|
||
CheckEm(IDM_RED, Preferences.iStart == iStartRed);
|
||
CheckEm(IDM_BLUE, Preferences.iStart == iStartBlue);
|
||
|
||
CheckEm(IDM_BEGIN, Preferences.skill == skillBegin);
|
||
CheckEm(IDM_INTER, Preferences.skill == skillInter);
|
||
CheckEm(IDM_EXPERT, Preferences.skill == skillExpert);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/****** M A I N W N D P R O C ******/
|
||
|
||
LRESULT APIENTRY MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch (message)
|
||
{
|
||
|
||
case WM_SYSCOMMAND:
|
||
switch (wParam & 0xFFF0)
|
||
{
|
||
case SC_MINIMIZE:
|
||
SetStatusPause();
|
||
SetStatusIcon();
|
||
break;
|
||
|
||
case SC_RESTORE:
|
||
ClrStatusPause();
|
||
ClrStatusIcon();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
|
||
|
||
case WM_COMMAND:
|
||
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
||
|
||
/** GAME **/
|
||
|
||
case IDM_NEW:
|
||
StartGame();
|
||
break;
|
||
|
||
case IDM_3x3:
|
||
case IDM_3x3x3:
|
||
case IDM_4x4x4:
|
||
Preferences.iGameType = GET_WM_COMMAND_ID(wParam, lParam) - IDM_3x3;
|
||
|
||
AdjustWindow(fCalc | fResize);
|
||
StartGame();
|
||
goto LUpdateMenu;
|
||
|
||
case IDM_EXIT:
|
||
ShowWindow(hwndMain, SW_HIDE);
|
||
#ifdef ORGCODE
|
||
goto LExit;
|
||
#else
|
||
SendMessage(hwndMain, WM_SYSCOMMAND, SC_CLOSE, 0);
|
||
return(0);
|
||
#endif
|
||
|
||
/** SKILL **/
|
||
|
||
case IDM_BEGIN:
|
||
Preferences.skill = skillBegin;
|
||
goto LUpdateMenu;
|
||
case IDM_INTER:
|
||
Preferences.skill = skillInter;
|
||
goto LUpdateMenu;
|
||
case IDM_EXPERT:
|
||
Preferences.skill = skillExpert;
|
||
goto LUpdateMenu;
|
||
|
||
/** OPTIONS **/
|
||
#ifdef NOISEY
|
||
case IDM_SOUND:
|
||
if (Preferences.fSound)
|
||
{
|
||
EndTunes();
|
||
Preferences.fSound = fFalse;
|
||
}
|
||
else
|
||
{
|
||
Preferences.fSound = FInitTunes();
|
||
}
|
||
goto LUpdateMenu;
|
||
#endif
|
||
|
||
case IDM_COLOR:
|
||
Preferences.fColor = !Preferences.fColor;
|
||
GetTheBitmap();
|
||
ReDoDisplay();
|
||
DisplayScreen();
|
||
goto LUpdateMenu;
|
||
|
||
case IDM_RND:
|
||
case IDM_RED:
|
||
case IDM_BLUE:
|
||
Preferences.iStart = GET_WM_COMMAND_ID(wParam, lParam) - IDM_RND;
|
||
StartGame();
|
||
/* IE goto LUpdateMenu; */
|
||
|
||
LUpdateMenu:
|
||
fUpdateIni = fTrue;
|
||
FixMenus();
|
||
break;
|
||
|
||
|
||
/** HELP **/
|
||
case IDM_INDEX:
|
||
DoHelp(HELP_INDEX, 0L);
|
||
break;
|
||
|
||
case IDM_HOW2PLAY:
|
||
DoHelp(HELP_CONTEXT, HLP_HOWTOPLAY);
|
||
break;
|
||
|
||
case IDM_COMMANDS:
|
||
DoHelp(HELP_CONTEXT, HLP_COMMANDS);
|
||
break;
|
||
|
||
case IDM_HELP_HELP:
|
||
DoHelp(HELP_HELPONHELP, 0L);
|
||
break;
|
||
|
||
|
||
case IDM_HELP_ABOUT:
|
||
DoAbout();
|
||
return 0;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
case WM_KEYDOWN:
|
||
switch (wParam)
|
||
{
|
||
case VK_ESCAPE:
|
||
PostMessage(hwndMain, WM_SYSCOMMAND, SC_MINIMIZE, 0L);
|
||
break;
|
||
|
||
#if 0
|
||
case VK_F1:
|
||
DoHelp(HELP_INDEX, 0L);
|
||
break;
|
||
|
||
case VK_F2:
|
||
StartGame();
|
||
break;
|
||
|
||
#endif
|
||
case VK_F4:
|
||
if (FSoundSwitchable())
|
||
if (FSoundOn())
|
||
{
|
||
EndTunes();
|
||
Preferences.fSound = fsoundOff;
|
||
}
|
||
else
|
||
Preferences.fSound = FInitTunes();
|
||
break;
|
||
|
||
case VK_F5:
|
||
if (FMenuSwitchable())
|
||
SetMenuBar(fmenuOff);
|
||
break;
|
||
|
||
case VK_F6:
|
||
if (FMenuSwitchable())
|
||
SetMenuBar(fmenuOn);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
|
||
// case WM_QUERYENDSESSION:
|
||
case WM_DESTROY:
|
||
//LExit:
|
||
KillTimer(hwndMain,ID_TIME_FLASH);
|
||
DoHelp(HELP_QUIT, 0L);
|
||
PostQuitMessage(0);
|
||
break;
|
||
|
||
case WM_CHAR:
|
||
break;
|
||
|
||
case WM_LBUTTONDOWN:
|
||
if (!FPlay())
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
fButton1Down = fTrue;
|
||
blkCurr = iBlkNil;
|
||
SetCapture(hwndMain);
|
||
|
||
case WM_MOUSEMOVE:
|
||
if (fButton1Down)
|
||
{
|
||
BLK blk = BlkFromXY(LOWORD(lParam), HIWORD(lParam));
|
||
if ((blk != blkCurr) && FValidMove(blk))
|
||
{
|
||
if (FValidMove(blkCurr))
|
||
DisplayBall(blkCurr, iBallBlank);
|
||
blkCurr = blk;
|
||
PlayTune(TUNE_MOVE);
|
||
DisplayBall(blk, iBallGrey);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case WM_LBUTTONUP:
|
||
if (fButton1Down)
|
||
{
|
||
fButton1Down = fFalse;
|
||
ReleaseCapture();
|
||
if (FValidMove(blkCurr))
|
||
DoMove(blkCurr);
|
||
}
|
||
break;
|
||
|
||
case WM_RBUTTONDOWN:
|
||
if (FPlay())
|
||
UnDoMove();
|
||
else
|
||
StartGame();
|
||
break;
|
||
|
||
case WM_TIMER:
|
||
DoTimer();
|
||
return 0;
|
||
|
||
case WM_PAINT:
|
||
{
|
||
PAINTSTRUCT ps;
|
||
HDC hDC = BeginPaint(hwnd,&ps);
|
||
|
||
DrawScreen(hDC);
|
||
|
||
EndPaint(hwnd, &ps);
|
||
}
|
||
return 0;
|
||
|
||
case WM_MOVE:
|
||
if (!FIcon())
|
||
{
|
||
Preferences.xWindow = 1+LOWORD(lParam);
|
||
Preferences.yWindow = 1+HIWORD(lParam);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
|
||
}
|
||
|
||
return (DefWindowProc(hwnd, message, wParam, lParam));
|
||
}
|
||
|
||
|
||
/****** A D J U S T W I N D O W ******/
|
||
|
||
VOID AdjustWindow(INT fAdjust)
|
||
{
|
||
SetupData();
|
||
|
||
dypAdjust = dypCaption;
|
||
|
||
if (FMenuOn())
|
||
dypAdjust += dypMenu;
|
||
|
||
if (GetSystemMetrics(SM_CYSCREEN) >= 480) /* Is display 8514 ? */
|
||
{
|
||
#define stupid8514 40
|
||
|
||
dxpWindow = 180 + stupid8514;
|
||
if (f4)
|
||
dxpGridOff = 16 + stupid8514/2;
|
||
else
|
||
dxpGridOff = 34 + stupid8514/2;
|
||
}
|
||
else
|
||
{
|
||
dxpWindow = 180; /* Aren't constants fun ? */
|
||
if (f4)
|
||
dxpGridOff = 16;
|
||
else
|
||
dxpGridOff = 34;
|
||
}
|
||
|
||
dyBlkPlane = dyBlk * cBlkRow;
|
||
dxpGrid = dxpPlane = (dxBall-1)*cBlkRow;
|
||
dypPlane = dyBlkPlane + dyLevel;
|
||
dypGrid = (((dyBlk * cBlkRow) + dyLevel+dyBlkDiff) * cPlane);
|
||
|
||
dypWindow = dypGridOff + dypGrid + dyEdge;
|
||
|
||
if (fAdjust & fResize)
|
||
{
|
||
SetupBoard();
|
||
|
||
InvalidateRect(hwndMain, NULL, fTrue);
|
||
|
||
MoveWindow(hwndMain, Preferences.xWindow - dxpBorder,
|
||
Preferences.yWindow - dypAdjust,
|
||
dxpWindow+dxpBorder, dypWindow + dypAdjust, fTrue);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|