/* 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/boflib/misc.h" #include "bagel/hodjnpodj/hnplibs/stdafx.h" #include "bagel/hodjnpodj/wordsearch/wordsearch.h" #include "bagel/hodjnpodj/wordsearch/dialogs.h" #include "bagel/hodjnpodj/wordsearch/wordlist.h" #include "bagel/hodjnpodj/wordsearch/clongdlg.h" #include "bagel/hodjnpodj/hodjnpodj.h" namespace Bagel { namespace HodjNPodj { namespace WordSearch { extern CMainWSWindow *pMainGameWnd; extern HCURSOR hGameCursor; extern void PlayEasterEgg(CDC *pDC, CWnd *pWnd, CPalette *pPalette, const char *pszAnimFile, const char *pszSoundFile, int nNumCels, int nXLoc, int nYLoc, int nSleep, bool bPlaySound); CPalette *pGamePalette = nullptr; // Palette to be used throughout the game CBmpButton *pOptionButton = nullptr; // Option button object for getting to the options dialog char acWordChosen[WORDSPERLIST]; char acWordBack[WORDSPERLIST]; POINT ptCurrPosInGrid; POINT ptLastPosInGrid; POINT ptOrigPosInGrid; bool bResetGame; CDC *pOffScreenDC = nullptr; CPalette *pOldOffScreenPal = nullptr; CBitmap *pOffScreenBmp = nullptr; CBitmap *pOldOffScreenBmp = nullptr; CBitmap *pbmpSplashScreen = nullptr; CBitmap *pbmpAllLetters; int nCurrentLetter; CText *ptxtScore = nullptr; CString *astrGameList[WORDSPERLIST]; CString *astrGameListDisplay[WORDSPERLIST]; CText *atxtDisplayWord[WORDSPERLIST]; static CSound *pGameSound = nullptr; // Game theme song CSprite *pTimerSprite = nullptr; int nLastCell; unsigned int nTimerRes; long lCurrentTimer; int nWordsLeft; int nWordList; char acAlpha[26] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; extern const char *astrWLCat[NUMBEROFLISTS]; extern char acList[NUMBEROFLISTS][WORDSPERLIST][20]; /***************************************************************** * * CMainWSWindow * * FUNCTIONAL DESCRIPTION: * * Create the window with the appropriate style, size, menu, etc.; * it will be later revealed by CTheApp::InitInstance(). Then * create our splash screen object by opening and loading its DIB. * * FORMAL PARAMETERS: * * lUserAmount = initial amount of money that user starts with * defaults to zero * nRounds = the number of rounds to play, if 0 then not playing rounds * = defaults to zero * * IMPLICIT INPUT PARAMETERS: * * n/a * * IMPLICIT OUTPUT PARAMETERS: * * n/a * * RETURN VALUE: * * n/a * ****************************************************************/ CMainWSWindow::CMainWSWindow(HWND hCallingWnd, LPGAMESTRUCT lpGameStruct) : rNewGame(21, 3, 227, 20), rRefreshRect(0, 0, GAME_WIDTH, 385), rScore(190, 340, 610, 365) { CDC *pDC = nullptr; // device context for the screen CString WndClass; CSize mySize; bool bTestCreate; // bool for testing the creation of each button int x, y; CText atxtDisplayRow[NUMBEROFROWS]; BeginWaitCursor(); CPalette *pOldPal = nullptr; // 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. WndClass = AfxRegisterWndClass(CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_OWNDC, hGameCursor, nullptr, nullptr); // set the seed for the random number generator //srand( (unsigned)time( nullptr )); // initialize private members m_lpGameStruct = lpGameStruct; m_lpGameStruct->lScore = (WORDSPERLIST); m_hCallAppWnd = hCallingWnd; m_bWordsForwardOnly = false; // Initialize globals to point to class fields for (int i = 0; i < WORDSPERLIST; ++i) { astrGameList[i] = &_strGameList[i]; astrGameListDisplay[i] = &_strGameListDisplay[i]; atxtDisplayWord[i] = &_txtDisplayWord[i]; } // load splash screen pDC = GetDC(); // get a device context for our window pbmpSplashScreen = FetchBitmap(pDC, &pGamePalette, SPLASHSPEC); // get splash screen and game palettte pOldPal = pDC->SelectPalette(pGamePalette, false); // load game palette pDC->RealizePalette(); // realize game palette // set window coordinates to center game on screeen MainRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) >> 1; MainRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) >> 1; MainRect.right = MainRect.left + GAME_WIDTH; // determine where to place the game window MainRect.bottom = MainRect.top + GAME_HEIGHT; // ... so it is centered on the screen pDC->SelectPalette(pOldPal, false); // replace old palette ReleaseDC(pDC); // release our window context // Create the window as a POPUP so that no boarders, title, or menu are present; // this is because the game's background art will fill the entire 640x40 area. Create(WndClass, "Boffo Games - Word Search", WS_POPUP, MainRect, nullptr, 0); pDC = GetDC(); pOldPal = pDC->SelectPalette(pGamePalette, false); // load game palette pDC->RealizePalette(); // realize game palette pOptionButton = new CBmpButton; // create the Options button ASSERT(pOptionButton != 0); OptionRect.SetRect(OPTION_LEFT, OPTION_TOP, OPTION_LEFT + OPTION_WIDTH, OPTION_TOP + OPTION_HEIGHT); bTestCreate = pOptionButton->Create("Options", BS_OWNERDRAW | WS_CHILD | WS_VISIBLE, OptionRect, this, IDC_OPTION); ASSERT(bTestCreate != 0); // test for button's creation bTestCreate = pOptionButton->LoadBitmaps(SCROLLUP, SCROLLDOWN, SCROLLUP, SCROLLUP); ASSERT(bTestCreate != 0); // test for button's creation ShowWindow(SW_SHOWNORMAL); PaintBitmap(pDC, pGamePalette, pbmpSplashScreen, 0, 0, GAME_WIDTH, GAME_HEIGHT); pOffScreenBmp = new CBitmap(); pOffScreenDC = new CDC(); pOffScreenBmp->CreateCompatibleBitmap(pDC, GAME_WIDTH, GAME_HEIGHT); // create offscreen bitmap pOffScreenDC->CreateCompatibleDC(pDC); // create offscreen DC pOldOffScreenPal = pOffScreenDC->SelectPalette(pGamePalette, false); // load in game palette pOldOffScreenBmp = pOffScreenDC->SelectObject(pOffScreenBmp); // load in offscreen bitmap pOffScreenDC->RealizePalette(); // realize palette //pbmpAllLetters = FetchBitmap( pDC, nullptr, ALLLETTERS ); pbmpAllLetters = FetchBitmap(pOffScreenDC, nullptr, ALLLETTERS); ASSERT(pbmpAllLetters != 0); ptxtScore = new CText(pOffScreenDC, pGamePalette, &rScore, JUSTIFY_CENTER); pTimerSprite = new CSprite; pTimerSprite->SharePalette(pGamePalette); bTestCreate = pTimerSprite->LoadCels(pDC, TIMERSPRITE, TIMERSPRITECELS); ASSERT(bTestCreate); // test for sprite's creation pTimerSprite->SetPosition(FLOWER_X, FLOWER_Y); pTimerSprite->SetMasked(true); pTimerSprite->SetMobile(false); for (y = 0; y < WORDSPERLIST; y++) { arWordDisplay[y].SetRect(20, 50 + (y * 15), 170, 50 + (y * 15) + 14); _txtDisplayWord[y].SetupText(pOffScreenDC, pGamePalette, &arWordDisplay[y], JUSTIFY_RIGHT); } // paint splash screen to offscreen DC PaintBitmap(pOffScreenDC, pGamePalette, pbmpSplashScreen, 0, 0, GAME_WIDTH, GAME_HEIGHT); pDC->SelectPalette(pOldPal, false); // replace old palette ReleaseDC(pDC); // release our window context for (y = 0; y < NUMBEROFROWS; y++) { for (x = 0; x < NUMBEROFCOLS; x++) { arScreenGrid[y][x].SetRect(190 + (x * 21), 40 + (y * 21), 190 + (x * 21) + 20, 40 + (y * 21) + 21); } } if (m_lpGameStruct->bPlayingMetagame == true) { pDC = GetDC(); m_bShowWordList = false; if (m_lpGameStruct->nSkillLevel == SKILLLEVEL_LOW) { m_nTimeForGame = 75; m_bWordsForwardOnly = true; } if (m_lpGameStruct->nSkillLevel == SKILLLEVEL_MEDIUM) { m_nTimeForGame = 60; m_bWordsForwardOnly = true; } if (m_lpGameStruct->nSkillLevel == SKILLLEVEL_HIGH) { m_nTimeForGame = 60; m_bWordsForwardOnly = false; } // SetTimer( GAMETIMER, nTimerRes, nullptr ); long lTemp = (long)m_nTimeForGame * 1000; // nTimerRes = (unsigned int)( lTemp / ( TIMERSPRITECELS - 1) ); nTimerRes = (unsigned int)(lTemp / (TIMERSPRITECELS - 2)); nLastCell = -1; pTimerSprite->SetCel(nLastCell); ReleaseDC(pDC); } else { m_nTimeForGame = 300; // nTimerRes = (unsigned int)( (m_nTimeForGame * 1000) / ( TIMERSPRITECELS - 1) ); nTimerRes = (unsigned int)((m_nTimeForGame * 1000) / (TIMERSPRITECELS - 2)); nLastCell = -1; m_bShowWordList = true; m_bWordsForwardOnly = false; } //CreateNewGrid(); //SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE ); // create buttons m_bMouseCaptured = false; bResetGame = false; lCurrentTimer = 1; nWordsLeft = WORDSPERLIST; if (m_lpGameStruct->bMusicEnabled) { pGameSound = new CSound(this, GAME_THEME, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END); (*pGameSound).midiLoopPlaySegment(500, 31500, 0, FMT_MILLISEC); } // end if pGameSound EndWaitCursor(); if (m_lpGameStruct->bPlayingMetagame) { CreateNewGrid(); SplashScreen(); SetTimer(GAMETIMER, nTimerRes, nullptr); } } /***************************************************************** * * 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 SplashScreen(); * * 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 CMainWSWindow::OnPaint() { PAINTSTRUCT lpPaint; BeginPaint(&lpPaint); // bracket start of window update SplashScreen(); // repaint our window's content EndPaint(&lpPaint); // bracket end of window update } /***************************************************************** * * SplashScreen * * FUNCTIONAL DESCRIPTION: * * Repaint the background artwork, together with all sprites in the * sprite chain queue. The entire window is redrawn, rather than just * the updated area, to ensure that the sprites end up with the correct * background bitmaps saved for their image areas. * * FORMAL PARAMETERS: * * n/a * * IMPLICIT INPUT PARAMETERS: * * n/a * * IMPLICIT OUTPUT PARAMETERS: * * n/a * * RETURN VALUE: * * n/a * ****************************************************************/ void CMainWSWindow::SplashScreen() { CPalette *pOldPalette; CDC *pDC = GetDC(); // get a device context for the window ASSERT(pDC); pOldPalette = pDC->SelectPalette(pGamePalette, false); // load game palette pDC->RealizePalette(); // realize game palette pTimerSprite->SetCel(nLastCell); pTimerSprite->PaintSprite(pOffScreenDC, FLOWER_X, FLOWER_Y); pDC->BitBlt(0, 0, GAME_WIDTH, GAME_HEIGHT, pOffScreenDC, 0, 0, SRCCOPY); // Draw Word grid from offscreen pDC->SelectPalette(pOldPalette, false); // replace old palette ReleaseDC(pDC); // release the window's context } /***************************************************************** * * ResetGame * * FUNCTIONAL DESCRIPTION: * * Start a new game, and reset all arrays and buttons * * FORMAL PARAMETERS: * * n/a * * IMPLICIT INPUT PARAMETERS: * * aDealtArray, apHold * * IMPLICIT OUTPUT PARAMETERS: * * n/a * * RETURN VALUE: * * n/a * ****************************************************************/ void CMainWSWindow::ResetGame() { CDC *pDC; pDC = GetDC(); nLastCell = -1; KillTimer(GAMETIMER); lCurrentTimer = 1; CreateNewGrid(); SplashScreen(); if (m_nTimeForGame > 0) { long lTemp = (long)m_nTimeForGame * 1000; nTimerRes = (unsigned int)(lTemp / (TIMERSPRITECELS - 2)); SetTimer(GAMETIMER, nTimerRes, nullptr); } ReleaseDC(pDC); return; } void CMainWSWindow::CreateNewGrid() { int x, y, z; POINT ptSPos; int nDirection; char cSpace = ' '; char cTemp1[21]; char cTemp2[21]; bool bTemp1; bool bTemp2; int nWordLen; CText atxtDisplayRow[NUMBEROFROWS]; CString strTemp; int nIterations1 = 0; int nIterations2; CRect rDisplayCat(190, 365, 610, 385); CText txtDisplayCat(pOffScreenDC, pGamePalette, &rDisplayCat, JUSTIFY_CENTER); BeginWaitCursor(); nWordsLeft = WORDSPERLIST; nWordList = brand() % NUMBEROFLISTS; nIterations2 = 0; for (y = 0; y < WORDSPERLIST; y++) { if (nIterations2 > 500) { nWordList++; nWordList %= NUMBEROFLISTS; // keep nWordList in range of 0 to 49 nIterations2 = 0; } if (y == 0) { for (x = 0; x < NUMBEROFROWS; x++) { for (z = 0; z < NUMBEROFCOLS; z++) { acGameGrid[x][z] = '\0'; } } for (x = 0; x < WORDSPERLIST; x++) { _strGameList[x].Empty(); _strGameListDisplay[x].Empty(); } } for (x = 0; x < 21; x++) { cTemp1[x] = '\0'; cTemp2[x] = '\0'; } for (x = 0, z = 0; x < 20; x++, z++) { if (acList[nWordList][y][x] != cSpace) { cTemp1[z] = acList[nWordList][y][x]; } else z--; cTemp2[x] = acList[nWordList][y][x]; } _strGameList[y] = cTemp1; _strGameListDisplay[y] = cTemp2; nWordLen = strlen(cTemp1); bTemp1 = true; if (m_bWordsForwardOnly) nDirection = brand() % 4; else nDirection = brand() % 8; while (bTemp1) { nIterations1++; if (nIterations1 > 500) { nIterations1 = 0; nIterations2++; y = -1; bTemp1 = false; continue; } ptSPos.x = brand() % NUMBEROFCOLS; ptSPos.y = brand() % NUMBEROFROWS; if (m_bWordsForwardOnly) switch (nDirection) { case 0: nDirection = 0; break; case 1: nDirection = 1; break; case 2: nDirection = 2; break; case 3: nDirection = 7; break; } else { switch (nDirection) { case 0: nDirection = 2; break; case 1: nDirection = 3; break; case 2: nDirection = 4; break; case 3: nDirection = 5; break; case 4: nDirection = 6; break; case 5: nDirection = 7; break; case 6: nDirection = 0; break; case 7: nDirection = 1; break; } } switch (nDirection) { case 0: // going right if (ptSPos.x + nWordLen >= NUMBEROFCOLS) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y][ptSPos.x + z] != '\0') && (acGameGrid[ptSPos.y][ptSPos.x + z] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y][ptSPos.x + z] = cTemp1[z]; bTemp1 = false; } break; case 1: // going down and right if (ptSPos.x + nWordLen >= NUMBEROFCOLS) continue; if (ptSPos.y + nWordLen >= NUMBEROFROWS) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y + z][ptSPos.x + z] != '\0') && (acGameGrid[ptSPos.y + z][ptSPos.x + z] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y + z][ptSPos.x + z] = cTemp1[z]; bTemp1 = false; } break; case 2: // going down if (ptSPos.y + nWordLen >= NUMBEROFROWS) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y + z][ptSPos.x] != '\0') && (acGameGrid[ptSPos.y + z][ptSPos.x] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y + z][ptSPos.x] = cTemp1[z]; bTemp1 = false; } break; case 3: // going down and left if (ptSPos.y + nWordLen >= NUMBEROFROWS) continue; if (ptSPos.x - nWordLen < 0) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y + z][ptSPos.x - z] != '\0') && (acGameGrid[ptSPos.y + z][ptSPos.x - z] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y + z][ptSPos.x - z] = cTemp1[z]; bTemp1 = false; } break; case 4: // going left if (ptSPos.x - nWordLen < 0) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y][ptSPos.x - z] != '\0') && (acGameGrid[ptSPos.y][ptSPos.x - z] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y][ptSPos.x - z] = cTemp1[z]; bTemp1 = false; } break; case 5: // going up and left if (ptSPos.x - nWordLen < 0) continue; if (ptSPos.y - nWordLen < 0) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y - z][ptSPos.x - z] != '\0') && (acGameGrid[ptSPos.y - z][ptSPos.x - z] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y - z][ptSPos.x - z] = cTemp1[z]; bTemp1 = false; } break; case 6: // going up if (ptSPos.y - nWordLen < 0) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y - z][ptSPos.x] != '\0') && (acGameGrid[ptSPos.y - z][ptSPos.x] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y - z][ptSPos.x] = cTemp1[z]; bTemp1 = false; } break; case 7: // going up and right if (ptSPos.x + nWordLen >= NUMBEROFCOLS) continue; if (ptSPos.y - nWordLen < 0) continue; bTemp2 = true; for (z = 0; z < nWordLen; z++) { if ((acGameGrid[ptSPos.y - z][ptSPos.x + z] != '\0') && (acGameGrid[ptSPos.y - z][ptSPos.x + z] != cTemp1[z])) { bTemp2 = false; } } if (bTemp2 == false) continue; for (z = 0; z < nWordLen; z++) { acGameGrid[ptSPos.y - z][ptSPos.x + z] = cTemp1[z]; bTemp1 = false; } break; } } } for (y = 0; y < NUMBEROFROWS; y++) { for (x = 0; x < NUMBEROFCOLS; x++) { if (acGameGrid[y][x] == '\0') acGameGrid[y][x] = acAlpha[(brand() % 26)]; } } PaintBitmap(pOffScreenDC, pGamePalette, pbmpSplashScreen, 0, 0, GAME_WIDTH, GAME_HEIGHT); for (y = 0; y < NUMBEROFROWS; y++) { for (x = 0; x < NUMBEROFCOLS; x++) { int a, b; CRect rTemp; a = ((int)(acGameGrid[y][x]) - 65); b = 0; // 21 if grey letter rTemp.SetRect((a * 21), (b), ((a * 21) + 20), (b + 20)); BltMaskedBitmap(pOffScreenDC, pGamePalette, pbmpAllLetters, &rTemp, arScreenGrid[y][x].left, arScreenGrid[y][x].top); } } strTemp = "Category: "; strTemp += astrWLCat[nWordList]; txtDisplayCat.DisplayString(pOffScreenDC, strTemp, 16, FW_BOLD, DK_CYAN); //Shadowed char cDisplayTemp[32]; Common::sprintf_s(cDisplayTemp, "Words Left: %i", nWordsLeft); ptxtScore->DisplayString(pOffScreenDC, cDisplayTemp, 16, FW_BOLD, DK_CYAN); //Shadowed m_bNoGrid = false; EndWaitCursor(); return; } /***************************************************************** * * 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 // void CALLBACK lpfnOptionCallback(CWnd * pWnd) { // do the mini options dialog int nOption = 0; // return from the Options dialog CWSOptDlg dlgMiniOptDlg(pWnd, pGamePalette, IDD_MINIOPTIONS_DIALOG); dlgMiniOptDlg.SetInitialOptions(pMainGameWnd->m_nTimeForGame, pMainGameWnd->m_bShowWordList, pMainGameWnd->m_bWordsForwardOnly); nOption = dlgMiniOptDlg.DoModal(); if (nOption > 0) { if (nOption >= 20000) { pMainGameWnd->m_bWordsForwardOnly = false; nOption -= 20000; } else { pMainGameWnd->m_bWordsForwardOnly = true; nOption -= 10000; } if (nOption >= 2000) { pMainGameWnd->m_bShowWordList = false; nOption -= 2000; } else { pMainGameWnd->m_bShowWordList = true; nOption -= 1000; } pMainGameWnd->m_nTimeForGame = nOption; bResetGame = true; } return; } bool CMainWSWindow::OnCommand(WPARAM wParam, LPARAM lParam) { int nMainOption = 0; // return from the Options dialog if (HIWORD(lParam) == BN_CLICKED) { // only want to look at button clicks switch (wParam) { // Option button clicked, then put up the Options dialog case IDC_OPTION: pOptionButton->EnableWindow(false); bResetGame = false; KillTimer(GAMETIMER); if (m_lpGameStruct->bPlayingMetagame == true) { CMainMenu dlgMainOpts((CWnd *)this, pGamePalette, (NO_NEWGAME | NO_OPTIONS), lpfnOptionCallback, RULESFILE, (m_lpGameStruct->bSoundEffectsEnabled ? RULES_WAV : nullptr), m_lpGameStruct); nMainOption = dlgMainOpts.DoModal(); switch (nMainOption) { case IDC_OPTIONS_QUIT: // if Quit buttons was hit, quit PostMessage(WM_CLOSE, 0, 0); break; } } else { CMainMenu dlgMainOpts((CWnd *)this, pGamePalette, 0, lpfnOptionCallback, RULESFILE, (m_lpGameStruct->bSoundEffectsEnabled ? RULES_WAV : nullptr), m_lpGameStruct); nMainOption = dlgMainOpts.DoModal(); switch (nMainOption) { case IDC_OPTIONS_QUIT: // if Quit buttons was hit, quit PostMessage(WM_CLOSE, 0, 0); break; case IDC_OPTIONS_NEWGAME: // reset the game and start a new hand bResetGame = true; break; } } pOptionButton->EnableWindow(true); // // Check to see if the music state was changed and adjust to match it // if ((m_lpGameStruct->bMusicEnabled == false) && (pGameSound != nullptr)) { if (pGameSound->playing()) pGameSound->stop(); } else if (m_lpGameStruct->bMusicEnabled) { if (pGameSound == nullptr) { pGameSound = new CSound(this, GAME_THEME, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END); } if (pGameSound != nullptr) { if (!pGameSound->playing()) (*pGameSound).midiLoopPlaySegment(500, 31500, 0, FMT_MILLISEC); } } if (bResetGame && !m_lpGameStruct->bPlayingMetagame) ResetGame(); else if ((m_nTimeForGame > 0) && (m_bNoGrid == false)) { long lTemp = (long)m_nTimeForGame * 1000; nTimerRes = (unsigned int)(lTemp / (TIMERSPRITECELS - 1)); // nTimerRes = ( ( m_nTimeForGame * 1000 ) / TIMERSPRITECELS ); SetTimer(GAMETIMER, nTimerRes, nullptr); } break; } } (*this).SetFocus(); // Reset focus back to the main window return true; } void CMainWSWindow::OnLButtonDown(unsigned int nFlags, CPoint point) { CDC *pDC = nullptr; CPalette *pTempPal = nullptr; CRect rChicken, rPig, rCow, rFlower; int x, y; rChicken.SetRect(CHICKEN_X, CHICKEN_Y, CHICKEN_X + CHICKEN_DX, CHICKEN_Y + CHICKEN_DY); rPig.SetRect(PIG_X, PIG_Y, PIG_X + PIG_DX, PIG_Y + PIG_DY); rCow.SetRect(COW_X, COW_Y, COW_X + COW_DX, COW_Y + COW_DY); rFlower.SetRect(FLOWER_X, FLOWER_Y, FLOWER_X + FLOWER_DX, FLOWER_Y + FLOWER_DY); if (m_lpGameStruct->bPlayingMetagame == false) { if (rNewGame.PtInRect(point)) { SetCapture(); m_bMouseCaptured = true; } } pDC = GetDC(); if (rChicken.PtInRect(point)) { CSound::waitWaveSounds(); sndPlaySound(nullptr, 0); PlayEasterEgg(pDC, (CWnd *)this, pGamePalette, CHICKEN_ANIM, CHICKEN_WAV, NUM_CHICKEN_CELS, CHICKEN_X, CHICKEN_Y, CHICKEN_SLEEP, (*m_lpGameStruct).bSoundEffectsEnabled); } else if (rCow.PtInRect(point)) { CSound::waitWaveSounds(); sndPlaySound(nullptr, 0); PlayEasterEgg(pDC, (CWnd *)this, pGamePalette, COW_ANIM, COW_WAV, NUM_COW_CELS, COW_X, COW_Y, COW_SLEEP, (*m_lpGameStruct).bSoundEffectsEnabled); } else if (rPig.PtInRect(point) && (*m_lpGameStruct).bSoundEffectsEnabled) { CSound::waitWaveSounds(); sndPlaySound(nullptr, 0); sndPlaySound(PIG_WAV, SND_ASYNC); } else if (rFlower.PtInRect(point) && (*m_lpGameStruct).bSoundEffectsEnabled) { CSound::waitWaveSounds(); sndPlaySound(nullptr, 0); sndPlaySound(FLOWER_WAV, SND_ASYNC); } ReleaseDC(pDC); if (m_bNoGrid) return; for (y = 0; y < NUMBEROFROWS; y++) { for (x = 0; x < NUMBEROFCOLS; x++) { if (arScreenGrid[y][x].PtInRect(point)) { CBrush cBrush((COLORREF)RGB(0, 255, 255)); pDC = GetDC(); pTempPal = pDC->SelectPalette(pGamePalette, false); SetCapture(); pDC->RealizePalette(); m_bMouseCaptured = true; ptCurrPosInGrid.x = x; ptCurrPosInGrid.y = y; ptOrigPosInGrid.x = x; ptOrigPosInGrid.y = y; ptLastPosInGrid.x = x; ptLastPosInGrid.y = y; pDC->FrameRect(&arScreenGrid[y][x], &cBrush); pDC->SelectPalette(pTempPal, false); ReleaseDC(pDC); } } } CWnd::OnLButtonDown(nFlags, point); } void CMainWSWindow::OnMouseMove(unsigned int nFlags, CPoint point) { CDC *pDC = nullptr; CBrush cBrush((COLORREF)RGB(0, 255, 255)); CPalette *pTempPal = nullptr; CRgn FrameRgn; POINT aptFrame[6]; int x, y; int nCurrentX, nCurrentY; SetCursor(LoadCursor(nullptr, IDC_ARROW)); // Refresh cursor object if (m_bNoGrid) return; if (m_bMouseCaptured) { for (int i = 0; i < 6; ++i) aptFrame[i].x = aptFrame[i].y = 0; for (y = 0; y < NUMBEROFROWS; y++) { for (x = 0; x < NUMBEROFCOLS; x++) { if (arScreenGrid[y][x].PtInRect(point)) { ptCurrPosInGrid.x = x; ptCurrPosInGrid.y = y; } } } if ((ptCurrPosInGrid.x != ptLastPosInGrid.x) || (ptCurrPosInGrid.y != ptLastPosInGrid.y)) { for (x = 0; x < WORDSPERLIST; x++) acWordChosen[x] = '\0'; // draw vertical box if (ptCurrPosInGrid.x == ptOrigPosInGrid.x) { if (ptCurrPosInGrid.y >= ptOrigPosInGrid.y) { // start from the top and go down aptFrame[0].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[1].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[2].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[4].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[4].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; // put the selected word into acWordChosen for (y = ptOrigPosInGrid.y; y <= ptCurrPosInGrid.y; y++) { acWordChosen[ y - ptOrigPosInGrid.y ] = acGameGrid[y][ptOrigPosInGrid.x]; } } else { // start from the bottom and go up aptFrame[0].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[1].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[2].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[4].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[4].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; // put the selected word into acWordChosen for (y = ptCurrPosInGrid.y; y <= ptOrigPosInGrid.y; y++) { acWordChosen[ y - ptCurrPosInGrid.y ] = acGameGrid[y][ptCurrPosInGrid.x]; } } } // draw horizontal box if (ptCurrPosInGrid.y == ptOrigPosInGrid.y) { if (ptCurrPosInGrid.x >= ptOrigPosInGrid.x) { // start from the left and go right aptFrame[0].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[1].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[2].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[4].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[4].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; // put the selected word into acWordChosen for (x = ptOrigPosInGrid.x; x <= ptCurrPosInGrid.x; x++) { acWordChosen[ x - ptOrigPosInGrid.x ] = acGameGrid[ptOrigPosInGrid.y][x]; } } else { // start from the right and go left aptFrame[0].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[1].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[2].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[4].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[4].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; // put the selected word into acWordChosen for (x = ptCurrPosInGrid.x; x <= ptOrigPosInGrid.x; x++) { acWordChosen[ x - ptCurrPosInGrid.x ] = acGameGrid[ptCurrPosInGrid.y][x]; } } } nCurrentX = ptCurrPosInGrid.x - ptOrigPosInGrid.x; nCurrentY = ptCurrPosInGrid.y - ptOrigPosInGrid.y; if ((nCurrentX - nCurrentY) == 0) { // diagnol with slope -1 if (ptCurrPosInGrid.x > ptOrigPosInGrid.x) { aptFrame[0].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[1].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[2].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; aptFrame[4].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[4].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; for (x = ptOrigPosInGrid.x, y = ptOrigPosInGrid.y; x <= ptCurrPosInGrid.x; x++, y++) { acWordChosen[ x - ptOrigPosInGrid.x ] = acGameGrid[y][x]; } } else { aptFrame[0].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[1].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[2].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; aptFrame[4].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[4].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; for (x = ptCurrPosInGrid.x, y = ptCurrPosInGrid.y; x <= ptOrigPosInGrid.x; x++, y++) { acWordChosen[ x - ptCurrPosInGrid.x ] = acGameGrid[y][x]; } } } else { if ((nCurrentX + nCurrentY) == 0) { // diagnol with slope 1 if (ptCurrPosInGrid.x > ptOrigPosInGrid.x) { aptFrame[0].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[1].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[2].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; aptFrame[4].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[4].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; for (x = ptOrigPosInGrid.x, y = ptOrigPosInGrid.y; x <= ptCurrPosInGrid.x; x++, y--) { acWordChosen[ x - ptOrigPosInGrid.x ] = acGameGrid[y][x]; } } else { aptFrame[0].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[0].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].top; aptFrame[1].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].left; aptFrame[1].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[2].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[2].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].top; aptFrame[3].x = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].right; aptFrame[3].y = arScreenGrid[ptOrigPosInGrid.y][ptOrigPosInGrid.x].bottom; aptFrame[4].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].right; aptFrame[4].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; aptFrame[5].x = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].left; aptFrame[5].y = arScreenGrid[ptCurrPosInGrid.y][ptCurrPosInGrid.x].bottom; for (x = ptCurrPosInGrid.x, y = ptCurrPosInGrid.y; x <= ptOrigPosInGrid.x; x++, y--) { acWordChosen[ x - ptCurrPosInGrid.x ] = acGameGrid[y][x]; } } } } // redraw only what's necessary RedrawWindow(&rRefreshRect); pDC = GetDC(); pTempPal = pDC->SelectPalette(pGamePalette, false); pDC->RealizePalette(); FrameRgn.CreatePolygonRgn(aptFrame, 6, WINDING); pDC->FrameRgn(&FrameRgn, &cBrush, 1, 1); } ptLastPosInGrid.x = ptCurrPosInGrid.x; ptLastPosInGrid.y = ptCurrPosInGrid.y; } if (pDC != nullptr) { pDC->SelectPalette(pTempPal, false); ReleaseDC(pDC); } CWnd::OnMouseMove(nFlags, point); } void CMainWSWindow::OnLButtonUp(unsigned int nFlags, CPoint point) { int x, y; POINT ptTemp; bool bFoundWord = false; int nWordNum = 0; int a, b; CRect rTemp; if (m_bMouseCaptured) { m_bMouseCaptured = false; ReleaseCapture(); if (rNewGame.PtInRect(point) && !m_lpGameStruct->bPlayingMetagame) { ResetGame(); return; } if (m_bNoGrid) return; for (x = 0; x < WORDSPERLIST; x++) acWordBack[x] = '\0'; if (acWordChosen[0] != '\0') { for (x = 0, y = (strlen(acWordChosen) - 1); y >= 0 ; x++, y--) acWordBack[x] = acWordChosen[y]; for (x = 0; x < WORDSPERLIST; x++) { bFoundWord = false; nWordNum = 0; if (_strGameList[x].IsEmpty() == false) { if (_strGameList[x] == acWordChosen) { bFoundWord = true; nWordNum = x; break; } else { if (_strGameList[x] == acWordBack) { bFoundWord = true; nWordNum = x; break; } } } } if (bFoundWord) { if ((*m_lpGameStruct).bSoundEffectsEnabled) { sndPlaySound(nullptr, 0); sndPlaySound(FIND_WAV, SND_ASYNC); } _strGameList[nWordNum].Empty(); nWordsLeft--; char cDisplayTemp[32]; Common::sprintf_s(cDisplayTemp, "Words Left: %i", nWordsLeft); ptxtScore->DisplayString(pOffScreenDC, cDisplayTemp, 16, FW_BOLD, DK_CYAN); ptTemp.x = ptOrigPosInGrid.x; ptTemp.y = ptOrigPosInGrid.y; a = ((int)(acGameGrid[ptTemp.y][ptTemp.x]) - 65); b = 22; rTemp.SetRect((a * 21), (b), ((a * 21) + 20), (b + 20)); BltMaskedBitmap(pOffScreenDC, pGamePalette, pbmpAllLetters, &rTemp, arScreenGrid[ptTemp.y][ptTemp.x].left, arScreenGrid[ptTemp.y][ptTemp.x].top); do { if ((ptCurrPosInGrid.y == ptOrigPosInGrid.y) && (ptCurrPosInGrid.x > ptOrigPosInGrid.x)) { // word direction right ptTemp.x++; } else { if ((ptCurrPosInGrid.y > ptOrigPosInGrid.y) && (ptCurrPosInGrid.x > ptOrigPosInGrid.x)) { // word direction down and right ptTemp.x++; ptTemp.y++; } else { if ((ptCurrPosInGrid.y > ptOrigPosInGrid.y) && (ptCurrPosInGrid.x == ptOrigPosInGrid.x)) { // word direction down ptTemp.y++; } else { if ((ptCurrPosInGrid.y > ptOrigPosInGrid.y) && (ptCurrPosInGrid.x < ptOrigPosInGrid.x)) { // word direction down and left ptTemp.x--; ptTemp.y++; } else { if ((ptCurrPosInGrid.y == ptOrigPosInGrid.y) && (ptCurrPosInGrid.x < ptOrigPosInGrid.x)) { // word direction left ptTemp.x--; } else { if ((ptCurrPosInGrid.y < ptOrigPosInGrid.y) && (ptCurrPosInGrid.x < ptOrigPosInGrid.x)) { // word direction up and left ptTemp.x--; ptTemp.y--; } else { if ((ptCurrPosInGrid.y < ptOrigPosInGrid.y) && (ptCurrPosInGrid.x == ptOrigPosInGrid.x)) { // word direction up ptTemp.y--; } else { if ((ptCurrPosInGrid.y < ptOrigPosInGrid.y) && (ptCurrPosInGrid.x > ptOrigPosInGrid.x)) { // word direction up and right ptTemp.x++; ptTemp.y--; } } } } } } } } a = ((int)(acGameGrid[ptTemp.y][ptTemp.x]) - 65); b = 22; rTemp.SetRect((a * 21), (b), ((a * 21) + 20), (b + 20)); BltMaskedBitmap(pOffScreenDC, pGamePalette, pbmpAllLetters, &rTemp, arScreenGrid[ptTemp.y][ptTemp.x].left, arScreenGrid[ptTemp.y][ptTemp.x].top); } while ((ptTemp.x != ptCurrPosInGrid.x) || (ptTemp.y != ptCurrPosInGrid.y)); } // end if bWordFound else { if ((*m_lpGameStruct).bSoundEffectsEnabled) { sndPlaySound(nullptr, 0); sndPlaySound(NOPE_WAV, SND_SYNC); sndPlaySound(TRYAGAIN_WAV, SND_SYNC); } } // end else } RedrawWindow(&rRefreshRect); if (nWordsLeft == 0) { CMsgDlg msgGameOver((CWnd *)this, pGamePalette); KillTimer(GAMETIMER); m_bNoGrid = true; if ((*m_lpGameStruct).bSoundEffectsEnabled) { sndPlaySound(nullptr, 0); sndPlaySound(ALLFOUND_WAV, SND_SYNC); // play sound } msgGameOver.SetInitialOptions(1, nWordsLeft); msgGameOver.DoModal(); if (m_lpGameStruct->bPlayingMetagame) PostMessage(WM_CLOSE, 0, 0); } } CWnd::OnLButtonUp(nFlags, point); } void CMainWSWindow::OnRButtonDown(unsigned int nFlags, CPoint point) { if (m_bShowWordList) { CLongDialog dlgWordlist((CWnd *)this, pGamePalette, "OK", "Word", "list"); dlgWordlist.DoModal(); } } void CMainWSWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) { // terminate app on ALT_F4 // if ((nChar == VK_F4) && (nFlags & 0x2000)) { PostMessage(WM_CLOSE, 0, 0); } else { // default action CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags); } } void CMainWSWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) { CRules dlgRules((CWnd *)this, RULESFILE, pGamePalette, nullptr); switch (nChar) { case VK_F1: pOptionButton->ShowWindow(SW_HIDE); // UpdateWindow(); CSound::waitWaveSounds(); dlgRules.DoModal(); // invoke the help dialog box pOptionButton->ShowWindow(SW_SHOWNORMAL); break; case VK_F2: SendMessage(WM_COMMAND, IDC_OPTION, BN_CLICKED); break; default: CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags); break; } return; } void CMainWSWindow::OnTimer(uintptr nWhichTimer) { if (nWhichTimer == GAMETIMER) { if (lCurrentTimer == (TIMERSPRITECELS - 1)) { //> ( TIMERSPRITECELS - 1 ) ) { CDC *pDC = GetDC(); CMsgDlg msgGameOver((CWnd *)this, pGamePalette); KillTimer(GAMETIMER); nLastCell++; pTimerSprite->SetCel(nLastCell); pTimerSprite->PaintSprite(pDC, FLOWER_X, FLOWER_Y); pTimerSprite->SetCel(nLastCell); pTimerSprite->PaintSprite(pOffScreenDC, FLOWER_X, FLOWER_Y); ReleaseDC(pDC); m_bNoGrid = true; if ((*m_lpGameStruct).bSoundEffectsEnabled) { sndPlaySound(nullptr, 0); sndPlaySound(TIMEOUT_WAV, SND_SYNC); // play sound } msgGameOver.SetInitialOptions(2, nWordsLeft); msgGameOver.DoModal(); if (m_lpGameStruct->bPlayingMetagame) PostMessage(WM_CLOSE, 0, 0); else RedrawWindow(); } else { CDC *pDC = GetDC(); lCurrentTimer++; nLastCell++; if ((*m_lpGameStruct).bSoundEffectsEnabled) { sndPlaySound(nullptr, 0); sndPlaySound(TICK_WAV, SND_ASYNC); } pTimerSprite->SetCel(nLastCell); pTimerSprite->PaintSprite(pDC, FLOWER_X, FLOWER_Y); pTimerSprite->SetCel(nLastCell); pTimerSprite->PaintSprite(pOffScreenDC, FLOWER_X, FLOWER_Y); ReleaseDC(pDC); } } return; } /***************************************************************** * * 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] * ****************************************************************/ bool CMainWSWindow::OnEraseBkgnd(CDC *pDC) { // eat this return true; } void CMainWSWindow::OnActivate(unsigned int nState, CWnd *pWndOther, bool bMinimized) { if (!bMinimized) switch (nState) { case WA_ACTIVE: case WA_CLICKACTIVE: InvalidateRect(nullptr, false); break; } return; } /***************************************************************** * * 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 CMainWSWindow::OnClose() { CDC *pDC = GetDC(); CRect rctFillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); CBrush Brush(RGB(0, 0, 0)); pDC->FillRect(&rctFillRect, &Brush); ReleaseDC(pDC); ReleaseResources(); CFrameWnd ::OnClose(); } /***************************************************************** * * OnDestroy * * FUNCTIONAL DESCRIPTION: * * This function is called when after the window has been destroyed. * For poker, we post a message bak to the calling app to tell it * that the user has quit the game, and therefore the app can unload * this DLLL * * FORMAL PARAMETERS: * * n/a * * IMPLICIT INPUT PARAMETERS: * * n/a * * IMPLICIT OUTPUT PARAMETERS: * * n/a * * RETURN VALUE: * * n/a * ****************************************************************/ void CMainWSWindow::OnDestroy() { // send a message to the calling app to tell it the user has quit the game m_lpGameStruct->lScore = (WORDSPERLIST - nWordsLeft); MFC::PostMessage(m_hCallAppWnd, WM_PARENTNOTIFY, WM_DESTROY, (LPARAM)m_lpGameStruct); m_lpGameStruct = nullptr; CFrameWnd::OnDestroy(); } /***************************************************************** * * ReleaseResources * * FUNCTIONAL DESCRIPTION: * * Release all resources that were created and retained during the * course of the game. This includes sprites in the sprite chain, * the game color palette, and button controls. * * FORMAL PARAMETERS: * * n/a * * IMPLICIT INPUT PARAMETERS: * * n/a * * IMPLICIT OUTPUT PARAMETERS: * * n/a * * RETURN VALUE: * * n/a * ****************************************************************/ void CMainWSWindow::ReleaseResources() { if (pGameSound != nullptr) { delete pGameSound; // delete the game theme song pGameSound = nullptr; } CSound::clearSounds(); if (pTimerSprite != nullptr) delete pTimerSprite; if (pOldOffScreenBmp != nullptr) pOffScreenDC->SelectObject(pOldOffScreenBmp); if (pOldOffScreenPal != nullptr) pOffScreenDC->SelectPalette(pOldOffScreenPal, false); if (pOffScreenDC->m_hDC != nullptr) { pOffScreenDC->DeleteDC(); delete pOffScreenDC; } if (pOffScreenBmp != nullptr) { pOffScreenBmp->DeleteObject(); delete pOffScreenBmp; } if (pbmpSplashScreen != nullptr) { pbmpSplashScreen->DeleteObject(); delete pbmpSplashScreen; } if (pbmpAllLetters != nullptr) { pbmpAllLetters->DeleteObject(); delete pbmpAllLetters; } if (ptxtScore != nullptr) delete ptxtScore; if (pGamePalette != nullptr) { pGamePalette->DeleteObject(); // release the game color palette delete pGamePalette; } delete pOptionButton; // release the buttons we used return; } /***************************************************************** * * FlushInputEvents * * FUNCTIONAL DESCRIPTION: * * Remove all keyboard and mouse related events from the message * so that they will not be sent to us for processing; i.e. this * flushes keyboard type ahead and extra mouse clicks and movement. * * FORMAL PARAMETERS: * * n/a * * IMPLICIT INPUT PARAMETERS: * * n/a * * IMPLICIT OUTPUT PARAMETERS: * * n/a * * RETURN VALUE: * * n/a * ****************************************************************/ void CMainWSWindow::FlushInputEvents() { MSG msg; while (true) { // find and remove all keyboard events if (!PeekMessage(&msg, nullptr, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) break; } while (true) { // find and remove all mouse events if (!PeekMessage(&msg, nullptr, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) break; } } //////////// Additional Sound Notify routines ////////////// LRESULT CMainWSWindow::OnMCINotify(WPARAM wParam, LPARAM lParam) { CSound *pSound; pSound = CSound::OnMCIStopped(wParam, lParam); if (pSound != nullptr) OnSoundNotify(pSound); return 0; } LRESULT CMainWSWindow::OnMMIONotify(WPARAM wParam, LPARAM lParam) { CSound *pSound; pSound = CSound::OnMMIOStopped(wParam, lParam); if (pSound != nullptr) OnSoundNotify(pSound); return 0; } void CMainWSWindow::OnSoundNotify(CSound *pSound) { // // Add your code to process explicit notification of a sound "done" event here. // pSound is a pointer to a CSound object for which you requested SOUND_NOTIFY. // } // CMainWSWindow message map: // Associate messages with member functions. // BEGIN_MESSAGE_MAP(CMainWSWindow, CFrameWnd) //{{AFX_MSG_MAP( CMainWSWindow ) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_CLOSE() ON_WM_DESTROY() ON_WM_TIMER() ON_WM_ERASEBKGND() ON_WM_KEYDOWN() ON_WM_SYSKEYDOWN() ON_WM_ACTIVATE() ON_MESSAGE(MM_MCINOTIFY, CMainWSWindow::OnMCINotify) ON_MESSAGE(MM_WOM_DONE, CMainWSWindow::OnMMIONotify) //}}AFX_MSG_MAP END_MESSAGE_MAP() void PlayEasterEgg(CDC *pDC, CWnd *pWnd, CPalette *pPalette, const char *pszAnimFile, const char *pszSoundFile, int nNumCels, int nXLoc, int nYLoc, int nSleep, bool bPlaySound) { CSprite *pSprite = nullptr; CSound *pEffect = nullptr; bool bSuccess; int i; pSprite = new CSprite; (*pSprite).SharePalette(pPalette); bSuccess = (*pSprite).LoadCels(pDC, pszAnimFile, nNumCels); if (!bSuccess) { delete pSprite; return; } (*pSprite).SetMasked(false); (*pSprite).SetMobile(false); if (bPlaySound) { pEffect = new CSound(pWnd, pszSoundFile, // Load up the sound file as a SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE | SOUND_AUTODELETE); //...Wave file, to delete itself } if (pEffect != nullptr) { bSuccess = (*pEffect).play(); if (!bSuccess) delete pEffect; } (*pSprite).SetCel(-1); // nNumCels for (i = 0; i < nNumCels; i++) { (*pSprite).PaintSprite(pDC, nXLoc, nYLoc); Sleep(nSleep); } if (pSprite != nullptr) delete pSprite; } // end PlayEasterEgg } // namespace WordSearch } // namespace HodjNPodj } // namespace Bagel