1 /* ColorCode, a free MasterMind clone with built in solver
2  * Copyright (C) 2009  Dirk Laebisch
3  * http://www.laebisch.com/
4  *
5  * ColorCode is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * ColorCode is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with ColorCode. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <QtWidgets>
20 
21 #include "settings.h"
22 #include "ccsolver.h"
23 #include "colorcode.h"
24 #include "colorpeg.h"
25 #include "pegrow.h"
26 #include "rowhint.h"
27 #include "msg.h"
28 #include "background.h"
29 #include "about.h"
30 #include "prefdialog.h"
31 #include "solutionrow.h"
32 #include "graphicsbtn.h"
33 #include "pegfactory.h"
34 #include "gamenodisplay.h"
35 #include "timedisplay.h"
36 #include "timedisplaybg.h"
37 #include "highscore.h"
38 #include "gametablesdialog.h"
39 
40 using namespace std;
41 
42 ColorCode* ColorCode::INSTANCE = NULL;
43 
44 const QString ColorCode::VERSION = "0.8.5";
45 
46 volatile bool ColorCode::mNoAct       = false;
47 volatile bool ColorCode::mIgnoreGuess = false;
48 
49 const int ColorCode::STATE_NONE    = 0;
50 const int ColorCode::STATE_RUNNING = 1;
51 const int ColorCode::STATE_PAUSED  = 2;
52 const int ColorCode::STATE_WON     = 3;
53 const int ColorCode::STATE_LOST    = 4;
54 const int ColorCode::STATE_GAVE_UP = 5;
55 const int ColorCode::STATE_ERROR   = 6;
56 
57 const int ColorCode::MODE_HVM = 0;
58 const int ColorCode::MODE_MVH = 1;
59 
60 const int ColorCode::MAX_COLOR_CNT = 10;
61 const int ColorCode::MIN_COLOR_CNT = 2;
62 const int ColorCode::SOLUTION_ROW_IX = -1;
63 
64 const int ColorCode::LAYER_BG    = 1;
65 const int ColorCode::LAYER_ROWS  = 2;
66 const int ColorCode::LAYER_HINTS = 3;
67 const int ColorCode::LAYER_SOL   = 4;
68 const int ColorCode::LAYER_MSG   = 5;
69 const int ColorCode::LAYER_PEGS  = 6;
70 const int ColorCode::LAYER_BTNS  = 7;
71 const int ColorCode::LAYER_DRAG  = 8;
72 
73 const int ColorCode::LEVEL_SETTINGS[5][3] = {
74                                                 { 2, 2, 1},
75                                                 { 4, 3, 0},
76                                                 { 6, 4, 1},
77                                                 { 8, 4, 1},
78                                                 {10, 5, 1}
79                                             };
80 
81 
82 int ColorCode::mMaxRowCnt = 10;
83 int ColorCode::mRowY0     = 130;
84 int ColorCode::mColorCnt  = 0;
85 int ColorCode::mPegCnt    = 0;
86 int ColorCode::mDoubles   = 1;
87 int ColorCode::mXOffs     = 0;
88 int ColorCode::mMaxZ      = 0;
89 int ColorCode::mLevel     = -1;
90 int ColorCode::mGameMode  = ColorCode::MODE_HVM;
91 
92 QString ColorCode::GAME_TITLE = "";
93 
ColorCode()94 ColorCode::ColorCode()
95 {
96     SetState(STATE_NONE);
97 
98     GAME_TITLE = tr("ColorCode");
99 
100     setWindowTitle(GAME_TITLE + " ");
101     setWindowIcon(QIcon(QPixmap(":/img/cc16.png")));
102     setIconSize(QSize(16, 16));
103 
104     setMouseTracking(true);
105     setAttribute(Qt::WA_Hover, true);
106     setAttribute(Qt::WA_AlwaysShowToolTips, true);
107 
108     INSTANCE = this;
109 
110     QCoreApplication::setOrganizationName("dirks");
111     QCoreApplication::setOrganizationDomain("laebisch.com");
112     QCoreApplication::setApplicationName("colorcode");
113 
114     QTime midnight(0, 0, 0);
115     qsrand(midnight.secsTo(QTime::currentTime()));
116 
117     Init();
118 }
119 
~ColorCode()120 ColorCode::~ColorCode()
121 {
122     mIgnoreGuess = true;
123     mSettings->WriteSettings();
124     WaitForSolver();
125 }
126 
Init()127 void ColorCode::Init()
128 {
129     mGameTablesDialog = new GameTablesDialog(this);
130     mGameInput = NULL;
131     mFinishedGameInput = NULL;
132     mPrefDialog = NULL;
133     mSettings = GetSettings();
134     connect(mSettings, SIGNAL(ReadSettingsGamesDone()), mGameTablesDialog, SLOT(ReadSettingsGamesSlot()));
135     connect(this, SIGNAL(NewHighScoreSignal(CCGame*)), mGameTablesDialog, SLOT(InsertHighScoreSlot(CCGame*)));
136     connect(mGameTablesDialog, SIGNAL(NewGameInputSignal(CCGame*)), this, SLOT(NewGameInputSlot(CCGame*)));
137 
138     mSettings->Init();
139 
140     mHighScore = new HighScore();
141 
142     mCurRow         = NULL;
143     mColorCnt       = 0;
144     mGameCnt        = 0;
145     mGameId         = 0;
146     mGuessCnt       = 0;
147     mHintsCnt       = 0;
148     mSolverStrength = CCSolver::STRENGTH_HIGH;
149 
150     mOrigSize = NULL;
151 
152     mMenuBar = menuBar();
153 
154     // as long as menuBar's size is invalid populated initially ... done for 4.6
155 #ifdef Q_WS_X11
156 #if QT_VERSION < 0x040600
157     mScene = new QGraphicsScene(0, 0, 320, 580);
158 #else
159     mScene = new QGraphicsScene(0, 0, 320, 560);
160 #endif
161 #else
162     mScene = new QGraphicsScene(0, 0, 320, 560);
163 #endif
164 
165     mScene->setBackgroundBrush(QBrush(QColor("#b0b1b3")));
166 
167     mView = new QGraphicsView;
168     mView->setScene(mScene);
169     mView->setGeometry(0, 0, 320, 560);
170     mView->setDragMode(QGraphicsView::NoDrag);
171     mView->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
172     mView->setContextMenuPolicy(Qt::NoContextMenu);
173     mView->setAlignment(Qt::AlignCenter);
174     mView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
175     mView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
176     mView->setFrameStyle(QFrame::NoFrame);
177 
178     setCentralWidget(mView);
179 
180     mBg = new BackGround();
181     mScene->addItem(mBg);
182     mBg->setPos(0, 0);
183     mBg->setZValue(LAYER_BG);
184 
185     mMsg = new Msg;
186     mScene->addItem(mMsg);
187     mMsg->setPos(20, 0);
188     mMsg->setZValue(LAYER_MSG);
189 
190     mGameNoDisplay = new GameNoDisplay;
191     mScene->addItem(mGameNoDisplay);
192     mGameNoDisplay->setPos(10, 534);
193     mGameNoDisplay->setZValue(LAYER_MSG);
194 
195     mDoneBtn = new GraphicsBtn;
196     mDoneBtn->SetLabel(tr("Done"));
197     mScene->addItem(mDoneBtn);
198     mDoneBtn->setPos(84, 118);
199     mDoneBtn->setZValue(LAYER_BTNS);
200     mDoneBtn->ShowBtn(false);
201     connect(mDoneBtn, SIGNAL(BtnPressSignal(GraphicsBtn *)), this, SLOT(DoneBtnPressSlot(GraphicsBtn *)));
202 
203     mOkBtn = new GraphicsBtn;
204     mOkBtn->SetWidth(38);
205     mOkBtn->SetLabel("ok");
206     mScene->addItem(mOkBtn);
207     mOkBtn->setPos(5, 329);
208     mOkBtn->setZValue(LAYER_BTNS);
209     mOkBtn->ShowBtn(false);
210     connect(mOkBtn, SIGNAL(BtnPressSignal(GraphicsBtn *)), this, SLOT(DoneBtnPressSlot(GraphicsBtn *)));
211 
212     mTimerBtn = new GraphicsBtn;
213     mTimerBtn->SetWidth(261);
214     mTimerBtn->SetLabel("");
215     mScene->addItem(mTimerBtn);
216     mTimerBtn->setScale(0.44);
217     mTimerBtn->setPos(102, 110);
218     mTimerBtn->setZValue(LAYER_HINTS);
219     mTimerBtn->InvertStates();
220     mTimerBtn->ShowBtn(true);
221     connect(mTimerBtn, SIGNAL(BtnPressSignal(GraphicsBtn *)), this, SLOT(PauseGameSlot(GraphicsBtn *)));
222 
223     mSolutionRowBg = new GraphicsBtn;
224     mSolutionRowBg->SetEnabled(false);
225     mSolutionRowBg->SetWidth(219);
226     mSolutionRowBg->SetLabel("");
227     mScene->addItem(mSolutionRowBg);
228     mSolutionRowBg->setScale(1.14);
229     mSolutionRowBg->setPos(35, 66);
230     mSolutionRowBg->setZValue(LAYER_ROWS);
231     mSolutionRowBg->SetStatesOpacity(1.0, 0.1);
232     mSolutionRowBg->InvertStates();
233     mSolutionRowBg->ShowBtn(true);
234 
235     mPegFactory = new PegFactory();
236     connect(mPegFactory, SIGNAL(SnapPegSignal(ColorPeg*)), this, SLOT(SnapPegSlot(ColorPeg*)));
237 
238     mSolver = new CCSolver(this);
239     connect(mSolver, SIGNAL(finished()), this, SLOT(SetSolverGuessSlot()));
240     connect(mSolver, SIGNAL(GuessDoneSignal()), this, SLOT(SetSolverGuessSlot()));
241     mHintsDelayTimer = new QTimer();
242     mHintsDelayTimer->setSingleShot(true);
243     mHintsDelayTimer->setInterval(500);
244     connect(mHintsDelayTimer, SIGNAL(timeout()), this, SLOT(SetAutoHintsSlot()));
245 
246     mGameTimerBg = new TimeDisplayBg();
247     mScene->addItem(mGameTimerBg);
248     mGameTimerBg->setPos(50, 108);
249     mGameTimerBg->setZValue(LAYER_SOL);
250 
251     mGameTimer = new TimeDisplay();
252     mScene->addItem(mGameTimer);
253     mGameTimer->setPos(49, 109);
254     mGameTimer->setZValue(LAYER_MSG);
255 
256     InitActions();
257     InitMenus();
258     InitToolBars();
259 
260     statusBar()->setStyleSheet("QStatusBar::item { border: 0px solid black }; ");
261     mStatusLabel = new QLabel();
262     statusBar()->addPermanentWidget(mStatusLabel, 0);
263 
264     InitSolution();
265     InitRows();
266 
267     ApplySettingsSlot();
268 }
269 
InitSolution()270 void ColorCode::InitSolution()
271 {
272     mSolutionRow = new SolutionRow();
273     mSolutionRow->SetIx(SOLUTION_ROW_IX);
274     mSolutionRow->setPos(50, 68);
275     mSolutionRow->setZValue(LAYER_SOL);
276     mScene->addItem(mSolutionRow);
277     connect(mSolutionRow, SIGNAL(RemovePegSignal(ColorPeg*)), mPegFactory, SLOT(RemovePegSlot(ColorPeg*)));
278     connect(mSolutionRow, SIGNAL(RowSolutionSignal(int)), this, SLOT(RowSolutionSlot(int)));
279 }
280 
InitRows()281 void ColorCode::InitRows()
282 {
283     PegRow* row;
284     RowHint* hint;
285 
286     int xpos = 60;
287     int ypos = mRowY0;
288     int i;
289 
290     for (i = 0; i < mMaxRowCnt; ++i)
291     {
292         row = new PegRow();
293         row->SetIx(i);
294         row->setPos(QPoint(xpos, ypos + (mMaxRowCnt - (i + 1)) * 40));
295         row->setZValue(LAYER_ROWS);
296         row->SetActive(false);
297         mScene->addItem(row);
298         mPegRows[i] = row;
299         connect(row, SIGNAL(RemovePegSignal(ColorPeg*)), mPegFactory, SLOT(RemovePegSlot(ColorPeg*)));
300         connect(row, SIGNAL(RowSolutionSignal(int)), this, SLOT(RowSolutionSlot(int)));
301 
302         hint = new RowHint;
303         hint->SetIx(i);
304         hint->setPos(QPoint(4, ypos + (mMaxRowCnt - (i + 1)) * 40));
305         hint->setZValue(LAYER_HINTS);
306         hint->SetActive(false);
307         mScene->addItem(hint);
308         mHintBtns[i] = hint;
309         connect(hint, SIGNAL(HintPressedSignal(int)), this, SLOT(HintPressedSlot(int)));
310     }
311 }
312 
InitActions()313 void ColorCode::InitActions()
314 {
315     mActNewGame = new QAction(tr("&New Game"), this);
316     mActNewGame->setIcon(QIcon(":/img/document-new.png"));
317     mActNewGame->setShortcut(tr("Ctrl+N"));
318     connect(mActNewGame, SIGNAL(triggered()), this, SLOT(NewGameSlot()));
319 
320     mActSelectGame = new QAction(tr("&Start particular Game"), this);
321     mActSelectGame->setIcon(QIcon(":/img/document-new.png"));
322     mActSelectGame->setShortcut(tr("Ctrl+Alt+N"));
323     connect(mActSelectGame, SIGNAL(triggered()), mGameTablesDialog, SLOT(ShowInputSlot()));
324 
325     mActCopyGameNo = new QAction(tr("&Copy Game Number"), this);
326     mActCopyGameNo->setIcon(QIcon(":/img/edit-copy.png"));
327     mActCopyGameNo->setShortcut(tr("Ctrl+C"));
328     connect(mActCopyGameNo, SIGNAL(triggered()), this, SLOT(CopyGameNoSlot()));
329 
330     mActRestartGame = new QAction(tr("&Restart Game"), this);
331     mActRestartGame->setIcon(QIcon(":/img/view-refresh.png"));
332     mActRestartGame->setShortcut(tr("Ctrl+Shift+R"));
333     connect(mActRestartGame, SIGNAL(triggered()), this, SLOT(RestartGameSlot()));
334 
335     mActGiveIn = new QAction(tr("&Throw In The Towel"), this);
336     mActGiveIn->setIcon(QIcon(":/img/face-sad.png"));
337     mActGiveIn->setShortcut(tr("Ctrl+G"));
338     connect(mActGiveIn, SIGNAL(triggered()), this, SLOT(GiveInSlot()));
339 
340     mActPauseGame = new QAction(tr("&Have a Break"), this);
341     mActPauseGame->setIcon(QIcon(":/img/pause.png"));
342     mActPauseGame->setShortcut(tr("Ctrl+P"));
343     connect(mActPauseGame, SIGNAL(triggered()), this, SLOT(PauseGameSlot()));
344 
345     mActSaveGame = new QAction(tr("&Bookmark Current Game"), this);
346     mActSaveGame->setIcon(QIcon(":/img/bookmark_add.png"));
347     mActSaveGame->setShortcut(tr("Ctrl+B"));
348     connect(mActSaveGame, SIGNAL(triggered()), this, SLOT(SavePrevGameSlot()));
349 
350     mActShowHighScores = new QAction(tr("&Highscores"), this);
351     mActShowHighScores->setIcon(QIcon(":/img/games-highscores.png"));
352     mActShowHighScores->setShortcut(tr("Ctrl+Alt+H"));
353     connect(mActShowHighScores, SIGNAL(triggered()), mGameTablesDialog, SLOT(ShowHighSlot()));
354 
355     mActShowPrevGames = new QAction(tr("&Recent Games"), this);
356     mActShowPrevGames->setIcon(QIcon(":/img/history.png"));
357     mActShowPrevGames->setShortcut(tr("Ctrl+Alt+R"));
358     connect(mActShowPrevGames, SIGNAL(triggered()), mGameTablesDialog, SLOT(ShowPrevSlot()));
359 
360     mActShowSavedGames = new QAction(tr("&Bookmarks"), this);
361     mActShowSavedGames->setIcon(QIcon(":/img/bookmark.png"));
362     mActShowSavedGames->setShortcut(tr("Ctrl+Alt+B"));
363     connect(mActShowSavedGames, SIGNAL(triggered()), mGameTablesDialog, SLOT(ShowSavedSlot()));
364 
365     mActExit = new QAction(tr("E&xit"), this);
366     mActExit->setIcon(QIcon(":/img/application-exit.png"));
367     mActExit->setShortcut(tr("Ctrl+Q"));
368     connect(mActExit, SIGNAL(triggered()), this, SLOT(close()));
369 
370     mActShowToolbar = new QAction(tr("Show Toolbar"), this);
371     mActShowToolbar->setCheckable(true);
372     mActShowToolbar->setChecked(true);
373     mActShowToolbar->setShortcut(tr("Ctrl+Shift+T"));
374     connect(mActShowToolbar, SIGNAL(triggered()), this, SLOT(ShowToolbarSlot()));
375 
376     mActShowMenubar = new QAction(tr("Show Menubar"), this);
377     mActShowMenubar->setCheckable(true);
378     mActShowMenubar->setChecked(true);
379     mActShowMenubar->setShortcut(tr("Ctrl+M"));
380     connect(mActShowMenubar, SIGNAL(triggered()), this, SLOT(ShowMenubarSlot()));
381 
382     mActShowStatusbar = new QAction(tr("Show Statusbar"), this);
383     mActShowStatusbar->setCheckable(true);
384     mActShowStatusbar->setChecked(true);
385     mActShowStatusbar->setShortcut(tr("Ctrl+Shift+B"));
386     connect(mActShowStatusbar, SIGNAL(triggered()), this, SLOT(ShowStatusbarSlot()));
387 
388     mActShowTimer = new QAction(tr("Show Timer"), this);
389     mActShowTimer->setCheckable(true);
390     mActShowTimer->setChecked(true);
391     mActShowTimer->setShortcut(tr("Ctrl+T"));
392     connect(mActShowTimer, SIGNAL(triggered()), this, SLOT(ShowTimerSlot()));
393 
394     mActShowGameNo = new QAction(tr("Display Game Number"), this);
395     mActShowGameNo->setCheckable(true);
396     mActShowGameNo->setChecked(true);
397     mActShowGameNo->setShortcut(tr("Ctrl+Shift+N"));
398     connect(mActShowGameNo, SIGNAL(triggered()), this, SLOT(ShowGameNoSlot()));
399 
400     mActResetColorsOrder = new QAction(tr("Reset Color Order"), this);
401     mActResetColorsOrder->setShortcut(tr("Ctrl+Shift+C"));
402     connect(mActResetColorsOrder, SIGNAL(triggered()), mPegFactory, SLOT(ResetColorsOrderSlot()));
403 
404     mActShowIndicators = new QAction(tr("Show Indicators"), this);
405     mActShowIndicators->setCheckable(true);
406     mActShowIndicators->setChecked(false);
407     mActShowIndicators->setShortcut(tr("Ctrl+Shift+L"));
408     connect(mActShowIndicators, SIGNAL(triggered()), this, SLOT(SetIndicatorsSlot()));
409 
410     mActDoubles = new QAction(tr("Allow Pegs of the Same Color"), this);
411     mActDoubles->setCheckable(true);
412     mActDoubles->setChecked(true);
413     mActDoubles->setShortcut(tr("Ctrl+Shift+S"));
414     connect(mActDoubles, SIGNAL(triggered(bool)), this, SLOT(DoublesChangedSlot(bool)));
415 
416     mActDoublesIcon = new QAction(tr("Allow Pegs of Same Color"), this);
417     mActDoublesIcon->setCheckable(true);
418     mActDoublesIcon->setChecked(true);
419     mActDoublesIcon->setToolTip(tr("Disallow Pegs of Same Color"));
420     mActDoublesIcon->setIcon(QIcon(":/img/same_color_1.png"));
421     connect(mActDoublesIcon, SIGNAL(triggered(bool)), this, SLOT(DoublesChangedSlot(bool)));
422 
423     mActAutoClose = new QAction(tr("Close Rows when the last Peg is placed"), this);
424     mActAutoClose->setCheckable(true);
425     mActAutoClose->setChecked(false);
426     mActAutoClose->setShortcut(tr("Ctrl+L"));
427     connect(mActAutoClose, SIGNAL(triggered()), this, SLOT(AutoCloseSlot()));
428 
429     mActAutoHints = new QAction(tr("Set Hints automatically"), this);
430     mActAutoHints->setCheckable(true);
431     mActAutoHints->setChecked(false);
432     mActAutoHints->setShortcut(tr("Ctrl+Shift+H"));
433     connect(mActAutoHints, SIGNAL(triggered()), this, SLOT(AutoHintsSlot()));
434 
435     mLaunchHelpAction = new QAction(tr("Online &Help"), this);
436     mLaunchHelpAction->setIcon(QIcon(":/img/help.png"));
437     mLaunchHelpAction->setShortcut(tr("F1"));
438     connect(mLaunchHelpAction, SIGNAL(triggered()), this, SLOT(OnlineHelpSlot()));
439 
440     mActAbout = new QAction(tr("About &ColorCode"), this);
441     mActAbout->setIcon(QIcon(":/img/help-about.png"));
442     mActAbout->setShortcut(tr("Ctrl+A"));
443     connect(mActAbout, SIGNAL(triggered()), this, SLOT(AboutSlot()));
444 
445     mActAboutQt = new QAction(tr("About &Qt"), this);
446     mActAboutQt->setIcon(QIcon(":/img/qt.png"));
447     mActAboutQt->setShortcut(tr("Ctrl+I"));
448     connect(mActAboutQt, SIGNAL(triggered()), this, SLOT(AboutQtSlot()));
449 
450     mActRandRow = new QAction(tr("Fill Row by Random"), this);
451     mActRandRow->setIcon(QIcon(":/img/system-switch-user.png"));
452     mActRandRow->setShortcut(tr("Ctrl+R"));
453     connect(mActRandRow, SIGNAL(triggered()), this, SLOT(RandRowSlot()));
454 
455     mActPrevRow = new QAction(tr("Duplicate Previous Row"), this);
456     mActPrevRow->setIcon(QIcon(":/img/edit-copy.png"));
457     mActPrevRow->setShortcut(tr("Ctrl+D"));
458     connect(mActPrevRow, SIGNAL(triggered()), this, SLOT(PrevRowSlot()));
459 
460     mActClearRow = new QAction(tr("Clear Row"), this);
461     mActClearRow->setIcon(QIcon(":/img/edit-clear.png"));
462     mActClearRow->setShortcut(tr("Ctrl+Alt+C"));
463     connect(mActClearRow, SIGNAL(triggered()), this, SLOT(ClearRowSlot()));
464 
465     mActLevelEasy = new QAction(tr("Beginner (2 Colors, 2 Slots, Doubles)"), this);
466     mActLevelEasy->setData(0);
467     mActLevelEasy->setCheckable(true);
468     mActLevelEasy->setChecked(false);
469     connect(mActLevelEasy, SIGNAL(triggered()), this, SLOT(SetLevelSlot()));
470 
471     mActLevelClassic = new QAction(tr("Easy (4 Colors, 3 Slots, No Doubles)"), this);
472     mActLevelClassic->setData(1);
473     mActLevelClassic->setCheckable(true);
474     mActLevelClassic->setChecked(false);
475     connect(mActLevelClassic, SIGNAL(triggered()), this, SLOT(SetLevelSlot()));
476 
477     mActLevelMedium = new QAction(tr("Classic (6 Colors, 4 Slots, Doubles)"), this);
478     mActLevelMedium->setData(2);
479     mActLevelMedium->setCheckable(true);
480     mActLevelMedium->setChecked(true);
481     connect(mActLevelMedium, SIGNAL(triggered()), this, SLOT(SetLevelSlot()));
482 
483     mActLevelChallenging = new QAction(tr("Challenging (8 Colors, 4 Slots, Doubles)"), this);
484     mActLevelChallenging->setData(3);
485     mActLevelChallenging->setCheckable(true);
486     mActLevelChallenging->setChecked(false);
487     connect(mActLevelChallenging, SIGNAL(triggered()), this, SLOT(SetLevelSlot()));
488 
489     mActLevelHard = new QAction(tr("Hard (10 Colors, 5 Slots, Doubles)"), this);
490     mActLevelHard->setData(4);
491     mActLevelHard->setCheckable(true);
492     mActLevelHard->setChecked(false);
493     connect(mActLevelHard, SIGNAL(triggered()), this, SLOT(SetLevelSlot()));
494 
495     mActSetGuess = new QAction(tr("Computer's Guess"), this);
496     mActSetGuess->setIcon(QIcon(":/img/business_user.png"));
497     mActSetGuess->setShortcut(tr("Ctrl+H"));
498     connect(mActSetGuess, SIGNAL(triggered()), this, SLOT(SetGuessSlot()));
499 
500     mActSetHints = new QAction(tr("Rate it for me"), this);
501     mActSetHints->setIcon(QIcon(":/img/icon_female16.png"));
502     mActSetHints->setShortcut(tr("Ctrl+H"));
503     connect(mActSetHints, SIGNAL(triggered()), this, SLOT(SetHintsSlot()));
504 
505     mActModeHvM = new QAction(tr("Human vs Computer"), this);
506     mActModeHvM->setData(MODE_HVM);
507     mActModeHvM->setCheckable(true);
508     mActModeHvM->setChecked(true);
509     connect(mActModeHvM, SIGNAL(triggered()), this, SLOT(SetGameModeSlot()));
510 
511     mActModeMvH = new QAction(tr("Computer vs Human"), this);
512     mActModeMvH->setData(MODE_MVH);
513     mActModeMvH->setCheckable(true);
514     mActModeMvH->setChecked(false);
515     connect(mActModeMvH, SIGNAL(triggered()), this, SLOT(SetGameModeSlot()));
516 
517     mActPreferences = new QAction(tr("Preferences"), this);
518     mActPreferences->setIcon(QIcon(":/img/configure.png"));
519     mActPreferences->setShortcut(tr("Ctrl+Shift+P"));
520     connect(mActPreferences, SIGNAL(triggered()), this, SLOT(OpenPreferencesSlot()));
521 }
522 
InitMenus()523 void ColorCode::InitMenus()
524 {
525     mMenuGame = mMenuBar->addMenu(tr("&Game"));
526     mMenuGame->addAction(mActNewGame);
527     mMenuGame->addAction(mActSelectGame);
528     mMenuGame->addAction(mActRestartGame);
529     mMenuGame->addSeparator();
530     mMenuGame->addAction(mActPauseGame);
531     mMenuGame->addAction(mActGiveIn);
532     mMenuGame->addSeparator();
533     mMenuGame->addAction(mActCopyGameNo);
534     mMenuGame->addAction(mActSaveGame);
535     mMenuGame->addSeparator();
536     mMenuGame->addAction(mActExit);
537 
538     mMenuRow = mMenuBar->addMenu(tr("&Row"));
539     mMenuRow->addAction(mActRandRow);
540     mMenuRow->addAction(mActPrevRow);
541     mMenuRow->addAction(mActClearRow);
542     mMenuRow->addSeparator();
543     mMenuRow->addAction(mActSetGuess);
544     mMenuRow->addAction(mActSetHints);
545     connect(mMenuRow, SIGNAL(aboutToShow()), this, SLOT(UpdateRowMenuSlot()));
546 
547 
548     mMenuGames = mMenuBar->addMenu(tr("Game &Lists"));
549 
550     mMenuGames->addAction(mActShowHighScores);
551     mMenuGames->addAction(mActShowSavedGames);
552     mMenuGames->addAction(mActShowPrevGames);
553 
554 
555     mMenuSettings = mMenuBar->addMenu(tr("&Settings"));
556 
557     mMenuModes = mMenuSettings->addMenu(tr("Game Mode"));
558     mActGroupModes = new QActionGroup(mMenuModes);
559     mActGroupModes->setExclusive(true);
560     mActGroupModes->addAction(mActModeHvM);
561     mActGroupModes->addAction(mActModeMvH);
562     QList<QAction *> modeacts = mActGroupModes->actions();
563     mMenuModes->addActions(modeacts);
564     mMenuSettings->addSeparator();
565 
566     mMenuSettings->addAction(mActShowMenubar);
567     mMenuSettings->addAction(mActShowToolbar);
568     mMenuSettings->addAction(mActShowStatusbar);
569     mMenuSettings->addSeparator();
570     mMenuSettings->addAction(mActShowTimer);
571     mMenuSettings->addAction(mActShowGameNo);
572     mMenuSettings->addSeparator();
573     mMenuSettings->addAction(mActResetColorsOrder);
574     mMenuSettings->addAction(mActShowIndicators);
575     mMenuSettings->addSeparator();
576 
577     mMenuLevels = mMenuSettings->addMenu(tr("Level Presets"));
578     mActGroupLevels = new QActionGroup(mMenuLevels);
579     mActGroupLevels->addAction(mActLevelEasy);
580     mActGroupLevels->addAction(mActLevelClassic);
581     mActGroupLevels->addAction(mActLevelMedium);
582     mActGroupLevels->addAction(mActLevelChallenging);
583     mActGroupLevels->addAction(mActLevelHard);
584     QList<QAction *> levelacts = mActGroupLevels->actions();
585     mMenuLevels->addActions(levelacts);
586     mMenuSettings->addSeparator();
587 
588     mMenuSettings->addAction(mActDoubles);
589     mMenuSettings->addSeparator();
590 
591     mMenuSettings->addAction(mActAutoClose);
592     mMenuSettings->addAction(mActAutoHints);
593 
594     mMenuSettings->addSeparator();
595     mMenuSettings->addAction(mActPreferences);
596 
597 
598     mMenuHelp = mMenuBar->addMenu(tr("&Help"));
599     mMenuHelp->addAction(mLaunchHelpAction);
600     mMenuHelp->addSeparator();
601     mMenuHelp->addAction(mActAbout);
602     mMenuHelp->addAction(mActAboutQt);
603 
604     mMenuRowContext = new QMenu();
605     mMenuRowContext->addAction(mActRandRow);
606     mMenuRowContext->addAction(mActPrevRow);
607     mMenuRowContext->addAction(mActClearRow);
608     mMenuRowContext->addSeparator();
609     mMenuRowContext->addAction(mActSetGuess);
610     mMenuRowContext->addAction(mActSetHints);
611     mMenuRowContext->addSeparator();
612     mMenuRowContext->addAction(mActNewGame);
613     mMenuRowContext->addAction(mActRestartGame);
614     mMenuRowContext->addAction(mActGiveIn);
615     mMenuRowContext->addSeparator();
616     mMenuRowContext->addAction(mActExit);
617 
618     addActions(mMenuBar->actions());
619 }
620 
InitToolBars()621 void ColorCode::InitToolBars()
622 {
623     mGameToolbar = addToolBar(tr("Game"));
624     mGameToolbar->setAllowedAreas(Qt::NoToolBarArea);
625     mGameToolbar->setFloatable(false);
626     mGameToolbar->setIconSize(QSize(16, 16));
627     mGameToolbar->setMovable(false);
628     mGameToolbar->addAction(mActNewGame);
629     mGameToolbar->addAction(mActRestartGame);
630     mGameToolbar->addAction(mActGiveIn);
631     mGameToolbar->addSeparator();
632     mGameToolbar->addAction(mActSetGuess);
633     mGameToolbar->addAction(mActSetHints);
634 
635     mColorCntCmb = new QComboBox();
636     mColorCntCmb->setLayoutDirection(Qt::LeftToRight);
637     mColorCntCmb->setFixedWidth(84);
638     mColorCntCmb->addItem("2 " + tr("Colors"), 2);
639     mColorCntCmb->addItem("3 " + tr("Colors"), 3);
640     mColorCntCmb->addItem("4 " + tr("Colors"), 4);
641     mColorCntCmb->addItem("5 " + tr("Colors"), 5);
642     mColorCntCmb->addItem("6 " + tr("Colors"), 6);
643     mColorCntCmb->addItem("7 " + tr("Colors"), 7);
644     mColorCntCmb->addItem("8 " + tr("Colors"), 8);
645     mColorCntCmb->addItem("9 " + tr("Colors"), 9);
646     mColorCntCmb->addItem("10 " + tr("Colors"), 10);
647     mColorCntCmb->setCurrentIndex(6);
648     connect(mColorCntCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(ColorCntChangedSlot()));
649 
650     mPegCntCmb = new QComboBox();
651     mPegCntCmb->setLayoutDirection(Qt::LeftToRight);
652     mPegCntCmb->setFixedWidth(76);
653     mPegCntCmb->addItem("2 " + tr("Slots"), 2);
654     mPegCntCmb->addItem("3 " + tr("Slots"), 3);
655     mPegCntCmb->addItem("4 " + tr("Slots"), 4);
656     mPegCntCmb->addItem("5 " + tr("Slots"), 5);
657     mPegCntCmb->setCurrentIndex(2);
658     connect(mPegCntCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(PegCntChangedSlot()));
659 
660     mLevelToolbar = addToolBar(tr("Level"));
661     mLevelToolbar->setAllowedAreas(Qt::NoToolBarArea);
662     mLevelToolbar->setFloatable(false);
663     mLevelToolbar->setIconSize(QSize(16, 16));
664     mLevelToolbar->setMovable(false);
665     mLevelToolbar->setLayoutDirection(Qt::RightToLeft);
666     mLevelToolbar->addWidget(mColorCntCmb);
667     QWidget* spacer = new QWidget();
668     spacer->setMinimumWidth(4);
669     mLevelToolbar->addWidget(spacer);
670     mLevelToolbar->addWidget(mPegCntCmb);
671     QWidget* spacer2 = new QWidget();
672     spacer2->setMinimumWidth(4);
673     mLevelToolbar->addWidget(spacer2);
674     mLevelToolbar->addAction(mActDoublesIcon);
675 }
676 
ApplySettingsSlot()677 void ColorCode::ApplySettingsSlot()
678 {
679     bool restart = NeedsRestart();
680     mNoAct = true;
681 
682     mActShowToolbar->setChecked(mSettings->mShowToolBar);
683     ShowToolbarSlot();
684     mActShowMenubar->setChecked(mSettings->mShowMenuBar);
685     ShowMenubarSlot();
686     mActShowStatusbar->setChecked(mSettings->mShowStatusBar);
687     ShowStatusbarSlot();
688     mActShowTimer->setChecked(mSettings->mShowTimer);
689     ShowTimer();
690     mActShowGameNo->setChecked(mSettings->mShowGameNo);
691     UpdateGameNoDisplay();
692     mActShowIndicators->setChecked(mSettings->mShowIndicators);
693     SetIndicatorsSlot();
694 
695     mActAutoClose->setChecked(mSettings->mAutoClose);
696     mActAutoHints->setChecked(mSettings->mAutoHints);
697 
698     SetDoublesSlot(mSettings->mDoubles);
699     int i;
700     i = mColorCntCmb->findData(mSettings->mColorCnt);
701     if (i != -1 && mColorCntCmb->currentIndex() != i)
702     {
703         mColorCntCmb->setCurrentIndex(i);
704     }
705     i = mPegCntCmb->findData(mSettings->mPegCnt);
706     if (i != -1 && mPegCntCmb->currentIndex() != i)
707     {
708         mPegCntCmb->setCurrentIndex(i);
709     }
710     CheckLevel();
711 
712     if (mSettings->mGameMode == MODE_HVM)
713     {
714         mActModeHvM->setChecked(true);
715         UpdateGameNoDisplay();
716     }
717     else
718     {
719         mActModeMvH->setChecked(true);
720     }
721 
722     mHintsDelayTimer->setInterval(mSettings->mHintsDelay);
723 
724     mNoAct = false;
725 
726     if (restart)
727     {
728         TryNewGame();
729     }
730 }
731 
TryNewGame()732 void ColorCode::TryNewGame()
733 {
734     int r = QMessageBox::Yes;
735     if (GamesRunning())
736     {
737         r = QMessageBox::question( this,
738                                    tr("Message"),
739                                    tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"),
740                                    QMessageBox::Yes | QMessageBox::No,
741                                    QMessageBox::Yes);
742     }
743 
744     if (r == QMessageBox::Yes)
745     {
746         mGameInput = NULL;
747         NewGame();
748     }
749 }
750 
NeedsRestart() const751 bool ColorCode::NeedsRestart() const
752 {
753     bool need = false;
754 
755     if ( mSettings->mDoubles != mActDoubles->isChecked()
756         || mSettings->mColorCnt != mColorCnt
757         || mSettings->mPegCnt != mPegCnt
758         || mSettings->mGameMode != mGameMode
759         || (mGameMode == MODE_MVH && mSolverStrength != mSettings->mSolverStrength) )
760     {
761         need = true;
762     }
763 
764     return need;
765 }
766 
contextMenuEvent(QContextMenuEvent * e)767 void ColorCode::contextMenuEvent(QContextMenuEvent* e)
768 {
769 
770     QList<QGraphicsItem *> list = mView->items(mView->mapFromGlobal(e->globalPos()));
771     int i = 0;
772     bool isrow = false;
773     if (mGameState == STATE_RUNNING && mCurRow != NULL)
774     {
775         for (i = 0; i < list.size(); ++i)
776         {
777             if (list.at(i) == mCurRow || list.at(i) == mHintBtns[mCurRow->GetIx()])
778             {
779                  isrow = true;
780                  break;
781             }
782         }
783     }
784 
785     if (isrow)
786     {
787         UpdateRowMenuSlot();
788         mMenuRowContext->exec(e->globalPos());
789     }
790     else
791     {
792         mMenuGame->exec(e->globalPos());
793     }
794 }
795 
resizeEvent(QResizeEvent * e)796 void ColorCode::resizeEvent (QResizeEvent* e)
797 {
798     Q_UNUSED(e);
799     Scale();
800 }
801 
keyPressEvent(QKeyEvent * e)802 void ColorCode::keyPressEvent(QKeyEvent *e)
803 {
804     if (mCurRow == NULL || mGameState != STATE_RUNNING)
805     {
806         return;
807     }
808 
809     switch (e->key())
810     {
811         case Qt::Key_Return:
812         case Qt::Key_Enter:
813             if (mGameMode == MODE_HVM)
814             {
815                 int ix = mCurRow->GetIx();
816                 if (mHintBtns[ix]->mActive)
817                 {
818                     std::vector<int> s = mCurRow->GetSolution();
819                     if (s.size() == (unsigned) mPegCnt)
820                     {
821                         mHintBtns[ix]->SetActive(false);
822                         HintPressedSlot(ix);
823                     }
824                 }
825             }
826             else if (mGameMode == MODE_MVH)
827             {
828                 if (mDoneBtn->isVisible() || mOkBtn->isVisible())
829                 {
830                     DoneBtnPressSlot(mOkBtn);
831                 }
832             }
833         break;
834     }
835 }
836 
UpdateActions()837 void ColorCode::UpdateActions()
838 {
839     if (mGameState == STATE_PAUSED)
840     {
841         mActSelectGame->setEnabled(true);
842         mActSaveGame->setEnabled(true);
843         mActSetGuess->setEnabled(false);
844         mActRestartGame->setEnabled(false);
845         mActGiveIn->setEnabled(false);
846         return;
847     }
848 
849     bool running = (mGameState == STATE_RUNNING && mCurRow != NULL);
850     if (mGameMode == MODE_HVM)
851     {
852         mActSelectGame->setVisible(true);
853         mActSelectGame->setEnabled(true);
854         mActSaveGame->setVisible(true);
855         mActSaveGame->setEnabled(true);
856         mActPauseGame->setVisible(true);
857         mActShowTimer->setVisible(true);
858         mActShowTimer->setEnabled(true);
859         mActShowGameNo->setVisible(true);
860         mActShowGameNo->setEnabled(true);
861         mActCopyGameNo->setVisible(true);
862         mActCopyGameNo->setEnabled(true);
863         if (running)
864         {
865             mActSetGuess->setEnabled(true);
866             mActRestartGame->setEnabled(true);
867             mActGiveIn->setEnabled(true);
868             mActPauseGame->setEnabled(true);
869         }
870         else
871         {
872             mActSetGuess->setEnabled(false);
873             mActRestartGame->setEnabled(false);
874             mActGiveIn->setEnabled(false);
875             mActPauseGame->setEnabled(false);
876         }
877     }
878     else if (mGameMode == MODE_MVH)
879     {
880         mActSelectGame->setVisible(false);
881         mActSelectGame->setEnabled(false);
882         mActSaveGame->setVisible(false);
883         mActSaveGame->setEnabled(false);
884         mActPauseGame->setVisible(false);
885         mActPauseGame->setEnabled(false);
886         mActShowTimer->setVisible(false);
887         mActShowTimer->setEnabled(false);
888         mActShowGameNo->setVisible(false);
889         mActShowGameNo->setEnabled(false);
890         mActCopyGameNo->setVisible(false);
891         mActCopyGameNo->setEnabled(false);
892         if (running)
893         {
894             mActRestartGame->setEnabled(true);
895             mActGiveIn->setEnabled(true);
896             if (mCurRow == mSolutionRow)
897             {
898                 mActSetHints->setEnabled(false);
899             }
900             else
901             {
902                 mActSetHints->setEnabled(!mSettings->mAutoHints && !mSolver->isRunning());
903             }
904             UpdateRowMenuSlot();
905         }
906         else
907         {
908             mActSetHints->setEnabled(false);
909             mActRestartGame->setEnabled(false);
910             mActGiveIn->setEnabled(false);
911         }
912     }
913 }
914 
UpdateRowMenuSlot()915 void ColorCode::UpdateRowMenuSlot()
916 {
917     if (mGameMode == MODE_HVM)
918     {
919         if (mGameState != STATE_RUNNING || mCurRow == NULL)
920         {
921             mActRandRow->setEnabled(false);
922             mActPrevRow->setEnabled(false);
923             mActClearRow->setEnabled(false);
924             mActSetGuess->setEnabled(false);
925             return;
926         }
927         else
928         {
929             mActRandRow->setEnabled(true);
930         }
931 
932         if (mCurRow->GetIx() < 1)
933         {
934             mActPrevRow->setEnabled(false);
935         }
936         else
937         {
938             mActPrevRow->setEnabled(true);
939         }
940 
941         if (mCurRow->GetPegCnt() == 0)
942         {
943             mActClearRow->setEnabled(false);
944         }
945         else
946         {
947             mActClearRow->setEnabled(true);
948         }
949     }
950     else if (mGameMode == MODE_MVH)
951     {
952         if (mGameState == STATE_RUNNING)
953         {
954             if (mCurRow == mSolutionRow)
955             {
956                 mActSetHints->setEnabled(false);
957                 mActRandRow->setEnabled(true);
958                 if (mSolutionRow->GetPegCnt() == 0)
959                 {
960                     mActClearRow->setEnabled(false);
961                 }
962                 else
963                 {
964                     mActClearRow->setEnabled(true);
965                 }
966             }
967             else
968             {
969                 mActSetHints->setEnabled(!mSettings->mAutoHints && !mSolver->isRunning());
970                 mActRandRow->setEnabled(false);
971                 mActClearRow->setEnabled(false);
972             }
973         }
974         else
975         {
976             mActRandRow->setEnabled(false);
977             mActClearRow->setEnabled(false);
978             mActSetHints->setEnabled(false);
979         }
980     }
981 }
982 
PauseGameSlot(GraphicsBtn *)983 void ColorCode::PauseGameSlot(GraphicsBtn*)
984 {
985     if (mCurRow == NULL)
986     {
987         return;
988     }
989 
990     bool paused = (mGameState == STATE_PAUSED);
991     if (mGameState == STATE_RUNNING)
992     {
993         mGameTimer->PauseT();
994         mActPauseGame->setText(tr("&Resume Game"));
995         mActPauseGame->setIcon(QIcon(":/img/resume.png"));
996         SetState(STATE_PAUSED);
997         UpdateGameNoDisplay();
998         ResolveGame();
999     }
1000     else if (paused)
1001     {
1002         mGameTimer->ResumeT();
1003         mActPauseGame->setText(tr("&Have a Break"));
1004         mActPauseGame->setIcon(QIcon(":/img/pause.png"));
1005         SetState(STATE_RUNNING);
1006         UpdateGameNoDisplay();
1007         RowSolutionSlot(mCurRow->GetIx());
1008     }
1009     mPegFactory->SetPaused();
1010     for (int i = 0; i < mMaxRowCnt; ++i)
1011     {
1012         mHintBtns[i]->SetPaused(paused);
1013     }
1014     UpdateActions();
1015 }
1016 
RestartGameSlot()1017 void ColorCode::RestartGameSlot()
1018 {
1019     if (mSolver->isRunning())
1020     {
1021         WaitForSolver();
1022     }
1023 
1024     if (mGameMode == MODE_HVM)
1025     {
1026         ResetRows();
1027         SetState(STATE_RUNNING);
1028         SetCurRow(NULL);
1029         mSolver->RestartGame();
1030         NextRow();
1031     }
1032     else if (mGameMode == MODE_MVH)
1033     {
1034         mHintsDelayTimer->stop();
1035         mOkBtn->ShowBtn(false);
1036         ResetRows();
1037 
1038         SetCurRow(NULL);
1039         mSolver->NewGame(mColorCnt, mPegCnt, mDoubles, mSolverStrength, mMaxRowCnt);
1040         mSolutionRow->OpenRow();
1041         GetSolution();
1042         SetState(STATE_RUNNING);
1043         RowSolutionSlot(mSolutionRow->GetIx());
1044     }
1045 }
1046 
NewGameSlot()1047 void ColorCode::NewGameSlot()
1048 {
1049     if (mGameState == STATE_RUNNING && mCurRow != NULL)
1050     {
1051         int r = QMessageBox::warning( this,
1052                                       tr("New Game"),
1053                                       tr("Do you want to give in\nand start a new Game?"),
1054                                       QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
1055         if (r == QMessageBox::Yes)
1056         {
1057             mGameInput = NULL;
1058             NewGame();
1059         }
1060     }
1061     else
1062     {
1063         mGameInput = NULL;
1064         NewGame();
1065     }
1066 }
1067 
GiveInSlot()1068 void ColorCode::GiveInSlot()
1069 {
1070     int r = QMessageBox::Yes;
1071     if (mGameState == STATE_RUNNING && mCurRow != NULL)
1072     {
1073         r = QMessageBox::warning( this,
1074                                   tr("Give In"),
1075                                   tr("Do you really want to give in?"),
1076                                   QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
1077     }
1078 
1079     if (r == QMessageBox::Yes)
1080     {
1081         SetState(STATE_GAVE_UP);
1082 
1083         if (mSolver->isRunning())
1084         {
1085             WaitForSolver();
1086         }
1087 
1088         if (mCurRow != NULL)
1089         {
1090             mCurRow->CloseRow();
1091             mHintBtns[mCurRow->GetIx()]->SetActive(false);
1092         }
1093 
1094         ResolveGame();
1095     }
1096 }
1097 
CopyGameNoSlot()1098 void ColorCode::CopyGameNoSlot()
1099 {
1100     uint no = 0;
1101     if (mGameInput != NULL)
1102     {
1103         no = mGameInput->mGameNo;
1104     }
1105     else if (mFinishedGameInput != NULL)
1106     {
1107         no = mFinishedGameInput->mGameNo;
1108     }
1109 
1110     if (no > 0)
1111     {
1112         QClipboard* cb = QApplication::clipboard();
1113         cb->setText(QString::number(no));
1114     }
1115 }
1116 
OpenPreferencesSlot()1117 void ColorCode::OpenPreferencesSlot()
1118 {
1119     if (mPrefDialog == NULL)
1120     {
1121         CreatePrefDialog();
1122     }
1123     if (mPrefDialog == NULL)
1124     {
1125         return;
1126     }
1127 
1128     mSettings->SaveLastSettings();
1129     mPrefDialog->SetSettings();
1130     int r = mPrefDialog->exec();
1131 
1132     if (r == QDialog::Accepted)
1133     {
1134         ApplySettingsSlot();
1135     }
1136     else
1137     {
1138         mSettings->RestoreLastSettings();
1139     }
1140 }
1141 
OnlineHelpSlot()1142 void ColorCode::OnlineHelpSlot()
1143 {
1144     QDesktopServices::openUrl(QUrl("http://colorcode.laebisch.com/documentation", QUrl::TolerantMode));
1145 }
1146 
AboutSlot()1147 void ColorCode::AboutSlot()
1148 {
1149     About ab(this);
1150     ab.exec();
1151 }
1152 
AboutQtSlot()1153 void ColorCode::AboutQtSlot()
1154 {
1155     QMessageBox::aboutQt( this,
1156                         tr("About Qt"));
1157 }
1158 
ShowToolbarSlot()1159 void ColorCode::ShowToolbarSlot()
1160 {
1161     mSettings->mShowToolBar = mActShowToolbar->isChecked();
1162     if (!mActShowToolbar->isChecked())
1163     {
1164         mGameToolbar->hide();
1165         mLevelToolbar->hide();
1166     }
1167     else
1168     {
1169         mGameToolbar->show();
1170         mLevelToolbar->show();
1171     }
1172     Scale();
1173 }
1174 
ShowMenubarSlot()1175 void ColorCode::ShowMenubarSlot()
1176 {
1177     mSettings->mShowMenuBar = mActShowMenubar->isChecked();
1178     if (!mActShowMenubar->isChecked())
1179     {
1180         mMenuBar->hide();
1181     }
1182     else
1183     {
1184         mMenuBar->show();
1185     }
1186     Scale();
1187 }
1188 
ShowStatusbarSlot()1189 void ColorCode::ShowStatusbarSlot()
1190 {
1191     mSettings->mShowStatusBar = mActShowStatusbar->isChecked();
1192     if (!mActShowStatusbar->isChecked())
1193     {
1194         statusBar()->hide();
1195     }
1196     else
1197     {
1198         statusBar()->show();
1199     }
1200     Scale();
1201 }
1202 
ShowTimerSlot()1203 void ColorCode::ShowTimerSlot()
1204 {
1205     mSettings->mShowTimer = mActShowTimer->isChecked();
1206     ShowTimer();
1207 }
1208 
ShowTimer()1209 void ColorCode::ShowTimer()
1210 {
1211     if (mGameMode == MODE_HVM)
1212     {
1213         mGameTimer->SetTenth(mSettings->mShowTenth);
1214         mGameTimer->setVisible(mSettings->mShowTimer);
1215         mGameTimer->update();
1216         mGameTimerBg->setVisible(mSettings->mShowTimer);
1217         mTimerBtn->ShowBtn(mSettings->mShowTimer);
1218     }
1219     else
1220     {
1221         mGameTimer->setVisible(false);
1222         mGameTimerBg->setVisible(false);
1223         mTimerBtn->ShowBtn(false);
1224     }
1225 }
1226 
ShowGameNoSlot()1227 void ColorCode::ShowGameNoSlot()
1228 {
1229     mSettings->mShowGameNo = mActShowGameNo->isChecked();
1230     UpdateGameNoDisplay();
1231 }
1232 
UpdateGameNoDisplay()1233 void ColorCode::UpdateGameNoDisplay()
1234 {
1235     if (mGameMode == MODE_HVM)
1236     {
1237         QString str = tr("Human vs. Computer");
1238         CCGame* g = GetCurrentGameInput();
1239         if (mSettings->mShowGameNo && g != NULL && mGameState != STATE_PAUSED)
1240         {
1241             str += QString(" :: ") + QString(tr("Game Number")) + QString(": ") + QString::number(g->mGameNo);
1242         }
1243         mGameNoDisplay->ShowStr(str);
1244     }
1245     else if (mGameMode == MODE_MVH)
1246     {
1247         mGameNoDisplay->ShowStr(tr("Computer vs. Human"));
1248     }
1249 }
1250 
GetCurrentGameInput() const1251 CCGame* ColorCode::GetCurrentGameInput() const
1252 {
1253     if (mGameInput != NULL && mGameInput->IsValidGame())
1254     {
1255         return mGameInput;
1256     }
1257     else if (mFinishedGameInput != NULL && mFinishedGameInput->IsValidGame())
1258     {
1259         return mFinishedGameInput;
1260     }
1261     return NULL;
1262 }
1263 
CloseHighScoreDialogSlot()1264 void ColorCode::CloseHighScoreDialogSlot()
1265 {
1266     ;
1267 }
1268 
SetIndicatorsSlot()1269 void ColorCode::SetIndicatorsSlot()
1270 {
1271     mSettings->mShowIndicators = mActShowIndicators->isChecked();
1272     mPegFactory->SetIndicators();
1273 }
1274 
AutoCloseSlot()1275 void ColorCode::AutoCloseSlot()
1276 {
1277     mSettings->mAutoClose = mActAutoClose->isChecked();
1278 }
1279 
AutoHintsSlot()1280 void ColorCode::AutoHintsSlot()
1281 {
1282     mSettings->mAutoHints = mActAutoHints->isChecked();
1283 
1284     if (mGameMode == MODE_MVH && mGameState == STATE_RUNNING && mCurRow != NULL && mCurRow != mSolutionRow)
1285     {
1286         mActSetHints->setEnabled(!mSettings->mAutoHints);
1287         if (mSettings->mAutoHints)
1288         {
1289             SetHintsSlot();
1290             SetAutoHintsSlot();
1291         }
1292     }
1293 }
1294 
ColorCntChangedSlot()1295 void ColorCode::ColorCntChangedSlot()
1296 {
1297     SetColorCnt();
1298 
1299     if (mNoAct)
1300     {
1301         return;
1302     }
1303 
1304     int r = QMessageBox::Yes;
1305     if (GamesRunning())
1306     {
1307         r = QMessageBox::question( this,
1308                                    tr("Message"),
1309                                    tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"),
1310                                    QMessageBox::Yes | QMessageBox::No,
1311                                    QMessageBox::Yes);
1312     }
1313 
1314     if (r == QMessageBox::Yes)
1315     {
1316         mGameInput = NULL;
1317         NewGame();
1318     }
1319 }
1320 
PegCntChangedSlot()1321 void ColorCode::PegCntChangedSlot()
1322 {
1323     SetPegCnt();
1324 
1325     if (mNoAct)
1326     {
1327         return;
1328     }
1329 
1330     int pcnt = GetPegCntInput();
1331     if (pcnt == mPegCnt)
1332     {
1333         return;
1334     }
1335 
1336     int r = QMessageBox::Yes;
1337     if (GamesRunning())
1338     {
1339         r = QMessageBox::question( this,
1340                                    tr("Message"),
1341                                    tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"),
1342                                    QMessageBox::Yes | QMessageBox::No,
1343                                    QMessageBox::Yes);
1344     }
1345 
1346     if (r == QMessageBox::Yes)
1347     {
1348         mGameInput = NULL;
1349         NewGame();
1350     }
1351 }
1352 
DoublesChangedSlot(bool checked)1353 void ColorCode::DoublesChangedSlot(bool checked)
1354 {
1355     if (mNoAct)
1356     {
1357         return;
1358     }
1359 
1360     SetDoublesSlot(checked);
1361 
1362     if (mDoubles == mSettings->mDoubles)
1363     {
1364         return;
1365     }
1366 
1367     int r = QMessageBox::Yes;
1368     if (GamesRunning())
1369     {
1370         r = QMessageBox::question( this,
1371                                    tr("Message"),
1372                                    tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"),
1373                                    QMessageBox::Yes | QMessageBox::No,
1374                                    QMessageBox::Yes);
1375     }
1376 
1377     if (r == QMessageBox::Yes)
1378     {
1379         mGameInput = NULL;
1380         NewGame();
1381     }
1382 }
1383 
SetLevelSlot()1384 void ColorCode::SetLevelSlot()
1385 {
1386     mNoAct = true;
1387     int ix = mActGroupLevels->checkedAction()->data().toInt();
1388 
1389     if (ix < 0 || ix > 4)
1390     {
1391         return;
1392     }
1393 
1394     int i;
1395     i = mColorCntCmb->findData(LEVEL_SETTINGS[ix][0]);
1396     if (i != -1 && mColorCntCmb->currentIndex() != i)
1397     {
1398         mColorCntCmb->setCurrentIndex(i);
1399         SetColorCnt();
1400     }
1401     i = mPegCntCmb->findData(LEVEL_SETTINGS[ix][1]);
1402     if (i != -1 && mPegCntCmb->currentIndex() != i)
1403     {
1404         mPegCntCmb->setCurrentIndex(i);
1405         SetPegCnt();
1406     }
1407 
1408     SetDoublesSlot((LEVEL_SETTINGS[ix][2] == 1));
1409 
1410     int r = QMessageBox::Yes;
1411     if (GamesRunning())
1412     {
1413         r = QMessageBox::question( this,
1414                                    tr("Message"),
1415                                    tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"),
1416                                    QMessageBox::Yes | QMessageBox::No,
1417                                    QMessageBox::Yes);
1418     }
1419 
1420     mNoAct = false;
1421 
1422     if (r == QMessageBox::Yes)
1423     {
1424         mGameInput = NULL;
1425         NewGame();
1426     }
1427 }
1428 
SetGameModeSlot()1429 void ColorCode::SetGameModeSlot()
1430 {
1431     SetGameMode();
1432 
1433     int r = QMessageBox::Yes;
1434     if (GamesRunning())
1435     {
1436         r = QMessageBox::question( this,
1437                                    tr("Message"),
1438                                    tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"),
1439                                    QMessageBox::Yes | QMessageBox::No,
1440                                    QMessageBox::Yes);
1441     }
1442 
1443     if (r == QMessageBox::Yes)
1444     {
1445         mGameInput = NULL;
1446         NewGame();
1447     }
1448 }
1449 
1450 
SetPegCnt()1451 void ColorCode::SetPegCnt()
1452 {
1453     mSettings->mPegCnt = GetPegCntInput();
1454 }
1455 
SetColorCnt()1456 void ColorCode::SetColorCnt()
1457 {
1458     mSettings->mColorCnt = GetColorCntInput();
1459 }
1460 
SetGameMode()1461 void ColorCode::SetGameMode()
1462 {
1463     mSettings->mGameMode = GetGameModeInput();
1464 }
1465 
ShowMsgSlot(QString msg)1466 void ColorCode::ShowMsgSlot(QString msg)
1467 {
1468     mMsg->ShowMsg(msg);
1469 }
1470 
SnapPegSlot(ColorPeg * cp)1471 void ColorCode::SnapPegSlot(ColorPeg* cp)
1472 {
1473     int i;
1474     bool snapped = false;
1475 
1476     if (mGameMode == MODE_HVM)
1477     {
1478         QList<QGraphicsItem *> list = mScene->items(QPointF(cp->pos().x() + 18, cp->pos().y() + 18));
1479 
1480         if (mSolver->isRunning())
1481         {
1482             WaitForSolver();
1483         }
1484 
1485         for (i = 0; i < list.size(); ++i)
1486         {
1487             if (mCurRow != NULL && list.at(i) == mCurRow)
1488             {
1489                  snapped = mCurRow->SnapCP(cp);
1490                  break;
1491             }
1492         }
1493     }
1494     else if (mGameMode == MODE_MVH)
1495     {
1496         snapped = mSolutionRow->SnapCP(cp);
1497     }
1498 
1499     if (!snapped)
1500     {
1501         mPegFactory->RemovePegSlot(cp);
1502     }
1503 }
1504 
RowSolutionSlot(int ix)1505 void ColorCode::RowSolutionSlot(int ix)
1506 {
1507     if (mGameMode == MODE_HVM)
1508     {
1509         if (ix == SOLUTION_ROW_IX) { return; }
1510 
1511         std::vector<int> s = mPegRows[ix]->GetSolution();
1512         if (s.size() == (unsigned) mPegCnt)
1513         {
1514             if (mActAutoClose->isChecked())
1515             {
1516                 HintPressedSlot(ix);
1517             }
1518             else
1519             {
1520                 mHintBtns[ix]->SetActive(true);
1521                 ShowMsgSlot(tr("Press the Hint Field or Key Enter if You're done."));
1522             }
1523         }
1524         else
1525         {
1526             mHintBtns[ix]->SetActive(false);
1527             ShowMsgSlot(tr("Place Your pegs ..."));
1528         }
1529     }
1530     else if (mGameMode == MODE_MVH)
1531     {
1532         if (ix == SOLUTION_ROW_IX)
1533         {
1534             std::vector<int> s = mSolutionRow->GetSolution();
1535             if (s.size() == (unsigned) mPegCnt)
1536             {
1537                 bool valid = true;
1538                 if (!mActDoubles->isChecked())
1539                 {
1540                     int i;
1541                     int check[mColorCnt];
1542                     for (i = 0; i < mColorCnt; ++i)
1543                     {
1544                         check[i] = 0;
1545                     }
1546 
1547                     for (i = 0; (unsigned)i < s.size(); ++i)
1548                     {
1549                         if (s[i] >= mColorCnt)
1550                         {
1551                             valid = false;
1552                             break;
1553                         }
1554 
1555                         if (check[s[i]] != 0)
1556                         {
1557                             valid = false;
1558                             break;
1559                         }
1560 
1561                         check[s[i]] = 1;
1562                     }
1563                 }
1564 
1565                 if (valid)
1566                 {
1567                     mDoneBtn->ShowBtn(true);
1568                     ShowMsgSlot(tr("Press the button below or Key Enter if You're done."));
1569                 }
1570                 else
1571                 {
1572                     ShowMsgSlot(tr("The chosen settings do not allow pegs of the same color!"));
1573                 }
1574             }
1575             else
1576             {
1577                 mDoneBtn->ShowBtn(false);
1578                 ShowMsgSlot(tr("Place Your secret ColorCode ..."));
1579             }
1580         }
1581     }
1582 }
1583 
HintPressedSlot(int)1584 void ColorCode::HintPressedSlot(int)
1585 {
1586     mCurRow->CloseRow();
1587     ResolveRow();
1588     NextRow();
1589     ResolveGame();
1590 }
1591 
RandRowSlot()1592 void ColorCode::RandRowSlot()
1593 {
1594     if (mCurRow == NULL || !mCurRow->IsActive() || mGameState != STATE_RUNNING)
1595     {
1596         return;
1597     }
1598 
1599     if (mGameMode == MODE_HVM || (mGameMode == MODE_MVH && mCurRow == mSolutionRow))
1600     {
1601         mCurRow->ClearRow();
1602 
1603         int i, rndm;
1604         int check[mColorCnt];
1605         ColorPeg* peg;
1606         for (i = 0; i < mColorCnt; ++i)
1607         {
1608             check[i] = 0;
1609         }
1610 
1611         for (i = 0; i < mPegCnt; ++i)
1612         {
1613             rndm = qrand() % mColorCnt;
1614             if (mDoubles == 0 && check[rndm] != 0)
1615             {
1616                 --i;
1617                 continue;
1618             }
1619 
1620             check[rndm] = 1;
1621 
1622             peg = mPegFactory->CreatePeg(rndm);
1623             mCurRow->ForceSnap(peg, i);
1624         }
1625     }
1626 }
1627 
SetSolverGuessSlot()1628 void ColorCode::SetSolverGuessSlot()
1629 {
1630     if (mIgnoreGuess)
1631     {
1632         mIgnoreGuess = false;
1633         return;
1634     }
1635 
1636     if (mGameState != STATE_RUNNING || mCurRow == NULL)
1637     {
1638         return;
1639     }
1640 
1641     int* row = mSolver->GuessOut();
1642     if (row == NULL)
1643     {
1644         SetState(STATE_ERROR);
1645     }
1646     else
1647     {
1648         ColorPeg* peg;
1649         int i;
1650         for (i = 0; i < mPegCnt; ++i)
1651         {
1652             peg = mPegFactory->CreatePeg(row[i]);
1653             mCurRow->ForceSnap(peg, i);
1654         }
1655 
1656         if (mGameMode == MODE_HVM)
1657         {
1658             return;
1659         }
1660     }
1661 
1662     if (mGameState == STATE_RUNNING)
1663     {
1664         mCurRow->CloseRow();
1665         mHintBtns[mCurRow->GetIx()]->SetActive(true);
1666 
1667         if (mActAutoHints->isChecked())
1668         {
1669             if (mOkBtn->isVisible())
1670             {
1671                 mOkBtn->ShowBtn(false);
1672             }
1673             ShowMsgSlot(tr("guessed and rated ..."));
1674             SetHintsSlot();
1675             mHintBtns[mCurRow->GetIx()]->SetActive(false);
1676 
1677             std::vector<int> rowhints = mHintBtns[mCurRow->GetIx()]->GetHints();
1678             int b = 0;
1679             for (unsigned i = 0; i < rowhints.size(); ++i)
1680             {
1681                 if (rowhints.at(i) == 2)
1682                 {
1683                     ++b;
1684                 }
1685             }
1686 
1687             if (b == mPegCnt)
1688             {
1689                 SetState(STATE_WON);
1690                 ResolveGame();
1691             }
1692             else
1693             {
1694                 mHintsDelayTimer->start();
1695             }
1696         }
1697         else
1698         {
1699             ShowMsgSlot(tr("Please rate the guess. Press OK or Key Enter if You're done."));
1700             mOkBtn->setPos(5, mCurRow->pos().y() - 39);
1701             mOkBtn->ShowBtn(true);
1702         }
1703     }
1704     else
1705     {
1706         mCurRow->SetActive(false);
1707         ResolveGame();
1708     }
1709     UpdateActions();
1710 }
1711 
SetGuessSlot()1712 void ColorCode::SetGuessSlot()
1713 {
1714     if (mCurRow == NULL || mCurRow == mSolutionRow || mGameState != STATE_RUNNING || mSolver->isRunning())
1715     {
1716         return;
1717     }
1718 
1719     mCurRow->ClearRow();
1720     ShowMsgSlot(tr("Let me think ..."));
1721     mSolver->StartGuess();
1722     UpdateActions();
1723 }
1724 
SetHintsSlot()1725 void ColorCode::SetHintsSlot()
1726 {
1727     if (mCurRow == NULL || mGameState != STATE_RUNNING)
1728     {
1729         return;
1730     }
1731 
1732     if (mGameMode == MODE_MVH)
1733     {
1734         if (mCurRow == mSolutionRow || !mHintBtns[mCurRow->GetIx()]->IsActive())
1735         {
1736             return;
1737         }
1738 
1739         std::vector<int> hints = RateSol2Guess(mSolution, mCurRow->GetSolution());
1740         mHintBtns[mCurRow->GetIx()]->DrawHints(hints);
1741     }
1742 }
1743 
PrevRowSlot()1744 void ColorCode::PrevRowSlot()
1745 {
1746     if (mCurRow == NULL || mGameState != STATE_RUNNING)
1747     {
1748         return;
1749     }
1750 
1751     if (mCurRow->GetIx() < 1)
1752     {
1753         return;
1754     }
1755 
1756     mCurRow->ClearRow();
1757 
1758     ColorPeg* peg;
1759     std::vector<int> prev = mPegRows[mCurRow->GetIx() - 1]->GetSolution();
1760     int i;
1761     for (i = 0; i < mPegCnt; ++i)
1762     {
1763         peg = mPegFactory->CreatePeg(prev.at(i));
1764         mCurRow->ForceSnap(peg, i);
1765     }
1766 }
1767 
ClearRowSlot()1768 void ColorCode::ClearRowSlot()
1769 {
1770     if (mCurRow == NULL || mGameState != STATE_RUNNING)
1771     {
1772         return;
1773     }
1774 
1775     mCurRow->ClearRow();
1776 }
1777 
DoneBtnPressSlot(GraphicsBtn *)1778 void ColorCode::DoneBtnPressSlot(GraphicsBtn*)
1779 {
1780     mDoneBtn->ShowBtn(false);
1781     mOkBtn->ShowBtn(false);
1782 
1783     if (mCurRow == mSolutionRow)
1784     {
1785         SetSolution();
1786         NextRow();
1787     }
1788     else
1789     {
1790         ResolveHints();
1791     }
1792 }
1793 
SetAutoHintsSlot()1794 void ColorCode::SetAutoHintsSlot()
1795 {
1796     DoneBtnPressSlot(mOkBtn);
1797 }
1798 
TestSlot()1799 void ColorCode::TestSlot()
1800 {
1801     ;
1802 }
1803 
ApplyPreferencesSlot()1804 void ColorCode::ApplyPreferencesSlot()
1805 {
1806     ;
1807 }
1808 
CreatePrefDialog()1809 void ColorCode::CreatePrefDialog()
1810 {
1811     mPrefDialog = new PrefDialog(this);
1812     mPrefDialog->setModal(true);
1813     mPrefDialog->InitSettings();
1814     connect(mPrefDialog, SIGNAL(accepted()), this, SLOT(ApplyPreferencesSlot()));
1815     connect(mPrefDialog, SIGNAL(accepted()), mGameTablesDialog, SLOT(SetSettingsSlot()));
1816     connect(mPrefDialog, SIGNAL(ResetColorOrderSignal()), mPegFactory, SLOT(ResetColorsOrderSlot()));
1817 }
1818 
CheckDoublesSetting()1819 void ColorCode::CheckDoublesSetting()
1820 {
1821     if (mColorCnt < mPegCnt)
1822     {
1823         if (mActDoubles->isEnabled())
1824         {
1825             mActDoubles->setEnabled(false);
1826         }
1827         if (mActDoublesIcon->isEnabled())
1828         {
1829             mActDoublesIcon->setEnabled(false);
1830         }
1831         if (!mActDoubles->isChecked())
1832         {
1833             mActDoubles->setChecked(true);
1834         }
1835         if (!mActDoublesIcon->isChecked())
1836         {
1837             mActDoublesIcon->setChecked(true);
1838         }
1839     }
1840     else
1841     {
1842         if (!mActDoubles->isEnabled())
1843         {
1844             mActDoubles->setEnabled(true);
1845         }
1846         if (!mActDoublesIcon->isEnabled())
1847         {
1848             mActDoublesIcon->setEnabled(true);
1849         }
1850     }
1851 
1852     if (mActDoublesIcon->isChecked())
1853     {
1854         mActDoublesIcon->setIcon(QIcon(":/img/same_color_1.png"));
1855         mActDoublesIcon->setToolTip(tr("Disallow Pegs of the Same Color"));
1856     }
1857     else
1858     {
1859         mActDoublesIcon->setIcon(QIcon(":/img/same_color_0.png"));
1860         mActDoublesIcon->setToolTip(tr("Allow Pegs of the Same Color"));
1861     }
1862 }
1863 
SetDoublesSlot(bool checked)1864 void ColorCode::SetDoublesSlot(bool checked)
1865 {
1866     mSettings->mDoubles = checked;
1867 
1868     mActDoubles->setChecked(checked);
1869     mActDoublesIcon->setChecked(checked);
1870 
1871     if (checked)
1872     {
1873         mActDoublesIcon->setIcon(QIcon(":/img/same_color_1.png"));
1874         mActDoublesIcon->setToolTip(tr("Disallow Pegs of the Same Color"));
1875     }
1876     else
1877     {
1878         mActDoublesIcon->setIcon(QIcon(":/img/same_color_0.png"));
1879         mActDoublesIcon->setToolTip(tr("Allow Pegs of the Same Color"));
1880     }
1881 }
1882 
CheckLevel()1883 void ColorCode::CheckLevel()
1884 {
1885     int ix = -1;
1886     for (int i = 0; i < 5; ++i)
1887     {
1888         if ( LEVEL_SETTINGS[i][0] == mColorCnt
1889              && LEVEL_SETTINGS[i][1] == mPegCnt
1890              && LEVEL_SETTINGS[i][2] == mDoubles )
1891         {
1892             ix = i;
1893             break;
1894         }
1895     }
1896 
1897     if (ix > -1)
1898     {
1899         QList<QAction *> levelacts = mActGroupLevels->actions();
1900         levelacts.at(ix)->setChecked(true);
1901     }
1902     else
1903     {
1904         QAction* act = mActGroupLevels->checkedAction();
1905         if (act != NULL)
1906         {
1907             act->setChecked(false);
1908         }
1909     }
1910 }
1911 
ResetGame()1912 void ColorCode::ResetGame()
1913 {
1914     mDoneBtn->ShowBtn(false);
1915     mOkBtn->ShowBtn(false);
1916 
1917     ApplyPegCnt();
1918 
1919     mSolutionRow->Reset(mPegCnt, mGameMode);
1920     ResetRows();
1921 
1922     mGameId = qrand();
1923     mGuessCnt = 0;
1924     ++mGameCnt;
1925 
1926     mPegFactory->ApplyColorCnt();
1927 
1928     CheckDoublesSetting();
1929 
1930     mDoubles = GetDoublesInput();
1931     CheckLevel();
1932 
1933     ApplySolverStrength();
1934 }
1935 
ResetRows()1936 void ColorCode::ResetRows()
1937 {
1938     for (int i = 0; i < mMaxRowCnt; ++i)
1939     {
1940         mPegRows[i]->Reset(mPegCnt, mGameMode);
1941         mHintBtns[i]->Reset(mPegCnt, mGameMode);
1942     }
1943 }
1944 
NewGameInputSlot(CCGame * g)1945 void ColorCode::NewGameInputSlot(CCGame* g)
1946 {
1947     if (g != NULL && g->IsValidGame())
1948     {
1949         mGameInput = g;
1950         mGameInput->Anonymize();
1951 
1952         mNoAct = true;
1953         if (mGameInput->mGameMode == MODE_HVM)
1954         {
1955             mActModeHvM->setChecked(true);
1956         }
1957         else
1958         {
1959             mActModeMvH->setChecked(true);
1960         }
1961 
1962         SetDoublesSlot((bool) mGameInput->mDoubles);
1963 
1964         int i;
1965         i = mColorCntCmb->findData(mGameInput->mColorCnt);
1966         if (i != -1 && mColorCntCmb->currentIndex() != i)
1967         {
1968             mColorCntCmb->setCurrentIndex(i);
1969         }
1970         i = mPegCntCmb->findData(mGameInput->mPegCnt);
1971         if (i != -1 && mPegCntCmb->currentIndex() != i)
1972         {
1973             mPegCntCmb->setCurrentIndex(i);
1974         }
1975         CheckLevel();
1976 
1977         mNoAct = false;
1978     }
1979 
1980     NewGame();
1981 }
1982 
GetRandGameInput()1983 CCGame* ColorCode::GetRandGameInput()
1984 {
1985     int gameno = mSolver->GetRandGameNo(mColorCnt, mPegCnt, mDoubles);
1986     CCGame* g = mSettings->GetCurSettingsGame();
1987     g->mGameNo = gameno;
1988 
1989     return g;
1990 }
1991 
NewGame()1992 void ColorCode::NewGame()
1993 {
1994     if (mGameState == STATE_PAUSED)
1995     {
1996         PauseGameSlot();
1997     }
1998 
1999     mHintsDelayTimer->stop();
2000 
2001     if (mSolver->isRunning())
2002     {
2003         WaitForSolver();
2004     }
2005 
2006     ApplyGameMode();
2007     ResetGame();
2008     QString doubles = (mDoubles == 1) ? tr("Yes") : tr("No");
2009     QString colors = QString::number(mColorCnt, 10);
2010     QString pegs = QString::number(mPegCnt, 10);
2011     mStatusLabel->setText(tr("Pegs of Same Color") + ": <b>" + doubles + "</b> :: " + tr("Slots") + ": <b>" + pegs + "</b> :: " + tr("Colors") + ": <b>" + colors + "</b> ");
2012     SetState(STATE_RUNNING);
2013 
2014     SetCurRow(NULL);
2015 
2016     if (mGameMode == MODE_HVM)
2017     {
2018         mFinishedGameInput = NULL;
2019         mSolver->NewGame(mColorCnt, mPegCnt, mDoubles, CCSolver::STRENGTH_HIGH, mMaxRowCnt);
2020         mHighScore->NewGame(mSolver->CalcPosCnt(mColorCnt, mPegCnt, mDoubles));
2021         if (mGameInput == NULL)
2022         {
2023             mGameInput = mSettings->GetCurSettingsGame();
2024         }
2025 
2026         if (mGameInput->mColorCnt != mColorCnt)
2027         {
2028             mGameInput->mColorCnt = mColorCnt;
2029         }
2030         if (mGameInput->mPegCnt != mPegCnt)
2031         {
2032             mGameInput->mPegCnt = mPegCnt;
2033         }
2034         if (mGameInput->mDoubles != mDoubles)
2035         {
2036             mGameInput->mDoubles = mDoubles;
2037         }
2038         if (mGameInput->mGameMode != mGameMode)
2039         {
2040             mGameInput->mGameMode = mGameMode;
2041         }
2042 
2043         mGameInput->mDuration = 0;
2044         mGameInput->mTime = QDateTime::currentDateTime().toTime_t();
2045 
2046         if (mGameInput->mGameNo == 0)
2047         {
2048             mGameInput->mGameNo = mSolver->GetRandGameNo(mColorCnt, mPegCnt, mDoubles);
2049         }
2050 
2051         mGameTablesDialog->InsertPrevGameSlot(mGameInput);
2052 
2053         SetSolution();
2054 
2055         mGameTimer->StartT();
2056 
2057         NextRow();
2058     }
2059     else if (mGameMode == MODE_MVH)
2060     {
2061         mSolver->NewGame(mColorCnt, mPegCnt, mDoubles, mSolverStrength, mMaxRowCnt);
2062         GetSolution();
2063     }
2064 
2065     UpdateGameNoDisplay();
2066 }
2067 
NextRow()2068 void ColorCode::NextRow()
2069 {
2070     if (mGameState != STATE_RUNNING)
2071     {
2072         return;
2073     }
2074 
2075     if (mCurRow == NULL)
2076     {
2077         SetCurRow(mPegRows[0]);
2078     }
2079     else if (mCurRow->GetIx() < mMaxRowCnt - 1)
2080     {
2081         SetCurRow(mPegRows[mCurRow->GetIx() + 1]);
2082     }
2083     else
2084     {
2085         SetCurRow(NULL);
2086         SetState(STATE_LOST);
2087     }
2088 
2089     if (mCurRow != NULL)
2090     {
2091         ++mGuessCnt;
2092         mCurRow->SetActive(true);
2093         if (mGameMode == MODE_HVM)
2094         {
2095             ++mHighScore->mRowsCnt;
2096             ShowMsgSlot(tr("Place Your pegs ..."));
2097         }
2098         else if (mGameMode == MODE_MVH)
2099         {
2100             SetGuessSlot();
2101         }
2102     }
2103 }
2104 
SetCurRow(PegRow * const & row)2105 void ColorCode::SetCurRow(PegRow* const &row)
2106 {
2107     mCurRow = row;
2108     UpdateActions();
2109 }
2110 
ResolveRow()2111 void ColorCode::ResolveRow()
2112 {
2113     std::vector<int> rowsol = mCurRow->GetSolution();
2114     mSolver->GuessIn(&rowsol);
2115 
2116     std::vector<int> hints = RateSol2Guess(mSolution, rowsol);
2117 
2118     if (hints.size() == (unsigned) mPegCnt)
2119     {
2120         int bl = 0;
2121         for (int i = 0; i < mPegCnt; ++i)
2122         {
2123             if (hints.at(i) == 2)
2124             {
2125                 ++bl;
2126             }
2127         }
2128 
2129         if (bl == mPegCnt)
2130         {
2131             SetState(STATE_WON);
2132         }
2133     }
2134 
2135     mSolver->ResIn(&hints);
2136     mHintBtns[mCurRow->GetIx()]->DrawHints(hints);
2137 }
2138 
RateSol2Guess(const std::vector<int> sol,const std::vector<int> guess)2139 std::vector<int> ColorCode::RateSol2Guess(const std::vector<int> sol, const std::vector<int> guess)
2140 {
2141     std::vector<int> hints;
2142     std::vector<int> left1;
2143     std::vector<int> left0;
2144 
2145     int i, p0, p1;
2146     for (i = 0; i < mPegCnt; ++i)
2147     {
2148         p0 = guess.at(i);
2149         p1 = sol.at(i);
2150         if (p0 == p1)
2151         {
2152             hints.push_back(2);
2153         }
2154         else
2155         {
2156             left0.push_back(p0);
2157             left1.push_back(p1);
2158         }
2159     }
2160 
2161     if (hints.size() < (unsigned) mPegCnt)
2162     {
2163         int len0 = left0.size();
2164         for (i = 0; i < len0; ++i)
2165         {
2166             p0 = left0.at(i);
2167             for (unsigned j = 0; j < left1.size(); ++j)
2168             {
2169                 p1 = left1.at(j);
2170                 if (p0 == p1)
2171                 {
2172                     hints.push_back(1);
2173                     left1.erase(left1.begin() + j);
2174                     break;
2175                 }
2176             }
2177         }
2178     }
2179 
2180     return hints;
2181 }
2182 
ResolveHints()2183 void ColorCode::ResolveHints()
2184 {
2185     if (mCurRow == NULL)
2186     {
2187         return;
2188     }
2189 
2190     mHintBtns[mCurRow->GetIx()]->SetActive(false);
2191 
2192     std::vector<int> rowsol = mCurRow->GetSolution();
2193     mSolver->GuessIn(&rowsol);
2194     std::vector<int> rowhints = mHintBtns[mCurRow->GetIx()]->GetHints();
2195     int b = 0;
2196     int w = 0;
2197     for (unsigned i = 0; i < rowhints.size(); ++i)
2198     {
2199         if (rowhints.at(i) == 2)
2200         {
2201             ++b;
2202         }
2203         else if (rowhints.at(i) == 1)
2204         {
2205             ++w;
2206         }
2207     }
2208 
2209     if (b == mPegCnt)
2210     {
2211         SetState(STATE_WON);
2212         ResolveGame();
2213     }
2214     else if (b == mPegCnt - 1 && w == 1)
2215     {
2216         ;
2217     }
2218     else
2219     {
2220         mSolver->ResIn(&rowhints);
2221         NextRow();
2222         ResolveGame();
2223     }
2224 }
2225 
ResolveGame()2226 void ColorCode::ResolveGame()
2227 {
2228     if (mGameMode == MODE_HVM)
2229     {
2230         switch (mGameState)
2231         {
2232             case STATE_WON:
2233             {
2234                 ShowMsgSlot(tr("Congratulation! You have won!"));
2235                 mHighScore->mTime = mGameTimer->GetGameTime();
2236                 mGameInput->mScore = mHighScore->GetScore();
2237                 mGameInput->mDuration = mGameTimer->GetGameTime();
2238                 CCGame* g = new CCGame(mGameInput->ToString());
2239                 emit NewHighScoreSignal(g);
2240             }
2241             break;
2242             case STATE_LOST:
2243                 ShowMsgSlot(tr("Sorry! You lost!"));
2244             break;
2245             case STATE_GAVE_UP:
2246                 ShowMsgSlot(tr("Sure, You're too weak for me!"));
2247             break;
2248             case STATE_ERROR:
2249                 ShowMsgSlot(tr("The impossible happened, sorry."));
2250             break;
2251             case STATE_PAUSED:
2252                 ShowMsgSlot(tr("Paused"));
2253                 return;
2254             break;
2255             case STATE_RUNNING:
2256             default:
2257                 return;
2258             break;
2259         }
2260 
2261         mFinishedGameInput = new CCGame(mGameInput->ToString());
2262         mGameInput = NULL;
2263         mGameTimer->StopT();
2264         ShowSolution();
2265     }
2266     else if (mGameMode == MODE_MVH)
2267     {
2268         switch (mGameState)
2269         {
2270             case STATE_WON:
2271                 ShowMsgSlot(tr("Yeah! I guessed it, man!"));
2272             break;
2273             case STATE_LOST:
2274                 ShowMsgSlot(tr("Embarrassing! I lost a game!"));
2275             break;
2276             case STATE_GAVE_UP:
2277                 ShowMsgSlot(tr("Don't you like to see me winning? ;-)"));
2278             break;
2279             case STATE_ERROR:
2280                 ShowMsgSlot(tr("Nope! Thats impossible! Did you gave me false hints?"));
2281             break;
2282             case STATE_RUNNING:
2283             default:
2284                 return;
2285             break;
2286         }
2287 
2288         mDoneBtn->ShowBtn(false);
2289         mOkBtn->ShowBtn(false);
2290     }
2291 
2292     SetCurRow(NULL);
2293 }
2294 
ApplyGameMode()2295 void ColorCode::ApplyGameMode()
2296 {
2297     mGameMode = GetGameModeInput();
2298 
2299     if (mGameMode == MODE_HVM)
2300     {
2301         mActSetHints->setVisible(false);
2302 
2303         mActSetGuess->setVisible(true);
2304         mActPrevRow->setVisible(true);
2305     }
2306     else if (mGameMode == MODE_MVH)
2307     {
2308         mActSetHints->setVisible(true);
2309 
2310         mActSetGuess->setVisible(false);
2311         mActPrevRow->setVisible(false);
2312     }
2313     ShowTimer();
2314 }
2315 
GetGameState() const2316 int ColorCode::GetGameState() const
2317 {
2318     return mGameState;
2319 }
2320 
GetGameModeInput() const2321 int ColorCode::GetGameModeInput() const
2322 {
2323     int ix = mActGroupModes->checkedAction()->data().toInt();
2324     if (ix != MODE_HVM && ix != MODE_MVH)
2325     {
2326         ix = MODE_HVM;
2327     }
2328     return ix;
2329 }
2330 
GetDoublesInput() const2331 int ColorCode::GetDoublesInput() const
2332 {
2333     return (int) mActDoubles->isChecked();
2334 }
2335 
GetColorCntInput() const2336 int ColorCode::GetColorCntInput() const
2337 {
2338     int ccnt = mColorCntCmb->itemData(mColorCntCmb->currentIndex(), Qt::UserRole).toInt();
2339     ccnt = max(2, min(10, ccnt));
2340     return ccnt;
2341 }
2342 
GetPegCntInput() const2343 int ColorCode::GetPegCntInput() const
2344 {
2345     int pegcnt = mPegCntCmb->itemData(mPegCntCmb->currentIndex(), Qt::UserRole).toInt();
2346     pegcnt = max(2, min(5, pegcnt));
2347     return pegcnt;
2348 }
2349 
ApplyPegCnt()2350 void ColorCode::ApplyPegCnt()
2351 {
2352     mPegCnt = GetPegCntInput();
2353     mXOffs = 160 - mPegCnt * 20;
2354 }
2355 
ApplySolverStrength()2356 void ColorCode::ApplySolverStrength()
2357 {
2358     mSolverStrength = mSettings->mSolverStrength;
2359 }
2360 
SetSolution()2361 void ColorCode::SetSolution()
2362 {
2363     mSolution.clear();
2364 
2365     if (mGameMode == MODE_HVM)
2366     {
2367         mSolutionRow->ClearRow();
2368         mSolution = mSolver->GetSolutionByNo(mGameInput->mGameNo);
2369     }
2370     else if (mGameMode == MODE_MVH)
2371     {
2372         std::vector<int> s = mSolutionRow->GetSolution();
2373         if (s.size() == (unsigned) mPegCnt)
2374         {
2375             mSolutionRow->CloseRow();
2376             mDoneBtn->ShowBtn(false);
2377 
2378             for (int i = 0; i < mPegCnt; ++i)
2379             {
2380                 mSolution.push_back(s.at(i));
2381             }
2382         }
2383     }
2384 }
2385 
GetSolution()2386 void ColorCode::GetSolution()
2387 {
2388     ShowMsgSlot(tr("Place Your secret ColorCode ..."));
2389     mSolutionRow->SetActive(true);
2390     SetCurRow(mSolutionRow);
2391 }
2392 
ShowSolution()2393 void ColorCode::ShowSolution()
2394 {
2395     mSolutionRow->SetActive(true);
2396     ColorPeg* peg;
2397     for (int i = 0; i < mPegCnt; ++i)
2398     {
2399         peg = mPegFactory->CreatePeg(mSolution.at(i));
2400         peg->SetBtn(false);
2401         mSolutionRow->ForceSnap(peg, i);
2402     }
2403     mSolutionRow->CloseRow();
2404 }
2405 
SetState(const int s)2406 void ColorCode::SetState(const int s)
2407 {
2408     if (mGameState != s)
2409     {
2410         mGameState = s;
2411     }
2412 }
2413 
GamesRunning()2414 bool ColorCode::GamesRunning()
2415 {
2416     if (mGameMode == MODE_HVM)
2417     {
2418         return ((mGameState == STATE_RUNNING || mGameState == STATE_PAUSED) && mGuessCnt > 1);
2419     }
2420     else if (mGameMode == MODE_MVH)
2421     {
2422         return (mGameState == STATE_RUNNING && mCurRow != mSolutionRow);
2423     }
2424     return false;
2425 }
2426 
Scale()2427 void ColorCode::Scale()
2428 {
2429     if (mGameCnt == 0)
2430     {
2431         return;
2432     }
2433 
2434     qreal w = geometry().width();
2435     qreal h = geometry().height();
2436 
2437     if (mActShowStatusbar->isChecked())
2438     {
2439         h -= statusBar()->height();
2440     }
2441     if (mActShowMenubar->isChecked())
2442     {
2443         h -= mMenuBar->height();
2444     }
2445     if (mActShowToolbar->isChecked())
2446     {
2447         h -= mGameToolbar->height();
2448     }
2449 
2450     if (w < 50 || h < 50)
2451     {
2452         return;
2453     }
2454 
2455     if (mOrigSize == NULL)
2456     {
2457         mOrigSize = new QSize(320, 560);
2458         mScene->setSceneRect(QRectF(0, 0, 320, 560));
2459     }
2460     else
2461     {
2462         qreal sc = min(w / mOrigSize->width(), h / mOrigSize->height());
2463         mView->resetTransform();
2464         mView->scale(sc, sc);
2465     }
2466 }
2467 
GetCCSolver() const2468 CCSolver* ColorCode::GetCCSolver() const
2469 {
2470     return mSolver;
2471 }
2472 
WaitForSolver()2473 void ColorCode::WaitForSolver()
2474 {
2475     mIgnoreGuess = true;
2476     mSolver->Interrupt();
2477     mSolver->wait();
2478 }
2479 
ForceRepaint()2480 bool ColorCode::ForceRepaint()
2481 {
2482     mView->viewport()->repaint();
2483     QApplication::processEvents();
2484     return true;
2485 }
2486 
SavePrevGameSlot()2487 void ColorCode::SavePrevGameSlot()
2488 {
2489     CCGame* g = GetCurrentGameInput();
2490     if (g != NULL)
2491     {
2492         mGameTablesDialog->InsertSavedGameSlot(g);
2493     }
2494 }
2495