]> Shamusworld >> Repos - warehouse-man-deluxe/blob - src/mainwin.cpp
Added/fixed editor, added play level functionality.
[warehouse-man-deluxe] / src / mainwin.cpp
1 //
2 // mainwin.cpp: Implementation of the MainWin class
3 //
4 //   JLH = James Hammons <jlhamm@acm.org>
5 //
6 // Who  When        What
7 // ---  ----------  ------------------------------------------------------------
8 // JLH  03/01/2014  Created this file
9 //
10
11 // TO DO:
12 //
13
14 #include "mainwin.h"
15
16 #include <stdlib.h>                     // For rand()
17 #include <time.h>                       // For time()
18 #include "gameboard.h"
19 #include "editorwindow.h"       // Actual mouse/drawing window
20 #include "gamewidget.h"         // Actual mouse/drawing window
21 //#include "resource.h"
22 //#include "optiondlg.h"                // Options dialog class
23 //#include "statdlg.h"          // Statistics dialog class
24
25
26 MainWin::MainWin()
27 {
28         gameWidget = new GameWidget(this);
29         setCentralWidget(gameWidget);
30         gameWidget->setFocusPolicy(Qt::StrongFocus);    // Without this, it gets no keys
31         setWindowTitle("Warehouse Man Deluxe");
32         setWindowIcon(QIcon(":/wmd-icon.png"));
33
34 //      editor = new QWindow(this);
35         editorWindow = new EditorWindow(this);
36 //      editor->setCentralWidget(editorWidget);
37 //      editorWidget->setFocusPolicy(Qt::StrongFocus);  // Without this, it gets no keys
38         editorWindow->show();
39
40         newGame = CreateAction(tr("&New"), tr("New Game"), tr("Start a new game of Warehouse Man Deluxe"), QIcon(), QKeySequence(tr("ctrl+n")));
41 //      connect(newGame, SIGNAL(triggered()), this, SLOT(OnNewGame()));
42
43         undoAction = CreateAction(tr("&Undo"), tr(""), tr(""), QIcon(), QKeySequence(tr("ctrl+z")));
44         connect(undoAction, SIGNAL(triggered()), this, SLOT(HandleUndo()));
45
46         resetLevel = CreateAction(tr("&Reset Level"), tr("Reset Level"), tr("Start the current level over"), QIcon(), QKeySequence(tr("ctrl+r")));
47         connect(resetLevel, SIGNAL(triggered()), this, SLOT(HandleReset()));
48
49         skipLevel = CreateAction(tr("&Skip Level"), tr("Skip Level"), tr("Skip the current level"), QIcon(), QKeySequence(tr("ctrl+k")));
50         connect(skipLevel, SIGNAL(triggered()), this, SLOT(HandleSkipLevel()));
51
52         gameOptions = CreateAction(tr("&Options..."), tr("Options"), tr("Configure Warehouse Man Deluxe's options"), QIcon(), QKeySequence(tr("ctrl+o")));
53 //      connect(gameOptions, SIGNAL(triggered()), this, SLOT(OnGameOptions()));
54
55         gameStats = CreateAction(tr("&Stats..."), tr("Game Stats"), tr("Show game stats"), QIcon(), QKeySequence(tr("ctrl+s")));
56 //      connect(gameStats, SIGNAL(triggered()), this, SLOT(OnGameStats()));
57
58         appExit = CreateAction(tr("E&xit"), tr("Exit"), tr("Quit playing Warehouse Man Deluxe..."), QIcon(), QKeySequence(tr("ctrl+q")));
59         connect(appExit, SIGNAL(triggered()), this, SLOT(close()));
60
61         appAbout = CreateAction(tr("&About"), tr("About"), tr("Display program information..."), QIcon(), QKeySequence(tr("")));
62         connect(appAbout, SIGNAL(triggered()), this, SLOT(AboutGame()));
63
64         // Get signals from the gameboard to update scores...
65 //      connect(gameBoard, SIGNAL(UpdateScore(int)), this, SLOT(OnUpdateScore(int)));
66         connect(gameWidget, SIGNAL(GameWasWon()), this, SLOT(WeHaveAWinner()));
67
68         // Connect editor to game widget...
69         connect(editorWindow, SIGNAL(SetupLevel(Level *)), gameWidget,
70                 SLOT(HandlePlayGameFromEditor(Level *)));
71
72
73         QMenu * menu = menuBar()->addMenu(tr("&Game"));
74         menu->addAction(newGame);
75         menu->addSeparator();
76 //      menu->addAction(gamePlay);
77         menu->addAction(undoAction);
78         menu->addAction(resetLevel);
79         menu->addAction(skipLevel);
80         menu->addSeparator();
81         menu->addAction(gameOptions);
82         menu->addAction(gameStats);
83         menu->addSeparator();
84         menu->addAction(appExit);
85
86         menu = menuBar()->addMenu(tr("&Help"));
87         menu->addAction(appAbout);
88
89 //      statusBar()->addPermanentWidget(gameBoard->score);
90         statusBar()->showMessage(tr("Ready"));
91
92         QSettings settings("Underground Software", "Warehouse Man Deluxe");
93         QPoint mainWinPosition = settings.value("pos", QPoint(200, 100)).toPoint();
94         move(mainWinPosition);
95         QSize mainWinSize = settings.value("size", QSize(500, 500)).toSize();
96         resize(mainWinSize);
97
98 /*      nCardBack = settings.value("CardBack", BACK4).toInt();
99         m_nBackground = settings.value("Background", 0).toInt();
100         bSoundOn = settings.value("EnableSound", true).toBool();
101         m_bAnimationsOn = settings.value("EnableAnimations", true).toBool();
102         bAutoRemove = settings.value("AutoRemove", true).toBool();
103         scoringOn = settings.value("EnableScoring", false).toBool();
104         m_bCumulativeOn = settings.value("CumulativeScore", false).toBool();
105         m_bVegasStyle = settings.value("VegasScoring", false).toBool();
106         m_bDrawThree = settings.value("DrawThree", false).toBool();
107         m_nWins = settings.value("NumWins", 0).toInt();
108         m_nLosses = settings.value("NumLosses", 0).toInt();
109         m_nHiScore = settings.value("HiScore", 0).toInt();
110         m_nVHiScore = settings.value("VegasHiScore", 0).toInt();
111         m_nStreakW = settings.value("WinStreak", 0).toInt();
112         m_nStreakL = settings.value("LoseStreak", 0).toInt();
113         m_nStreakC = settings.value("CurrentStreak", 0).toInt();
114         m_bWonLastGame = settings.value("WonLastGame", false).toBool();
115         m_nScore = settings.value("LastScore", -52).toInt();*/
116
117 //      gameBoard->CreateBackground();
118 //      InitializeAudio();
119
120 //      mouseDown = false;
121 //      myDeck.SetCardWidth(CARD_WIDTH);
122 //      myDeck.SetCardHeight(CARD_HEIGHT);
123 //
124 //      for(int i=0; i<52; i++)
125 //              myDeck.SetCardPosition(i, QPoint(0, 0));
126
127         ResetGame();
128 //      allowUserInput = true;
129 //      m_bFreeCard = false;
130 //      m_pFirstCard = NULL;
131 }
132
133
134 MainWin::~MainWin()
135 {
136 //      ShutDownAudio();
137         delete editorWindow;
138 }
139
140
141 //
142 // Consolidates action creation from a multi-step process to a single-step one.
143 //
144 QAction * MainWin::CreateAction(QString name, QString tooltip, QString statustip,
145         QIcon icon, QKeySequence key, bool checkable/*= false*/)
146 {
147         QAction * action = new QAction(icon, name, this);
148         action->setToolTip(tooltip);
149         action->setStatusTip(statustip);
150         action->setShortcut(key);
151         action->setCheckable(checkable);
152
153         return action;
154 }
155
156
157 //
158 // This is essentially the same as the previous function, but this allows more
159 // than one key sequence to be added as key shortcuts.
160 //
161 QAction * MainWin::CreateAction(QString name, QString tooltip, QString statustip,
162         QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
163 {
164         QAction * action = new QAction(icon, name, this);
165         action->setToolTip(tooltip);
166         action->setStatusTip(statustip);
167         QList<QKeySequence> keyList;
168         keyList.append(key1);
169         keyList.append(key2);
170         action->setShortcuts(keyList);
171         action->setCheckable(checkable);
172
173         return action;
174 }
175
176
177 void MainWin::closeEvent(QCloseEvent * event)
178 {
179 /*      if (allowUserInput && m_bTouchedGame)
180         {
181                 gameBoard->HandleStatistics();
182                 m_bWonLastGame = false;
183         }*/
184
185         QSettings settings("Underground Software", "Warehouse Man Deluxe");
186         settings.setValue("pos", pos());
187         settings.setValue("size", size());
188
189 /*
190         settings.setValue("CardBack", nCardBack);
191         settings.setValue("Background", m_nBackground);
192         settings.setValue("EnableSound", bSoundOn);
193         settings.setValue("EnableAnimations", m_bAnimationsOn);
194         settings.setValue("AutoRemove", bAutoRemove);
195         settings.setValue("EnableScoring", scoringOn);
196         settings.setValue("CumulativeScore", m_bCumulativeOn);
197         settings.setValue("VegasScoring", m_bVegasStyle);
198         settings.setValue("DrawThree", m_bDrawThree);
199         settings.setValue("NumWins", m_nWins);
200         settings.setValue("NumLosses", m_nLosses);
201         settings.setValue("HiScore", m_nHiScore);
202         settings.setValue("VegasHiScore", m_nVHiScore);
203         settings.setValue("WinStreak", m_nStreakW);
204         settings.setValue("LoseStreak", m_nStreakL);
205         settings.setValue("CurrentStreak", m_nStreakC);
206         settings.setValue("WonLastGame", m_bWonLastGame);
207         settings.setValue("LastScore", m_nScore);*/
208
209         event->accept();
210 }
211
212
213 /*
214 void MainWin::OnUpdateScore(int n)
215 {
216         if (!scoringOn)
217                 return;
218
219         QString s;
220
221         if (m_bVegasStyle)
222                 s = QString(tr("Score: $%1")).arg(n);
223         else
224                 s = QString(tr("Score: %1")).arg(n);
225
226         gameBoard->score->setText(s);
227 printf("OUS: n=%i, s=%s\n", n, s.toAscii().data());
228 }
229 */
230
231 void MainWin::ResetGame(void)
232 {
233         gameWidget->level = 1;
234
235 /*      myDeck.Shuffle();
236
237         for(int i=0; i<7; i++)
238                 for(int j=0; j<20; j++)
239                         solBoard[i][j] = -1; // Empty the board...
240
241         int card = 0;
242         myDeck.SetAllFaceDown();
243
244         for(int i=0; i<7; i++)       // Fill the tableaux
245         {
246                 for(int j=i; j<7; j++)
247                 {
248                         solBoard[6 - i][6 - j] = card;
249
250                         if (i == j)
251                                 myDeck.SetCardFaceUp(card);
252
253                         card++;
254                 }
255         }
256
257         for(int i=0; i<24; i++)   // Fill the stack
258                 stack1[i] = card++;
259
260         stack1p = 23;
261         stack2p = -1;
262         nAce[0] = nAce[1] = nAce[2] = nAce[3] = -1;
263
264         hitStack = hitDiscard = false;
265         nHitAce = 0;
266         m_bTouchedGame = false;
267
268         if (!m_bVegasStyle)
269                 m_nScore = 0;
270         else
271         {
272                 if (!m_bCumulativeOn)
273                         m_nScore = -52;
274                 else
275                         m_nScore -= 52;
276         }
277
278         m_nExhaustedDeck = 0;
279         m_bShowX = false;
280         m_bCanUndo = false;
281
282         OnUpdateScore(m_nScore);*/
283 }
284
285
286 void MainWin::AboutGame(void)
287 {
288         QMessageBox::about(this, tr("About Warehouse Man Deluxe"), tr("Warehouse Man Deluxe Version 1.0\n\nCopyright (C) 2014 Underground Software\n\nWritten by James L. Hammons"));
289 }
290
291
292 void MainWin::WeHaveAWinner(void)
293 {
294         QMessageBox::information(this, "Warehouse Man Deluxe", "Congratulations!\nYou beat this level!\nNow try the next level!");
295         gameWidget->NextLevel();
296 }
297
298
299 void MainWin::HandleReset(void)
300 {
301         gameWidget->ResetLevel();
302 }
303
304
305 void MainWin::HandleSkipLevel(void)
306 {
307         gameWidget->NextLevel();
308 }
309
310
311 void MainWin::HandleUndo(void)
312 {
313         gameWidget->UndoLastMove();
314 }
315
316
317 #if 0
318 void MainWin::OnNewGame(void) 
319 {
320         if (allowUserInput && m_bTouchedGame)   // Player didn't win...
321         {
322                 gameBoard->HandleStatistics();
323                 m_bWonLastGame = false;
324         }
325
326         ResetGame();
327         gameBoard->update();
328         allowUserInput = true;
329
330 #if HAVE_SOUND
331         if (bSoundOn)
332         {
333                 PlaySound(IDW_CARDKNOCK);
334                 gameBoard->Pause(300);
335                 PlaySound(IDW_SHUFFLE);
336         }
337 #endif
338 }
339
340
341 void MainWin::OnGameOptions(void)
342 {
343         OptionDlg dlg;
344
345         dlg.m_cardBack = nCardBack - BACK1;
346         dlg.m_nBackground = m_nBackground;
347         dlg.m_bCheck1 = bSoundOn;
348         dlg.m_bCheck2 = m_bAnimationsOn;
349         dlg.m_bCheck3 = bAutoRemove;
350         dlg.m_bCheck4 = scoringOn;
351         dlg.m_bCheck5 = m_bCumulativeOn;
352         dlg.m_nRadio1 = m_bVegasStyle;
353         dlg.m_nRadio3 = m_bDrawThree;
354
355         dlg.UpdateUI();
356
357         if (dlg.exec() == QDialog::Rejected)
358                 return;
359
360         dlg.UpdateData();
361
362         nCardBack = dlg.m_cardBack + BACK1;
363         m_nBackground = dlg.m_nBackground;
364         bSoundOn = (bool)dlg.m_bCheck1;
365         m_bAnimationsOn = (bool)dlg.m_bCheck2;
366         bAutoRemove = (bool)dlg.m_bCheck3;
367         m_bCumulativeOn = (bool)dlg.m_bCheck5;
368
369         // Reset game if Vegas Style/Draw Three changes at all...
370         bool bChanged =  (bool)((m_bVegasStyle != (bool)dlg.m_nRadio1)
371                 || (m_bDrawThree != (bool)dlg.m_nRadio3) || (scoringOn != (bool)dlg.m_bCheck4));
372
373         scoringOn = (bool)dlg.m_bCheck4;
374         m_bVegasStyle = (bool)dlg.m_nRadio1;
375         m_bDrawThree = (bool)dlg.m_nRadio3;
376
377         if (bChanged && m_bTouchedGame)
378                 OnNewGame();  // Probably should warn of this...
379
380         gameBoard->CreateBackground();
381         gameBoard->update();
382 }
383
384
385 void MainWin::OnGameStats(void)
386 {
387         StatDlg dlg;
388
389 /*      dlg.m_nWins = m_nWins;
390         dlg.m_nLosses = m_nLosses;
391         dlg.m_nHiScore = m_nHiScore;
392         dlg.m_nVHiScore = m_nVHiScore;
393         dlg.m_nStreakW = m_nStreakW;
394         dlg.m_nStreakL = m_nStreakL;
395         dlg.m_nStreakC = m_nStreakC;*/
396
397         dlg.exec();
398
399         // Since it's possible to reset the stats, we grab the fields back here...
400 /*      m_nWins = dlg.m_nWins;
401         m_nLosses = dlg.m_nLosses;
402         m_nHiScore = dlg.m_nHiScore;
403         m_nVHiScore = dlg.m_nVHiScore;
404         m_nStreakW = dlg.m_nStreakW;
405         m_nStreakL = dlg.m_nStreakL;
406         m_nStreakC = dlg.m_nStreakC;*/
407 }
408
409
410 void MainWin::OnundoAction(void)
411 {
412         if (m_bCanUndo)
413         {
414                 for(int i=0; i<7; i++)
415                         for(int j=0; j<20; j++)
416                                 solBoard[i][j] = solBoardUndo[i][j];
417
418                 for(int i=0; i<24; i++)
419                         stack1[i] = stack1Undo[i], stack2[i] = stack2Undo[i];
420
421                 for(int i=0; i<4; i++)
422                         nAce[i] = nAceUndo[i];
423
424                 stack1p = stack1pUndo, stack2p = stack2pUndo;
425                 m_nScore = m_nScoreUndo;
426                 m_nExhaustedDeck = m_nExhaustedDeckUndo;
427                 m_nNumToSplay = m_nNumToSplayUndo;
428                 m_bShowX = m_bShowXUndo;
429
430                 OnUpdateScore(m_nScore);
431         }
432
433         m_bCanUndo = false;
434         gameBoard->update();  // wil wok?
435 }
436
437
438 void MainWin::OnGamePlay(void)
439 {
440         // Play a card from discard deck...
441         //NOTE: can reduce size by eliminating duplicate code in OnLButtonDown...
442         m_bCanUndo = true;
443
444         if (stack1p == -1)  // I.e. it's empty...
445         {
446                 // Scoring...
447                 if ((m_bDrawThree && (m_nExhaustedDeck == 3))
448                         || (!m_bDrawThree && (m_nExhaustedDeck == 1)))
449                 {
450                         if (!m_bVegasStyle)
451                         {
452                                 m_nExhaustedDeck = 0;
453                                 m_nScore -= (m_bDrawThree ? 20 : 100);
454
455                                 if (m_nScore < 0)
456                                         m_nScore = 0;
457
458                                 OnUpdateScore(m_nScore);
459                         }
460                 }
461
462                 if (!m_bVegasStyle || (m_bVegasStyle && ((m_bDrawThree && (m_nExhaustedDeck < 3))
463                                 || (!m_bDrawThree && (m_nExhaustedDeck < 1)))))
464                 {
465                         for(; stack2p!=-1; stack2p--)
466                                 stack1[++stack1p] = stack2[stack2p];
467
468 #if HAVE_SOUND
469                         if (bSoundOn)
470                                 PlaySound(IDW_CARDKNOCK);
471 #endif
472                 }
473         }
474         else
475         {
476                 m_nNumToSplay = 0;
477
478                 for(int i=0; i<(m_bDrawThree ? 3 : 1); i++)
479                 {
480                         if (stack1p != -1)  // I.e., there are cards left...
481                         {
482                                 stack2[++stack2p] = stack1[stack1p--];
483
484 #if HAVE_SOUND
485                                 if (bSoundOn)
486                                 {
487                                         PlaySound(IDW_CARDFLIP);
488                                         // Pause
489                                         gameBoard->Pause(55);
490                                 }
491 #endif
492
493                                 m_nNumToSplay++;
494                         }
495                 }
496
497                 if (stack1p == -1)  // This is done here because it's right!
498                 {
499                         m_nExhaustedDeck++;
500
501                         if (m_bVegasStyle && ((m_bDrawThree && (m_nExhaustedDeck == 3))
502                                 || (!m_bDrawThree && (m_nExhaustedDeck == 1))))
503                                 m_bShowX = true;
504                 }
505         }
506
507         if (bAutoRemove)
508                 gameBoard->HandleAutoRemove();
509
510         gameBoard->update();
511 }
512
513
514 #endif
515