/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "bagel/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/hodjnpodj/libs/macros.h"
#include "bagel/boflib/sound.h"
#include "bagel/boflib/misc.h"
#include "bagel/hodjnpodj/mankala/mnk.h"
#include "bagel/hodjnpodj/mankala/resource.h"
namespace Bagel {
namespace HodjNPodj {
namespace Mankala {
//#define _MACROS3
#define IDC_PITBUTTON 1
#define PITBUTTON_TIMER 2
LPGAMESTRUCT pGameParams;
extern HWND ghParentWnd;
/////////////////////////////////////////////////////////////////////////////
char m_szText[80]; // descriptive text
int m_iHeaderSize; // size of header (# bytes)
int m_iVersion; // version number
int m_iTableStones; // # stones in stored best win table
long m_lTableSize; // length of stored best win table
void CFileHeader::sync(Common::Serializer &s) {
s.syncBytes((byte *)m_szText, 80);
s.syncAsUint16LE(m_iHeaderSize);
s.syncAsUint16LE(m_iVersion);
s.syncAsUint16LE(m_iTableStones);
s.syncAsUint32LE(m_lTableSize);
}
/////////////////////////////////////////////////////////////////////////////
// theMnkApp:
// Just creating this application object runs the whole application.
//
//CMnkApp NEAR theMnkApp ;
/////////////////////////////////////////////////////////////////////////////
/*****************************************************************
*
* CMnkWindow
*
* FUNCTIONAL DESCRIPTION:
*
* Create the window with the appropriate style, size, menu, etc. ;
* it will be later revealed by CMnkApp::InitInstance(). Then
* create our splash screen object by opening and loading its DIB.
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
static HCURSOR hHourGlassCursor;
extern bool gbTurnSoundsOff;
//* CMnkWindow::CMnkWindow() -- mankala window constructor function
CMnkWindow::CMnkWindow() {
CDC* pDC = nullptr ; // device context for the screen
CString xpszWndClass ;
CDibDoc *xpDibDoc = nullptr ; // pointer to the background art DIB
CSize cMySize ;
HCURSOR hOldCursor;
m_bJustStarted = true;
m_bStartGame = true ; // set flag - game just starting
m_bRulesActive = false; //flag to indicate the rules scroll is unfurled.
// this flag is set only when rules are invoked via the F1 key.
m_bPlaySound = pGameParams->bSoundEffectsEnabled;
pGameParams->lScore = 0L;
gbTurnSoundsOff = GetPrivateProfileInt("Mankala", "MuteCrab", 0, INI_FILENAME) ; // Crab talks
hHourGlassCursor = LoadCursor(nullptr, IDC_WAIT);
SetCursor(hHourGlassCursor);
hOldCursor = LoadCursor(nullptr, IDC_ARROW);
if (pGameParams->bMusicEnabled)
m_pSound = new CSound(this, MIDI_BCKGND, SOUND_MIDI | SOUND_DONT_LOOP_TO_END);
// initialize default game options
m_iStartStones = GetPrivateProfileInt("Mankala", "StartStones", 3, INI_FILENAME) ; // 3 stones per pit
m_bComputer[1] = true ; // player 1 is computer (0 is human)
m_iTableStones = MAXTABLESTONES ;
m_bInitData = false ; // don't init table
m_iMaxDepth[0] = m_iMaxDepth[1] = 5 ; // minimax depth
m_iCapDepth[0] = m_iCapDepth[1] = 3 ; // capture depth
// *** debugging defaults
// m_bDumpPopulate = m_bDumpMoves = m_bDumpTree = true ;
// m_bInitData = true ;
// m_iTableStones = 3 ;
Common::strcpy_s(m_szDataDirectory, DATADIR) ; // data directory
// containing the bitmap files
// Define a special window class which traps double-clicks, is byte
// aligned to maximize BITBLT performance, and creates "owned" DCs
// rather than sharing the five system defined DCs which are not
// guaranteed to be available ; this adds a bit to our app size but
// avoids hangs/freezes/lockups.
xpszWndClass = AfxRegisterWndClass(CS_DBLCLKS |
CS_BYTEALIGNWINDOW | CS_OWNDC,
nullptr, nullptr, nullptr) ;
xpDibDoc = new CDibDoc() ; // create an object to hold our screen
if (! xpDibDoc) {
MFC::SetCursor(hOldCursor);
MFC::MessageBox(nullptr, "Abnormal MiniGame Termination", "Internal Error", MB_ICONSTOP);
delete this;
return;
} // ... and verify we got it
if (!(*xpDibDoc).OpenDocument(".\\ART\\MANKALA.BMP")) {
MFC::SetCursor(hOldCursor);
MFC::MessageBox(nullptr, "Cannot Open Background Bitmap. Please Check for file path and/or system resources. Terminating Game", "Open Error", MB_ICONEXCLAMATION | MB_OK) ;
delete xpDibDoc;
delete this;
return;
}
// next load in the actual DIB based artwork for screen
if (!(CMnkWindow::m_xpGamePalette = (*xpDibDoc).DetachPalette())) {
// grab its palette and save it for later use
MFC::SetCursor(hOldCursor);
MFC::MessageBox(nullptr, "Cannot acquire a non nullptr Palette. Game Terminated", "Palette Error", MB_OK | MB_ICONEXCLAMATION);
delete xpDibDoc;
delete this;
return;
}
delete xpDibDoc ; // now discard the splash screen
if ((pDC = GetDC())) { // get a device context for our window
// determine where to place the game window
// ... so it is centered on the screen
#ifndef _CODEVIEW
m_cMainRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
#else
m_cMainRect.SetRect(300, 300, 300 + GAME_WIDTH, 300 + GAME_HEIGHT);
#endif
m_cMainRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) >> 1 ;
m_cMainRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) >> 1 ;
m_cMainRect.right = m_cMainRect.left + GAME_WIDTH ;
m_cMainRect.bottom = m_cMainRect.top + GAME_HEIGHT ;
// Create the window as a POPUP so that no borders, title, or menu are
// present ; this is because the game's background art will fill the
// entire 640x480 area.
#define WSTYLE WS_POPUP|WS_CLIPCHILDREN
pDC->SelectPalette(CMnkWindow::m_xpGamePalette, false);
pDC->RealizePalette();
ReleaseDC(pDC);
pDC = nullptr ; // zero out context pointer
} else {
return;
}
if (!Create(xpszWndClass, "Boffo Games -- Mankala", WSTYLE,
m_cMainRect, nullptr, 0)) {
MFC::MessageBox(nullptr, "Cannot open window. Close some other windows to continue", "Error", MB_ICONSTOP) ;
delete this;
return ;
}
//
// Put up the splash screen so they have somethin' to look at:
//
ShowWindow(SW_SHOWNORMAL);
PaintBitmapObject(&m_cBmpMain, BMT_MAIN) ; // paint main screen bitmap
m_cBmpScroll.m_bSprite = true ; // scroll is a sprite
PaintBitmapObject(&m_cBmpScroll, BMT_SCROLL) ;
if (!pGameParams->bPlayingMetagame) {
switch (GetPrivateProfileInt("Mankala", "StartLevel", 3, INI_FILENAME)) { // minimax algorithm is the default ...
case 0:
m_eLevel[0] = m_eLevel[1] = LEV_RANDOM;
break;
case 1:
m_eLevel[0] = m_eLevel[1] = LEV_LOWEST;
break;
case 2:
m_eLevel[0] = m_eLevel[1] = LEV_HIGHEST;
break;
default:
case 3:
m_eLevel[0] = m_eLevel[1] = LEV_EVAL;
break;
}
} else {
/* ...unless you're playing Meta Game, Levels 2,3,4 are mapped
into nSKilllevel=0,1,2 respectively, and the initial number of
stones are 3,4, 5 respectively.
*/
switch (pGameParams->nSkillLevel) {
case SKILLLEVEL_LOW:
m_iStartStones = 3;
m_eLevel[0] = m_eLevel[1] = LEV_LOWEST;
break;
case SKILLLEVEL_MEDIUM :
m_iStartStones = 4;
m_eLevel[0] = m_eLevel[1] = LEV_HIGHEST;
break;
case SKILLLEVEL_HIGH :
m_iStartStones = 5;
m_eLevel[0] = m_eLevel[1] = LEV_EVAL;
break;
default :
m_iStartStones = 3;
m_eLevel[0] = m_eLevel[1] = LEV_EVAL;
break;
}
}
AllocatePits() ; // allocate pit objects
//CMnk::InitData() ; // initialize data tables
//otherwise test for flag before playing music.
if (pGameParams->bMusicEnabled && m_pSound) {
if (!(m_pSound->midiLoopPlaySegment(1004L, 34040L, 1004L, FMT_MILLISEC)))
MFC::MessageBox("Unable to Play Background Music", "Internal Error");
}
MFC::SetCursor(hOldCursor);
}
//* CMnkWindow::~CMnkWindow -- Mankala window destructor function
CMnkWindow::~CMnkWindow() {
}
/*****************************************************************
*
* OnPaint
*
* FUNCTIONAL DESCRIPTION:
*
* Repaint the screen whenever needed ; e.g. when uncovered by an
* overlapping window, when maximized from an icon, and when it the
* window is initially created. Ensures that the entire client area
* of the main screen window is repainted, not just the portion in the
* update region ; see PaintScreen() ;
*
* This routine is called whenever Windows sends a WM_PAINT message.
* Note that creating a CPaintDC automatically does a BeginPaint and
* an EndPaint call is done when it is destroyed at the end of this
* function. CPaintDC's constructor needs the window (this).
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
void CMnkWindow::OnPaint() {
PAINTSTRUCT lpPaint ;
InvalidateRect(nullptr, false) ; // invalidate the entire window
BeginPaint(&lpPaint) ; // bracket start of window update
PaintScreen() ; // repaint our window's content
EndPaint(&lpPaint) ; // bracket end of window update
}
/*****************************************************************
*
* OnCommand
*
* FUNCTIONAL DESCRIPTION:
*
* Process the QUIT and OKAY buttons when they are clicked.
*
* This function is called when a WM_COMMAND message is issued,
* typically in order to process control related activities.
*
* FORMAL PARAMETERS:
*
* wParam identifier for the button to be processed
* lParam type of message to be processed
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
// OnCommand
//
bool CMnkWindow::OnCommand(WPARAM wParam, LPARAM lParam) {
if (HIWORD(lParam) == BN_CLICKED)
// only want to look at button clicks
switch (wParam) {
case IDC_SCROLL:
if (!m_bInMenu) {
OptionsDialog() ; //bring up main menu.
(*this).SetFocus() ; // Reset focus back to the main window
} //end if !m_bInMenu
break ; // ... to force a repaint
default :
break;
}
return true ;
}
/*****************************************************************
*
* OnChar
*
* FUNCTIONAL DESCRIPTION:
*
....... * This function is called when keyboard input generates a character.
*
* (Add game-specific processing)
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMnkWindow::OnChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// TODO: Add your message handler code here and/or call default
CFrameWnd ::OnChar(nChar, nRepCnt, nFlags) ; // default action
}
void CMnkWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
int iRVal;
if (nChar == VK_F1) {
m_bRulesActive = false;
CRules cRulesDlg(this, RULES, m_xpGamePalette, pGameParams->bSoundEffectsEnabled ? RULES_NARRATION : nullptr) ;
CSound::waitWaveSounds();
if ((iRVal = cRulesDlg.DoModal()) == -1)
MessageBox("The Mankala Rules Text File Can't Be Opened", "Error Opening File");
m_bRulesActive = false;
} else if (nChar == VK_F2) {
OptionsDialog();
} else {
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
}
/*****************************************************************
*
* OnSysChar
*
* FUNCTIONAL DESCRIPTION:
*
* This function is called when keyboard input generates a
* system character.
*
* (Add game-specific processing)
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMnkWindow::OnSysChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// terminate game on ALT-Q
if ((nChar == 'q') && (nFlags & 0x2000))
PostMessage(WM_CLOSE, 0, 0) ; // same as clicking QUIT button
else
CFrameWnd ::OnSysChar(nChar, nRepCnt, nFlags) ; // default action
}
void CMnkWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// terminate game on ALT-F4
if ((nChar == VK_F4) && (nFlags & 0x2000))
PostMessage(WM_CLOSE, 0, 0) ; // same as clicking QUIT button
else
CFrameWnd ::OnSysChar(nChar, nRepCnt, nFlags) ; // default action
}
/*****************************************************************
*
* OnXXXXXX
*
* FUNCTIONAL DESCRIPTION:
*
* These functions are called when ever the corresponding WM_
* event message is generated for the mouse.
*
* (Add game-specific processing)
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMnkWindow::OnMouseMove(unsigned int nFlags, CPoint point) {
MFC::SetCursor(LoadCursor(nullptr, IDC_ARROW));
static int dxCursor = GetSystemMetrics(SM_CXCURSOR); //cursor size.
static int dyCursor = GetSystemMetrics(SM_CYCURSOR);
int iPlayer = 0, iPit = 0;
bool bFound;
CDC *pDC;
CRect crctPitBounds, crctTxt;
HLOCAL hlocShells;
char *npszShells;
CBmpObject *pcBmpObject;
/*
DETERMINE the current location of the mouse visavis the pit locations
if not in the main menu (scroll down mode).
*/
for (iPlayer = 0, bFound = false; !(m_bRulesActive || m_bInMenu) && iPlayer < 2; iPlayer++) {
for (iPit = -1; !bFound && iPit < NUMPITS ; bFound || ++iPit) {
pcBmpObject = &(m_xpcPits[iPlayer][iPit + 2]->m_cBmpObject) ;
crctPitBounds = CRect(pcBmpObject->m_cPosition, pcBmpObject->m_cSize);
if (crctPitBounds.PtInRect(point))
bFound = true ;
}
if (bFound) break;
}//end for
if (bFound && (m_cCurrentMove.m_iNumStones[iPlayer][iPit + 2])) {
if ((pDC = GetDC())) {
if ((hlocShells = MFC::LocalAlloc(GHND, 16))) {
npszShells = (char *)MFC::LocalLock(hlocShells);
Common::sprintf_s(npszShells, 16, "%2d shell%c", m_cCurrentMove.m_iNumStones[iPlayer][iPit + 2], (m_cCurrentMove.m_iNumStones[iPlayer][iPit + 2] > 1) ? 's' : 0x0);
if (m_pText) {
m_pText->RestoreBackground(pDC);
delete m_pText;
m_pText = nullptr;
}
/* the following values are arrived thru trial and error */
/* "Attach" the text to the cursor */
crctTxt.SetRect(point.x + dxCursor - 20, point.y + dyCursor - 20, point.x + dxCursor + 40, point.y + dyCursor + 10);
if ((m_pText = new CText(pDC, m_xpGamePalette, &crctTxt, JUSTIFY_CENTER))) {
m_pText->DisplayString(pDC, npszShells, 20, FW_NORMAL, CTEXT_COLOR);
}
MFC::LocalUnlock(hlocShells);
MFC::LocalFree(hlocShells);
}
ReleaseDC(pDC);
pDC = nullptr;
}
} else {
if (m_pText) {
pDC = GetDC();
m_pText->RestoreBackground(pDC);
delete m_pText;
m_pText = nullptr;
ReleaseDC(pDC);
pDC = nullptr;
}
}//end if bFound&&...
CFrameWnd ::OnMouseMove(nFlags, point) ; // default action
}
void CMnkWindow::OnLButtonDown(unsigned int nFlags, CPoint point) {
CRect rectTemp;
CSprite *pSpriteGlobe, *pSpriteChair;
CDC *pDC = nullptr;
HCURSOR hOldCur;
int i;
CSound *pChairWaveSound = nullptr,
*pGlobeWaveSound = nullptr;
const POINT pointGlobeSprite = {14, 30}; // Top-Left Corner of painting Globe animation.
const POINT pointChairSprite = {202, 21}; // Top-Left Corner to paint Chair animation.
const RECT InkWell = {534, 41, 584, 66};
const RECT NetShells = {324, 20, 384, 58};
const RECT Pails = {197, 81, 246, 165};
const RECT FishHook = {118, 34, 152, 98};
const RECT ArmChair = {110, 116, 174, 209};
const RECT TrvBrch = {580, 58, 618, 157};
const RECT Globe = {15, 104, 83, 218};
const RECT Chair = {266, 64, 317, 183};
//const RECT Chair={273,103,351,180};
const RECT Wheel = {427, 75, 500, 146};
/*Delete any cText objects upon Mouse Click */
if (m_pText) {
pDC = GetDC();
m_pText->RestoreBackground(pDC);
ReleaseDC(pDC);
pDC = nullptr;
delete m_pText;
m_pText = nullptr;
}
rectTemp.SetRect(NEWGAME_LOCATION_X, NEWGAME_LOCATION_Y,
NEWGAME_LOCATION_X + NEWGAME_WIDTH,
NEWGAME_LOCATION_Y + NEWGAME_HEIGHT);
if (rectTemp.PtInRect(point)) {
if ((pGameParams->bPlayingMetagame && !bPlayedGameOnce) || (!pGameParams->bPlayingMetagame)) {
bPlayedGameOnce = true;
StartGame();
}
} else {
if (pGameParams->bSoundEffectsEnabled) {
rectTemp.SetRect(Globe.left, Globe.top, Globe.right, Globe.bottom);
if (rectTemp.PtInRect(point)) {
CSound::waitWaveSounds();
sndPlaySound(nullptr, 0);
if ((pDC = GetDC())) {
if ((pSpriteGlobe = new CSprite())) {
hOldCur = MFC::SetCursor(hHourGlassCursor);
if (pSpriteGlobe->LoadCels(pDC, GLOBE_SPRITE, 25)) {
pSpriteGlobe->SetCel(-1);
pSpriteGlobe->LinkSprite();
if (pGameParams->bSoundEffectsEnabled)
pGlobeWaveSound = new CSound(this, POP,
SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE | SOUND_QUEUE);
for (i = 0; i < 25; i++) {
if (pGameParams->bSoundEffectsEnabled && i == 4) pGlobeWaveSound->play(); //begin playing sound at the 4th loop cycle, for sync.
if (!pSpriteGlobe->PaintSprite(pDC, pointGlobeSprite.x, pointGlobeSprite.y)) {
MFC::SetCursor(hOldCur);
MessageBox("Can't Conduct Animation Anymore", "Insufficient Memory");
break;
}
//MFC::Sleep(gSleepTime);
}
pSpriteGlobe->EraseSprite(pDC);
pSpriteGlobe->UnlinkSprite();
MFC::SetCursor(hOldCur);
} else {
MFC::SetCursor(hOldCur);
MessageBox("Unable to Play Animation", " Out Of Memory");
}
delete pSpriteGlobe;
}
ReleaseDC(pDC);
pDC = nullptr;
} // end if pDC
} // if rectTemp.SetRect(Globe.left,....) over.
else if ((point.x < Chair.right) && (point.x > Chair.left) && (point.y < Chair.bottom) && (point.y > Chair.top)) {
CSound::waitWaveSounds();
sndPlaySound(nullptr, 0);
if ((pDC = GetDC())) {
if ((pSpriteChair = new CSprite())) {
hOldCur = MFC::SetCursor(hHourGlassCursor);
if (pSpriteChair->LoadCels(pDC, CHAIR_SPRITE, 25)) {
pSpriteChair->SetCel(-1);
pSpriteChair->LinkSprite();
if (pGameParams->bSoundEffectsEnabled) {
pChairWaveSound = new CSound(this, HONK, SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE | SOUND_QUEUE);
// pChairWaveSound->play();
}
for (i = 0; i < 25; i++) {
if (pGameParams->bSoundEffectsEnabled && i == 7) pChairWaveSound->play(); //begin playing sound at the 4th loop cycle, for sync.
if (!pSpriteChair->PaintSprite(pDC, pointChairSprite.x, pointChairSprite.y)) {
MFC::SetCursor(hOldCur);
MessageBox("Can't paint anymore animation", "Insufficient Memory");
break;
}
MFC::Sleep(110); //10);
}
pSpriteChair->EraseSprite(pDC);
pSpriteChair->UnlinkSprite();
} else {
MFC::SetCursor(hOldCur);
MessageBox("Unable To Play Animation", "Insufficient Memory");
}//end if pSpriteChair->LoadCels...
MFC::SetCursor(hOldCur);
delete pSpriteChair;
}//end if pSpriteChair=new...
ReleaseDC(pDC);
pDC = nullptr;
} // end if pDC
} else { // elseif (point.x bSoundEffectsEnabled) { // play EasterEggs only if sounds enabled
rectTemp.SetRect(InkWell.left, InkWell.top, InkWell.right, InkWell.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(INK, SND_ASYNC);
rectTemp.SetRect(Wheel.left, Wheel.top, Wheel.right, Wheel.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(WHEEL, SND_ASYNC);
rectTemp.SetRect(NetShells.left, NetShells.top, NetShells.right, NetShells.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(NETSHELL, SND_ASYNC);
rectTemp.SetRect(Pails.left, Pails.top, Pails.right, Pails.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(PAILS, SND_ASYNC);
rectTemp.SetRect(FishHook.left, FishHook.top, FishHook.right, FishHook.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(FISHHOOK, SND_ASYNC);
rectTemp.SetRect(ArmChair.left, ArmChair.top, ArmChair.right, ArmChair.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(ARMCHAIR, SND_ASYNC);
rectTemp.SetRect(TrvBrch.left, TrvBrch.top, TrvBrch.right, TrvBrch.bottom);
if (rectTemp.PtInRect(point))
sndPlaySound(BROCHURE, SND_ASYNC);
}//end if pGameParams->...
}// end else .... rectTemp block.
}//END if pGameParams->bsoundEffectsEnabled
} // end else .
}
void CMnkWindow::OnLButtonUp(unsigned int nFlags, CPoint point) {
CDC *pDC = nullptr;
/*Delete any cText objects upon Mouse Click */
if (m_pText) {
if ((pDC = GetDC())) {
m_pText->RestoreBackground(pDC);
ReleaseDC(pDC);
pDC = nullptr;
delete m_pText;
m_pText = nullptr;
}//end if pDC.
}
// insert mouse button processing code here
if (nFlags & (MK_CONTROL | MK_SHIFT | MK_RBUTTON))
// if control key, shift key, or right button down
; // ignore the click
else {
#ifdef _DEMO
#define TOGGLE(x) ((x)=!(x))
CMove* xpcMove = &m_cCurrentMove;
int iPitToStartWith;
xpcMove->m_iPlayer = 0; //start from the human side.
UpdateWindow();
do {
while (!m_bGameOver && !m_bComputer[xpcMove->m_iPlayer] && !(CMnk *)this->SearchMove(xpcMove, iPitToStartWith)) {
(CMnk*)this->Move((CPit*)(m_xpcPits[xpcMove->m_iPlayer][iPitToStartWith + 2]));
SetCrabSign(false);
}
while (!m_bGameOver && m_bComputer[xpcMove->m_iPlayer] && !(CMnk *)this->SearchMove(xpcMove, iPitToStartWith)) {
(CMnk*)this->Move((CPit*)(m_xpcPits[xpcMove->m_iPlayer][iPitToStartWith + 2]));
SetCrabSign(true);
}
} while (!m_bGameOver);
#endif //_DEMO
AcceptClick(point) ; // process the mouse click
}
}
void CMnkWindow::OnLButtonDblClk(unsigned int nFlags, CPoint point) {
// insert mouse button processing code here
}
void CMnkWindow::OnMButtonDown(unsigned int nFlags, CPoint point) {
// insert mouse button processing code here
}
void CMnkWindow::OnMButtonUp(unsigned int nFlags, CPoint point) {
// insert mouse button processing code here
}
void CMnkWindow::OnMButtonDblClk(unsigned int nFlags, CPoint point) {
// insert mouse button processing code here
}
void CMnkWindow::OnRButtonDown(unsigned int nFlags, CPoint point) {
if (nFlags & MK_CONTROL) {
gbTurnSoundsOff = !gbTurnSoundsOff; //F12 is pressed, toggle sounds ON/OFF.
WritePrivateProfileString("Mankala", "MuteCrab", gbTurnSoundsOff ? "1" : "0", INI_FILENAME);
}
}
void CMnkWindow::OnRButtonUp(unsigned int nFlags, CPoint point) {
}
void CMnkWindow::OnRButtonDblClk(unsigned int nFlags, CPoint point) {
// insert mouse button processing code here
}
/*****************************************************************
*
* OnTimer
*
* FUNCTIONAL DESCRIPTION:
*
* Update sprite positions on the screen ; this is cyclic based on
* the interval specified when the timer was initiated.
*
* This function is called when ever the interval timer generates
* an event message ; i.e. the timer fires.
*
* FORMAL PARAMETERS:
*
* nIDEvent identifies the particular timer that fired
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
void CMnkWindow::OnTimer(uintptr nIDEvent) {
// CDC *m_xpcDC ;
if (nIDEvent == PITBUTTON_TIMER) {
PostMessage(WM_RBUTTONUP, 0, 0L);
MFC::KillTimer(this->m_hWnd, nIDEvent);
} else {
CFrameWnd::OnTimer(nIDEvent) ;
}
}
/*****************************************************************
*
* OnClose
*
* FUNCTIONAL DESCRIPTION:
*
* This function is called when a Close event is generated. For
* this sample application we need only kill our event timer ;
* The ExitInstance will handle releasing resources.
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
void CMnkWindow::OnClose() {
CBrush Brush;
CDC *pDC = nullptr;
CRect rctTmp;
char *npszTmp;
HLOCAL hlocTmp;
int level;
KillTimer(SPRITE_TIMER) ;
if ((pDC = GetDC())) { // paint black
if (Brush.CreateStockObject(BLACK_BRUSH)) {
rctTmp.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
pDC->FillRect(&rctTmp, &Brush);
}
ReleaseDC(pDC);
pDC = nullptr;
}
hlocTmp = MFC::LocalAlloc(LHND, 16);
npszTmp = (char *)MFC::LocalLock(hlocTmp);
Common::sprintf_s(npszTmp, 16, "%d", m_iStartStones);
WritePrivateProfileString("Mankala", "StartStones", npszTmp, INI_FILENAME);
switch (m_eLevel[0]) {
case LEV_RANDOM:
level = 0;
break;
case LEV_LOWEST:
level = 1;
break;
case LEV_HIGHEST:
level = 2;
break;
default:
case LEV_EVAL:
level = 3;
break;
}
Common::sprintf_s(npszTmp, 16, "%d", level);
WritePrivateProfileString("Mankala", "StartLevel", npszTmp, INI_FILENAME);
MFC::LocalUnlock(hlocTmp);
MFC::LocalFree(hlocTmp);
if (m_xpGamePalette != nullptr) {
m_xpGamePalette->DeleteObject();
delete m_xpGamePalette;
m_xpGamePalette = nullptr;
}
if (m_pText) {
delete (m_pText);
m_pText = nullptr;
}
ReleaseResources() ; // release game specific resources
CFrameWnd ::OnClose() ;
MFC::PostMessage(ghParentWnd, WM_PARENTNOTIFY, WM_DESTROY, MAKELPARAM(m_hWnd, 0));
}
/*****************************************************************
*
* InitInstance
*
* FUNCTIONAL DESCRIPTION:
*
* This routine is automatically called when the application is
* started.
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* bool Success (true) / Failure (false) status
*
****************************************************************/
/*
bool CMnkApp::InitInstance()
{
CMnkWindow *pMyMain ;
SetDialogBkColor() ; // hook gray dialogs (was default in MFC V1)
m_pMainWnd = pMyMain = m_xpcMnkWindow = new CMnkWindow() ;
// make the main window visible
m_pMainWnd->ShowWindow( m_nCmdShow ) ;
m_pMainWnd->UpdateWindow() ;
return(true) ;
}
*/
inline void FlushMouseMessages(HWND hWnd) {
MSG msg;
// find and remove all mouse events
while (PeekMessage(&msg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE));
}
LRESULT CMnkWindow::OnMCINotify(WPARAM wParam, LPARAM lParam) {
//CSound* pSnd;
CSound::OnMCIStopped(wParam, lParam);
return 0;
}
LRESULT CMnkWindow::OnMMIONotify(WPARAM wParam, LPARAM lParam) {
//CSound* pSnd;
CSound::OnMMIOStopped(wParam, lParam);
return 0;
}
// CMnkWindow message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CMnkWindow, CFrameWnd)
//{{AFX_MSG_MAP( CMnkWindow )
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_RBUTTONDBLCLK()
ON_WM_MOUSEMOVE()
ON_WM_CHAR()
ON_WM_SYSCHAR()
ON_WM_TIMER()
ON_WM_CLOSE()
ON_WM_SYSKEYDOWN()
ON_WM_KEYDOWN()
ON_MESSAGE(MM_MCINOTIFY, CMnkWindow::OnMCINotify)
ON_MESSAGE(MM_WOM_DONE, CMnkWindow::OnMMIONotify)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
} // namespace Mankala
} // namespace HodjNPodj
} // namespace Bagel