Files
2026-02-02 04:50:13 +01:00

1494 lines
40 KiB
C++

/* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/hnplibs/bitmaps.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/hodjnpodj/hnplibs/mainmenu.h"
#include "bagel/hodjnpodj/hnplibs/cmessbox.h"
#include "bagel/hodjnpodj/hnplibs/rules.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/life/resource.h"
#include "bagel/hodjnpodj/life/game.h"
#include "bagel/hodjnpodj/life/life.h"
#include "bagel/hodjnpodj/life/usercfg.h"
#include "bagel/hodjnpodj/hodjnpodj.h"
namespace Bagel {
namespace HodjNPodj {
namespace Life {
#define RULES_TXT "life.txt" // rules text file
#define RULES_WAV ".\\sound\\rllf.wav" // rules narration
#define MIDI_SOUND ".\\SOUND\\life.mid" // background music
//
// Win/Lose conditions
//
#define WIN 1
#define LOSE 0
// Globals!
int nSpeed, // Speed between evolutions
nCountDown, // Counts before an evolution
nLife, // Num of lives given at game start
nPlace; // Profile holder for PrePlace bool
int nTurnCounter, // Counts num of years before end of game
nLifeCounter; // Counts num of lives left to place
bool bPrePlaceColonies, // Whether they want to pre-place some (default for meta)
bIsInfiniteLife, // Tells if num of lives is set to infi
bIsInfiniteTurns; // Tells if num of turns is set to infi
bool gbNewGame; // only used from options dialog
CColorButton *pEvolveButton;
extern CMainWindow *gMainWnd; // Allows me to pass main window New_Game
// messages from GameOver.cpp
CPalette *pGamePalette = nullptr; // Used everywhere for ref
CSprite *pScrollSprite = nullptr; // Commands button
CSprite *pCalendarSprite = nullptr; // Blank calendar
HWND hWndParent;
void CALLBACK GetGameParams(CWnd *pParentWnd);
/*****************************************************************
*
* CMainWindow
*
* FUNCTIONAL DESCRIPTION:
*
* CMainWindow constructor:
* 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:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
CMainWindow::CMainWindow(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CString WndClass;
CDC *pDC;
CRect MainRect,
QuitRect,
CommandRect,
OkayRect,
EvolveRect;
CDibDoc *pDibDoc; // Used to get game palette
bool bAssertCheck; // Assertion check when getting game pal
/*******************************************
* Handle the meta-game structure settings. *
*******************************************/
m_lpGameStruct = lpGameInfo;
initStatics();
/********************************
* Set the global window handle. *
********************************/
m_hCallAppWnd = hParentWnd;
/********************************************************************
* Get palette from background art that will be used for all related *
* game art work. *
********************************************************************/
pDibDoc = new CDibDoc();
bAssertCheck = (*pDibDoc).OpenDocument(SPLASHSPEC);
ASSERT(bAssertCheck);
pGamePalette = (*pDibDoc).DetachPalette();
ASSERT(pGamePalette);
delete pDibDoc;
/********************************************************************
* 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,
LoadCursor(nullptr, IDC_ARROW), //put in my own cursor
nullptr,
nullptr);
/***********************************
* Center our window on the screen. *
***********************************/
pDC = GetDC();
MainRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) >> 1;
MainRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) >> 1;
MainRect.right = MainRect.left + GAME_WIDTH;
MainRect.bottom = MainRect.top + GAME_HEIGHT;
ReleaseDC(pDC);
/********************************************************************
* Create the window as a POPUP so 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 -- Life", WS_POPUP, MainRect, nullptr, 0);
BeginWaitCursor();
ShowWindow(SW_SHOWNORMAL);
SplashScreen();
EndWaitCursor();
// allocation of CLife must happen before DisplayStats
pDC = GetDC();
m_cLife = new CLife(pDC);
// this must be called before RefreshStats (which will happen in OnPaint)
DisplayStats();
/*********************************************
* Life settings. These are global variables. *
*********************************************/
if (m_lpGameStruct->bPlayingMetagame == true) { // playing meta game?
nLife = VILLAGES_HI; // All levels start with 20
nTurnCounter = ROUNDS_META;
nSpeed = SPEED_DEF;
nCountDown = nSpeed * MONTHS;
nLifeCounter = nLife;
bIsInfiniteTurns = false;
bIsInfiniteLife = false;
bPrePlaceColonies = true;
} else { // playing stand alone
nSpeed = GetPrivateProfileInt(INI_SECTION, "Speed", SPEED_DEF, INI_FNAME);
nCountDown = nSpeed * MONTHS;
nTurnCounter = GetPrivateProfileInt(INI_SECTION, "Rounds", ROUNDS_DEF, INI_FNAME);
if (nTurnCounter == TURN_HI_BOUND) { // fastest turn counter?
bIsInfiniteTurns = true;
} else {
bIsInfiniteTurns = false;
} // end if
nLife = GetPrivateProfileInt(INI_SECTION, "Villages", VILLAGES_DEF, INI_FNAME);
if (nLife == LIFE_HI_BOUND) { // infinite life?
bIsInfiniteLife = true; // yes
nLifeCounter = 0;
} else {
bIsInfiniteLife = false;
nLifeCounter = nLife;
} // end if
nPlace = GetPrivateProfileInt(INI_SECTION, "PrePlace", PLACE_DEF, INI_FNAME);
if (nPlace > 0) { // fastest turn counter?
bPrePlaceColonies = true;
} else {
bPrePlaceColonies = false;
} // end if
} // end if
/*****************************************
* Reports whether game is active or not. *
*****************************************/
m_bGameActive = false;
/********************************
* Used with options dialog box. *
********************************/
gbNewGame = false;
/************************
* Set up Evolve button. *
************************/
EvolveRect.SetRect((GAME_WIDTH >> 1) - (EVOLVE_BUTTON_WIDTH >> 1) - EVOLVE_BUTTON_OFFSET_X,
EVOLVE_BUTTON_OFFSET_Y,
(GAME_WIDTH >> 1) + (EVOLVE_BUTTON_WIDTH >> 1) - EVOLVE_BUTTON_OFFSET_X,
EVOLVE_BUTTON_HEIGHT + EVOLVE_BUTTON_OFFSET_Y);
pEvolveButton = new CColorButton();
if (pEvolveButton != nullptr) {
(void)(*pEvolveButton).Create("Evolve", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
EvolveRect, this, IDC_EVOLVE);
(*pEvolveButton).SetPalette(pGamePalette);
}
/***********************************
* Initialize Sprite Scroll Button. *
***********************************/
pScrollSprite = new CSprite;
(*pScrollSprite).SharePalette(pGamePalette);
bAssertCheck = (*pScrollSprite).LoadSprite(pDC, SCROLL_BUTTON);
ASSERT(bAssertCheck);
(*pScrollSprite).SetMasked(true);
(*pScrollSprite).SetMobile(true);
/******************************
* Initialize Sprite Calendar *
******************************/
pCalendarSprite = new CSprite;
(*pCalendarSprite).SharePalette(pGamePalette);
bAssertCheck = (*pCalendarSprite).LoadSprite(pDC, CALENDAR_BMP);
ASSERT(bAssertCheck);
(*pCalendarSprite).SetMasked(true);
(*pCalendarSprite).SetMobile(false);
ReleaseDC(pDC);
/*******************************************************
* Set the coordinates for the "Start New Game" button. *
*******************************************************/
m_rNewGameButton.SetRect(15, 4, 233, 20);
/*************************
* Initialize MIDI sound. *
*************************/
if (m_lpGameStruct->bMusicEnabled != false) {
if ((m_pSound = new CSound((CWnd *) this, MIDI_SOUND, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END)) != nullptr) {
m_pSound->midiLoopPlaySegment(1500L, 31000L, 00L, FMT_MILLISEC);
} else {
PostMessage(WM_CLOSE, 0, 0);
}
}
/**************************************
* Initialize random number generator. *
**************************************/
//srand((unsigned) time(nullptr)); // seed the random number generator
/**************************
* New game or popup menu? *
**************************/
if (m_lpGameStruct->bPlayingMetagame == true) {
bPrePlaceColonies = true; // in meta, pre-place ten
PostMessage(WM_COMMAND, IDC_OPTIONS_NEWGAME, BN_CLICKED);
} else {
PostMessage(WM_COMMAND, IDC_COMMAND, BN_CLICKED);
} // end if
}
/*****************************************************************
*
* ~CMainWindow
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
CMainWindow::~CMainWindow() {
if (pGamePalette != nullptr)
delete pGamePalette;
if (pCalendarSprite != nullptr)
delete pCalendarSprite;
if (pScrollSprite != nullptr)
delete pScrollSprite;
}
void CMainWindow::initStatics() {
nSpeed = nCountDown = nLife = nPlace = 0;
nTurnCounter = nLifeCounter = 0;
bPrePlaceColonies = bIsInfiniteLife = bIsInfiniteTurns = false;
gbNewGame = false;
pEvolveButton = nullptr;
pGamePalette = nullptr;
pScrollSprite = nullptr;
pCalendarSprite = nullptr;
hWndParent = nullptr;
}
/*****************************************************************
*
* OnPaint
*
* FUNCTIONAL DESCRIPTION:
*
* OnPaint:
* This 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:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnPaint() {
PAINTSTRUCT lpPaint;
InvalidateRect(nullptr, false);
BeginPaint(&lpPaint);
SplashScreen();
RefreshStats();
EndPaint(&lpPaint);
}
/*****************************************************************
*
* NewGame
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::NewGame() {
CDC *pDC;
CPoint point;
int i,
row,
col;
if ((*m_cLife).m_bIsEvolving == true) { // Evolve timer on?
KillTimer(EVOLVE_TIMER_ID); // yes - turn it off.
(*m_cLife).m_bIsEvolving = false;
} // end if
pDC = GetDC();
(*m_cLife).NewGame(pDC);
if (bPrePlaceColonies) { // want ten colonies preplaced?
// Randomly place 10 of their villages for them!
i = 0; // initialize counter
while (i < VILLAGES_PLACED) { // until we place all preset villages
point.x = (((brand() % PLACE_COLS) + OFFSET_X) * CURLY_X) + BOARD_START_COL;
point.y = (((brand() % PLACE_ROWS) + OFFSET_Y) * CURLY_Y) + BOARD_START_ROW;
// track down cell of board that was clicked
row = (point.y - BOARD_START_ROW) / (BOARD_SPACING_TIMES_TWO + CURLY_Y);
col = (point.x - BOARD_START_COL) / (BOARD_SPACING_TIMES_TWO + CURLY_X);
if (!m_cLife->pColony->islife(row, col)) { // life at this cell already?
(*m_cLife).change_board(
0, // nFlags is not used by change_board
point,
pDC,
m_lpGameStruct->bPlayingMetagame
);
i++; // another one placed successfully
} // end if
} // end for
}
ReleaseDC(pDC);
SetDlgItemText(IDC_EVOLVE, "Evolve"); // Make sure button is reset to read Evolve
m_bGameActive = true;
}
/*****************************************************************
*
* GamePause
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::GamePause() {
if ((*m_cLife).m_bIsEvolving == true) { // Evolve timer on?
KillTimer(EVOLVE_TIMER_ID); // yes - turn it off.
} // end if
}
/*****************************************************************
*
* GameResume
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::GameResume() {
if ((*m_cLife).m_bIsEvolving == true) {
RefreshStats();
SetTimer(EVOLVE_TIMER_ID, EVOLVE_INTERVAL, nullptr);
}
}
/*****************************************************************
*
* OnCommand
*
* FUNCTIONAL DESCRIPTION:
*
* Called when a WM_COMMAND message is issued,
* typically in order to process control related activities.
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
bool CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) {
bool bAssertCheck;
CDC *pDC;
if (HIWORD(lParam) != BN_CLICKED)
return true;
if (wParam == IDC_COMMAND) { // user click scroll sprite?
GamePause();
pDC = GetDC();
bAssertCheck = (*pScrollSprite).EraseSprite(pDC);
ReleaseDC(pDC);
ASSERT(bAssertCheck);
CMainMenu COptionsWind( // Create the commands menu
(CWnd *)this,
pGamePalette,
(m_bGameActive ? 0 : NO_RETURN) |
(m_lpGameStruct->bPlayingMetagame ? (NO_NEWGAME | NO_OPTIONS) : 0),
GetGameParams,
RULES_TXT, // mini - game rules file
RULES_WAV, // naration sound file
m_lpGameStruct
);
CSound::waitWaveSounds();
switch (COptionsWind.DoModal()) {
case IDC_OPTIONS_NEWGAME: // new game?
NewGame();
break;
case IDC_OPTIONS_QUIT: // quit game?
if (m_lpGameStruct->bPlayingMetagame != false)
m_lpGameStruct->lScore = LOSE;
PostMessage(WM_CLOSE, 0, 0);
break;
default: // continue?
break;
} // end switch
if (!m_lpGameStruct->bMusicEnabled && (m_pSound != nullptr)) {
m_pSound->stop();
delete m_pSound;
m_pSound = nullptr;
} else if (m_lpGameStruct->bMusicEnabled && (m_pSound == nullptr)) {
if ((m_pSound = new CSound((CWnd *) this, MIDI_SOUND, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END)) != nullptr)
m_pSound->midiLoopPlaySegment(1500L, 31000L, 00L, FMT_MILLISEC);
}
// show the command scroll
pDC = GetDC();
bAssertCheck = (*pScrollSprite).PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
ReleaseDC(pDC);
ASSERT(bAssertCheck);
GameResume();
//if ( gbNewGame == true ) {
// PostMessage(WM_COMMAND, IDC_OPTIONS_NEWGAME, BN_CLICKED);
// gbNewGame = false;
//}
} else if (wParam == IDC_EVOLVE) { // Evolve button was clicked
if ((*m_cLife).m_bIsEvolving == true) { // currently evolving?
if (m_lpGameStruct->bPlayingMetagame == false) { // playing meta game?
(*m_cLife).m_bIsEvolving = false; // no - can turn evolve off, then
KillTimer(EVOLVE_TIMER_ID);
SetDlgItemText(IDC_EVOLVE, "Evolve"); // so give them the Suspend option
}
} else {
(*m_cLife).m_bIsEvolving = true; // no - turn it on
nCountDown = nSpeed * MONTHS;
if (m_lpGameStruct->bPlayingMetagame == false) { // not playing metagame
SetDlgItemText(IDC_EVOLVE, "Suspend"); // so give them the Suspend option
} else { // Only works once in metagame,
(*pEvolveButton).EnableWindow(false); //...so disable evolve button
}
pDC = GetDC(); // Update visual calendars
(*m_cLife).ResetMonths(pDC);
ReleaseDC(pDC);
RefreshStats();
SetTimer(EVOLVE_TIMER_ID, EVOLVE_INTERVAL, nullptr);
} // end if
} else if (wParam == IDC_OPTIONS_NEWGAME) {
NewGame();
} // end if
return true;
}
// OnChar and OnSysChar
// These functions are called when keyboard input generates a character.
//
/*****************************************************************
*
* OnSysChar
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
switch (nChar) {
// User has hit ALT_F4 so close down this App
//
case VK_F4:
if (m_lpGameStruct->bPlayingMetagame != false)
m_lpGameStruct->lScore = LOSE;
PostMessage(WM_CLOSE, 0, 0);
break;
default:
CFrameWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
break;
} // end switch
}
void CMainWindow::OnSysChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
if ((nChar == 'e') && (nFlags & 0x2000)) { // ALT-e - evolve
PostMessage(WM_COMMAND, IDC_EVOLVE, BN_CLICKED);
} else if ((nChar == 'q') && (nFlags & 0x2000)) { // Alt-q - quit
if (m_lpGameStruct->bPlayingMetagame != false)
m_lpGameStruct->lScore = LOSE;
PostMessage(WM_CLOSE, 0, 0);
} else {
CFrameWnd ::OnChar(nChar, nRepCnt, nFlags); // default action
} // end if
}
void CMainWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// Handle keyboard input
//
switch (nChar) {
case VK_F1: { // Bring up the Rules
GamePause();
CSound::waitWaveSounds();
CRules RulesDlg(
this,
RULES_TXT,
pGamePalette,
RULES_WAV // naration sound file
);
RulesDlg.DoModal();
GameResume();
break;
} // end case
case VK_F2: // Bring up the options menu
PostMessage(WM_COMMAND, IDC_COMMAND, BN_CLICKED);
break;
default:
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
break;
} // end switch
}
/*****************************************************************
*
* OnLButtonDown
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnLButtonDown(unsigned int nFlags, CPoint point) {
CDC *pDC;
CRect cTestRect;
cTestRect = (*pScrollSprite).GetRect();
if (cTestRect.PtInRect(point) == true) {
SendMessage(WM_COMMAND, IDC_COMMAND, BN_CLICKED);
} else if (
m_rNewGameButton.PtInRect(point) == true &&
m_lpGameStruct->bPlayingMetagame == false
) { // playing meta game?
NewGame(); // no - new game ok
} else {
pDC = GetDC();
(*m_cLife).change_board(
nFlags,
point,
pDC,
m_lpGameStruct->bPlayingMetagame
);
ReleaseDC(pDC);
} // end if
}
/*****************************************************************
*
* OnLButtonDblClk
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnLButtonDblClk(unsigned int nFlags, CPoint point) {
// insert mouse button processing code here
CRect cTestRect;
CDC *pDC;
cTestRect = (*pScrollSprite).GetRect();
if (cTestRect.PtInRect(point)) {
SendMessage(WM_COMMAND, IDC_COMMAND, BN_CLICKED);
} else if (m_rNewGameButton.PtInRect(point) &&
m_lpGameStruct->bPlayingMetagame == false
) {
NewGame();
} else {
pDC = GetDC();
(*m_cLife).change_board(
nFlags,
point,
pDC,
m_lpGameStruct->bPlayingMetagame
);
ReleaseDC(pDC);
}
}
/*****************************************************************
*
* OnTimer
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnTimer(uintptr nIDEvent) {
CDC *pDC;
switch (nIDEvent) {
case EVOLVE_TIMER_ID: {
// Are there no colonies left to place, and
// nothing left on the board?
if (
!nLifeCounter &&
bIsInfiniteLife != true &&
!(*m_cLife).ColonyPlaced() &&
m_lpGameStruct->bPlayingMetagame == false
) {
KillTimer(EVOLVE_TIMER_ID);
//b
if (m_lpGameStruct->bSoundEffectsEnabled != false) {
sndPlaySound(WAV_DEATH, SND_SYNC);
sndPlaySound(WAV_GAMEOVER, SND_ASYNC); // When first starts up so
// that u get to see the screen
} // end if
CMessageBox GameOver(
(CWnd*) this,
pGamePalette,
"Game over.",
"No villages left."
);
(*m_cLife).m_bIsEvolving = false;
if (m_lpGameStruct->bSoundEffectsEnabled != false) {
sndPlaySound(nullptr, SND_SYNC);
}
PostMessage(WM_COMMAND, IDC_OPTIONS_NEWGAME, BN_CLICKED);
break;
}
// Have we evolved proper number of turns or
// is evolution infinite?
if ((*m_cLife).m_nYears != nTurnCounter ||
bIsInfiniteTurns) {
// No - evolve again
// has timer run down to zero?
if (nCountDown <= 0) {
// Yes - then evolve
KillTimer(EVOLVE_TIMER_ID);
pDC = GetDC();
(*m_cLife).evolution(pDC);
// Restart timer and display it
nCountDown = nSpeed * MONTHS;
if (nSpeed != FASTEST) { // Evolve speed long enuf to play sound?
// Yes - play the tune
if (m_lpGameStruct->bSoundEffectsEnabled != false)
sndPlaySound(WAV_EVOLVE, SND_ASYNC);
// Update visual calendar
RefreshStats();
}
ReleaseDC(pDC);
SetTimer(EVOLVE_TIMER_ID, EVOLVE_INTERVAL, nullptr);
} else { // No, timer not zero, decrement
// Reduce counter by 1
nCountDown -= 1;
// Update visual calendar
pDC = GetDC();
(*m_cLife).DisplayMonth(nCountDown, pDC);
ReleaseDC(pDC);
}
} else { // Yes -- shut this thing down
KillTimer(EVOLVE_TIMER_ID);
(*m_cLife).m_bIsEvolving = false;
char buf[64];
Common::sprintf_s(buf, "Score: %ld", (long)(*m_cLife).m_dScore);
if (m_lpGameStruct->bSoundEffectsEnabled != false)
sndPlaySound(WAV_GAMEOVER, SND_SYNC); // When first starts up so
// that u get to see the screen
CMessageBox GameOver(
(CWnd*) this,
pGamePalette,
"Game over.",
buf
);
if (m_lpGameStruct->bPlayingMetagame != false) {
m_lpGameStruct->lScore = (long)(*m_cLife).m_dScore;
PostMessage(WM_CLOSE, 0, 0);
} else {
PostMessage(WM_COMMAND, IDC_OPTIONS_NEWGAME, BN_CLICKED);
}
}
break;
}
default:
CFrameWnd ::OnTimer(nIDEvent);
}
}
/*****************************************************************
*
* OnClose
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnClose() {
CDC *pDC = GetDC();
CRect rctFillRect(0, 0, 640, 480);
CBrush Brush(RGB(0, 0, 0));
pDC->FillRect(&rctFillRect, &Brush);
ReleaseDC(pDC);
// TODO: Add your message handler code here and/or call default
if (pEvolveButton != nullptr) {
delete pEvolveButton;
pEvolveButton = nullptr;
}
delete m_cLife;
if (m_pSound != nullptr) {
m_pSound->stop();
delete m_pSound;
m_pSound = nullptr;
} // end if
CSound::clearSounds();
CFrameWnd ::OnClose();
}
/*****************************************************************
*
* OnDestroy
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::OnDestroy() {
// send a message to the calling app to tell it the user has quit the game
MFC::PostMessage(m_hCallAppWnd, WM_PARENTNOTIFY, WM_DESTROY, (LPARAM)m_lpGameStruct);
// delete m_lpGameStruct;
CFrameWnd::OnDestroy();
}
/*****************************************************************
*
* SplashScreen
*
* FUNCTIONAL DESCRIPTION:
*
* Paint the background art (splash screen) in the client area;
* called by both OnPaint and InitInstance.
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::SplashScreen() {
CRect rcDest;
CRect rcDIB;
CDC *pDC;
CDibDoc myDoc;
HDIB hDIB;
CSprite *pSprite;
bool bCheck;
int nMonthIndex;
bCheck = myDoc.OpenDocument(SPLASHSPEC);
ASSERT(bCheck);
hDIB = myDoc.GetHDIB();
pDC = GetDC();
if (pDC && hDIB) {
GetClientRect(rcDest);
int cxDIB = (int) DIBWidth(hDIB);
int cyDIB = (int) DIBHeight(hDIB);
rcDIB.top = rcDIB.left = 0;
rcDIB.right = cxDIB;
rcDIB.bottom = cyDIB;
PaintDIB((*pDC).m_hDC, &rcDest, hDIB, &rcDIB, pGamePalette);
if (pScrollSprite != nullptr)
pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
if (pCalendarSprite != nullptr)
pCalendarSprite->PaintSprite(pDC, MONTH_COL_POS, MONTH_ROW_POS);
}
pSprite = CSprite::GetSpriteChain();
while (pSprite) {
(*pSprite).ClearBackground();
bCheck = (*pSprite).RefreshSprite(pDC);
ASSERT(bCheck);
pSprite = (*pSprite).GetNextSprite();
}
// Refresh visual calendar
if (nSpeed == FASTEST) {
nMonthIndex = 0;
} else {
nMonthIndex = (MONTHS - ((int) nCountDown / nSpeed) - 1);
if (nMonthIndex < 0)
nMonthIndex = 0;
}
if (m_cLife != nullptr)
m_cLife->m_cCalendar.pMonthSprite[nMonthIndex]->ClearBackground();
ReleaseDC(pDC);
}
/*****************************************************************
*
* DisplayStats
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::DisplayStats() {
CDC *pDC;
bool bAssertCheck;
CRect statsRect;
char buf[256];
pDC = GetDC();
// Colony placed count box
statsRect.SetRect(CURRENT_LEFT_COL,
CURRENT_LEFT_ROW,
CURRENT_RIGHT_COL,
CURRENT_RIGHT_ROW);
if (((*m_cLife).pColonyPlaced = new CText()) != nullptr) {
bAssertCheck = m_cLife->pColonyPlaced->SetupText(pDC, pGamePalette, &statsRect, JUSTIFY_LEFT);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "Current Villages: %d", (*m_cLife).ColonyPlaced());
bAssertCheck = m_cLife->pColonyPlaced->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
// Score box
statsRect.SetRect(SCORE_LEFT_COL,
SCORE_LEFT_ROW,
SCORE_RIGHT_COL,
SCORE_RIGHT_ROW);
if (((*m_cLife).pScore = new CText()) != nullptr) {
bAssertCheck = m_cLife->pScore->SetupText(pDC, pGamePalette, &statsRect, JUSTIFY_LEFT);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "Score: %.1f", (*m_cLife).m_dScore);
bAssertCheck = m_cLife->pScore->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
// Round box
statsRect.SetRect(ROUND_LEFT_COL,
ROUND_LEFT_ROW,
ROUND_RIGHT_COL,
ROUND_RIGHT_ROW);
if (((*m_cLife).pYears = new CText()) != nullptr) {
bAssertCheck = m_cLife->pYears->SetupText(pDC, pGamePalette, &statsRect);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "%d", (*m_cLife).m_nYears);
bAssertCheck = m_cLife->pYears->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
statsRect.SetRect(ROUND_TEXT1_LEFT_COL,
ROUND_TEXT1_LEFT_ROW,
ROUND_TEXT1_RIGHT_COL,
ROUND_TEXT1_RIGHT_ROW);
if (((*m_cLife).pYearsText1 = new CText()) != nullptr) {
bAssertCheck = m_cLife->pYearsText1->SetupText(pDC, pGamePalette, &statsRect);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "years");
bAssertCheck = m_cLife->pYearsText1->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
statsRect.SetRect(ROUND_TEXT2_LEFT_COL,
ROUND_TEXT2_LEFT_ROW,
ROUND_TEXT2_RIGHT_COL,
ROUND_TEXT2_RIGHT_ROW);
if (((*m_cLife).pYearsText2 = new CText()) != nullptr) {
bAssertCheck = m_cLife->pYearsText2->SetupText(pDC, pGamePalette, &statsRect);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "past");
bAssertCheck = m_cLife->pYearsText2->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
// Colony left count box
statsRect.SetRect(VILLAGE_LEFT_COL,
VILLAGE_LEFT_ROW,
VILLAGE_RIGHT_COL,
VILLAGE_RIGHT_ROW);
if (((*m_cLife).pColonyStat = new CText()) != nullptr) {
bAssertCheck = m_cLife->pColonyStat->SetupText(pDC, pGamePalette, &statsRect);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "%d", nLifeCounter);
bAssertCheck = m_cLife->pColonyStat->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
statsRect.SetRect(VILLAGE_TEXT1_LEFT_COL,
VILLAGE_TEXT1_LEFT_ROW,
VILLAGE_TEXT1_RIGHT_COL,
VILLAGE_TEXT1_RIGHT_ROW);
if (((*m_cLife).pColonyStatText1 = new CText()) != nullptr) {
bAssertCheck = m_cLife->pColonyStatText1->SetupText(pDC, pGamePalette, &statsRect);
ASSERT(bAssertCheck); // initialize the text objext
Common::sprintf_s(buf, "left");
bAssertCheck = m_cLife->pColonyStatText1->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
// Update visual calendar
(*m_cLife).DisplayMonth(nCountDown, pDC);
ReleaseDC(pDC);
}
/*****************************************************************
*
* RefreshStats
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CMainWindow::RefreshStats() {
CDC *pDC;
bool bAssertCheck;
char buf[256];
pDC = GetDC();
// Colony placed count box
Common::sprintf_s(buf, "Current Villages: %d", (*m_cLife).ColonyPlaced());
bAssertCheck = m_cLife->pColonyPlaced->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
// Score box
Common::sprintf_s(buf, "Score: %.1f", (*m_cLife).m_dScore);
bAssertCheck = m_cLife->pScore->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
// Round box
if (bIsInfiniteTurns != true) {
Common::sprintf_s(buf, "%d", (*m_cLife).m_nYears);
bAssertCheck = m_cLife->pYears->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
Common::sprintf_s(buf, "years");
bAssertCheck = m_cLife->pYearsText1->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
Common::sprintf_s(buf, "past");
bAssertCheck = m_cLife->pYearsText2->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
} else {
Common::strcat_s(buf, "");
bAssertCheck = m_cLife->pYears->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
bAssertCheck = m_cLife->pYearsText1->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
bAssertCheck = m_cLife->pYearsText2->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
// Colony left count box
// update colony count stat
if (bIsInfiniteLife == true) {
Common::sprintf_s(buf, "Unlim");
bAssertCheck = m_cLife->pColonyStat->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
Common::strcat_s(buf, "");
bAssertCheck = m_cLife->pColonyStatText1->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
} else {
Common::sprintf_s(buf, "%d", nLifeCounter);
bAssertCheck = m_cLife->pColonyStat->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
Common::sprintf_s(buf, "left");
bAssertCheck = m_cLife->pColonyStatText1->DisplayString(pDC, buf, STATS_FONT_SIZE, FW_BOLD, STATS_COLOR);
ASSERT(bAssertCheck); // paint the text
}
// Update visual calendar
(*m_cLife).DisplayMonth(nCountDown, pDC);
ReleaseDC(pDC);
}
LRESULT CMainWindow::OnMCINotify(WPARAM wParam, LPARAM lParam) {
//CSound *pSound;
CSound::OnMCIStopped(wParam, lParam);
return 0;
}
LRESULT CMainWindow::OnMMIONotify(WPARAM wParam, LPARAM lParam) {
//CSound *pSound;
CSound::OnMMIOStopped(wParam, lParam);
return 0;
}
/////////////////////////////////////////////////////////////////////////////
// CWindowMain message handlers
// CMainWindow message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
//{{AFX_MSG_MAP( CMainWindow )
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_SYSKEYDOWN()
ON_WM_KEYDOWN()
ON_WM_SYSCHAR()
ON_WM_TIMER()
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_MESSAGE(MM_MCINOTIFY, CMainWindow::OnMCINotify)
ON_MESSAGE(MM_WOM_DONE, CMainWindow::OnMMIONotify)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE(CWindowMain, CFrameWnd)
/////////////////////////////////////////////////////////////////////////////
// CTheApp
// InitInstance:
// When any CTheApp object is created, this member function is automatically
// called. Any data may be set up at this point.
//
// Also, the main window of the application should be created and shown here.
// Return true if the initialization is successful.
//
/*
bool CTheApp::InitInstance()
{
//COLORREF clrCtlBk = RGB(0,0,0);
//COLORREF clrCtlText = STATS_COLOR;
CMainWindow *pMyMain;
TRACE( "Boffo Games\n" );
//SetDialogBkColor(clrCtlBk,clrCtlText);
//SetDialogBkColor(); // hook gray dialogs (was default in MFC V1)
m_pMainWnd = gMainWnd = pMyMain = new CMainWindow();
m_pMainWnd->ShowWindow( m_nCmdShow );
// this is required stuff
pMyMain->SplashScreen(); // Force immediate display to minimize repaint delay
pMyMain->DisplayStats(); // Initializes the stats
m_pMainWnd->UpdateWindow();
return true;
}
*/
/////////////////////////////////////////////////////////////////////////////
// CWindowMain
CWindowMain::CWindowMain() {
}
CWindowMain::~CWindowMain() {
}
BEGIN_MESSAGE_MAP(CWindowMain, CFrameWnd)
//{{AFX_MSG_MAP(CWindowMain)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/*****************************************************************
*
* GetGameParams
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CALLBACK GetGameParams(CWnd *pParentWnd) {
gbNewGame = false;
CUserCfgDlg dlgUserCfg(pParentWnd, pGamePalette, IDD_USERCFG);
if (dlgUserCfg.DoModal() == IDOK) { // user click ok?
gbNewGame = true; // restart game with new settings
}
} // GetGameParams
} // namespace Life
} // namespace HodjNPodj
} // namespace Bagel