source: trunk/OpenYahtzee/src/MainFrame.cpp @ 85

Last change on this file since 85 was 85, checked in by guyru, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.1 KB
Line 
1// $Header$
2/***************************************************************************
3 *   Copyright (C) 2006 by Guy Rutenberg   *
4 *   guyrutenberg@gmail.com   *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 *   This program is distributed in the hope that it will be useful,       *
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14 *   GNU General Public License for more details.                          *
15 *                                                                         *
16 *   You should have received a copy of the GNU General Public License     *
17 *   along with this program; if not, write to the                         *
18 *   Free Software Foundation, Inc.,                                       *
19 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20 ***************************************************************************/
21
22 /***********************************************
23 *      This File contains the definitions      *
24 *      of MainFrame's functions                *
25 ***********************************************/
26
27// #define DEBUG
28
29#include <wx/wx.h>
30
31#include "MainFrame.h"
32#include "wxDynamicBitmap.h"
33#include "ObjectsID.h"
34#include "HighScoreDialog.h"
35#include "SettingsDialog.h"
36#include "About.h"
37#include "UtilityFunctions.h"
38#include <iostream>
39#include <sstream>
40#include <cstdlib>
41#include <wx/version.h>
42
43//include the images for the dice
44#include "one.xpm"
45#include "two.xpm"
46#include "three.xpm"
47#include "four.xpm"
48#include "five.xpm"
49#include "six.xpm"
50
51//include the icon file
52#include "Icon.h"
53
54//default values
55#define SPACE_SIZE 1
56#define DEF_HIGHSCORESIZE 20
57#define OY_VERSION "1.7.0"
58
59DEFINE_EVENT_TYPE(wxEVT_ENABLE_ROLL)
60
61
62MainFrame::MainFrame(const wxString& title, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE)
63        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, size, style)
64{
65        //give the frame an icon
66        SetIcon(wxIcon(ICON));
67
68
69        std::ostringstream sstr;
70
71        m_settingsdb = new SettingsDB(); //Get the settings database connection
72        m_highscoredb = new HighScoreTableDB();
73       
74        InitializeDatabase();//this must come _after_ m_settingsdb and m_highscoredb are created
75
76        bitmap_dices[0] = new wxBitmap(one_xpm);
77        bitmap_dices[1] = new wxBitmap(two_xpm);
78        bitmap_dices[2] = new wxBitmap(three_xpm);
79        bitmap_dices[3] = new wxBitmap(four_xpm);
80        bitmap_dices[4] = new wxBitmap(five_xpm);
81        bitmap_dices[5] = new wxBitmap(six_xpm);
82       
83        //randomize the random-number generator based on the time
84        srand( (unsigned)time( NULL ) );
85
86
87        /*****Create and initialize the menu bar******/
88
89        /*Create the menus*/
90        wxMenu *gameMenu = new wxMenu;  //create File menu
91        wxMenu *helpMenu = new wxMenu;  //create Help menu
92       
93       
94        //insert menu items into menu Help
95        helpMenu->Append(ID_CHECK_FOR_UPDATES, wxT("&Check for Updates"),
96                        wxT("Check for new version of the game via the web"));
97        helpMenu->AppendSeparator();
98        helpMenu->Append(ID_SENDCOMMENT, wxT("&Send a Comment to Developers"),
99                        wxT("Send a comment to the developers of the game"));
100        helpMenu->AppendSeparator();
101        helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
102                        wxT("Show about dialog"));
103
104        //insert menu items into menu File
105        gameMenu->Append(ID_NEWGAME,wxT("&New Game\tF2"),wxT("Start a new game"));
106        //create the undo button and make it disabled
107        gameMenu->Append(ID_UNDO,wxT("&Undo\tCTRL+Z"),wxT("Undo the last move"));
108        gameMenu->Append(ID_SHOWHIGHSCORE,wxT("High &Scores"),wxT("Show high-scores table"));
109        gameMenu->Append(ID_SETTINGS,wxT("Settings"),wxT("Show settings dialog"));
110        gameMenu->Append(wxID_EXIT, wxT("E&xit\tAlt-X"),
111                        wxT("Quit this program"));
112       
113        // Declare the menu-bar and append the freshly created menus to the menu bar...
114        wxMenuBar *menuBar = new wxMenuBar();
115        menuBar->Append(gameMenu, wxT("&Game"));
116        menuBar->Append(helpMenu, wxT("&Help"));
117       
118        // ... and attach this menu bar to the frame
119        SetMenuBar(menuBar);
120       
121        /***End menu-bar ***/
122        wxPanel* panel = new wxPanel(this, ID_PANEL,
123                wxDefaultPosition, wxDefaultSize);
124
125        wxBoxSizer *topSizer = new wxBoxSizer( wxHORIZONTAL );
126        wxBoxSizer *sectionsSizer = new wxBoxSizer( wxVERTICAL );
127        wxBoxSizer *diceSizer = new wxBoxSizer( wxVERTICAL );
128
129        wxSizer *uppersection = new wxStaticBoxSizer( new wxStaticBox( panel, wxID_ANY, wxT("Upper Section") ), wxVERTICAL);
130        wxSizer *lowersection = new wxStaticBoxSizer( new wxStaticBox( panel, wxID_ANY, wxT("Lower Section") ), wxVERTICAL);
131       
132        wxFlexGridSizer* uppergrid = new wxFlexGridSizer(2, 0, 10);
133        wxFlexGridSizer* lowergrid = new wxFlexGridSizer(2, 0, 10);
134
135        //BEGIN layout for the upper section of the score board
136        uppergrid->Add(new wxButton(panel,ID_ACES,wxT("Aces")),0,wxALL,SPACE_SIZE);
137        uppergrid->Add(new wxTextCtrl(panel, ID_ACESTEXT),1,wxALL,SPACE_SIZE);
138        uppergrid->Add(new wxButton(panel,ID_TWOS,wxT("Twos")),0,wxALL,SPACE_SIZE);
139        uppergrid->Add(new wxTextCtrl(panel, ID_TWOSTEXT),1,wxALL,SPACE_SIZE);
140        uppergrid->Add(new wxButton(panel,ID_THREES,wxT("Threes")),0,wxALL,SPACE_SIZE);
141        uppergrid->Add(new wxTextCtrl(panel, ID_THREESTEXT),1,wxALL,SPACE_SIZE);
142        uppergrid->Add(new wxButton(panel,ID_FOURS,wxT("Fours")),0,wxALL,SPACE_SIZE);
143        uppergrid->Add(new wxTextCtrl(panel, ID_FOURSTEXT),1,wxALL,SPACE_SIZE);
144        uppergrid->Add(new wxButton(panel,ID_FIVES,wxT("Fives")),0,wxALL,SPACE_SIZE);
145        uppergrid->Add(new wxTextCtrl(panel, ID_FIVESTEXT),1,wxALL,SPACE_SIZE);
146        uppergrid->Add(new wxButton(panel,ID_SIXES,wxT("Sixes")),0,wxALL,SPACE_SIZE);
147        uppergrid->Add(new wxTextCtrl(panel, ID_SIXESTEXT),1,wxALL,SPACE_SIZE);
148        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total score:")),0,wxALL,SPACE_SIZE);
149        uppergrid->Add(new wxTextCtrl(panel, ID_UPPERSECTIONTOTAL),1,wxALL,SPACE_SIZE);
150        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Bonus:")),0,wxALL,SPACE_SIZE);
151        uppergrid->Add(new wxTextCtrl(panel, ID_BONUS),1,wxALL,SPACE_SIZE);
152        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total of upper section:")),0,wxALL,SPACE_SIZE);
153        uppergrid->Add(new wxTextCtrl(panel, ID_UPPERTOTAL),1,wxALL,SPACE_SIZE);
154        //END layout for the upper section of the score board
155
156        //BEGIN layout for the lower section of the score board
157        lowergrid->Add(new wxButton(panel,ID_THREEOFAKIND,wxT("3 of a kind")),0,wxALL,SPACE_SIZE);
158        lowergrid->Add(new wxTextCtrl(panel, ID_THREEOFAKINDTEXT),1,wxALL,SPACE_SIZE);
159        lowergrid->Add(new wxButton(panel,ID_FOUROFAKIND,wxT("4 of a kind")),0,wxALL,SPACE_SIZE);
160        lowergrid->Add(new wxTextCtrl(panel, ID_FOUROFAKINDTEXT),1,wxALL,SPACE_SIZE);
161        lowergrid->Add(new wxButton(panel,ID_FULLHOUSE,wxT("Full House")),0,wxALL,SPACE_SIZE);
162        lowergrid->Add(new wxTextCtrl(panel, ID_FULLHOUSETEXT),1,wxALL,SPACE_SIZE);
163        lowergrid->Add(new wxButton(panel,ID_SMALLSEQUENCE,wxT("Sequence of 4")),0,wxALL,SPACE_SIZE);
164        lowergrid->Add(new wxTextCtrl(panel, ID_SMALLSEQUENCETEXT),1,wxALL,SPACE_SIZE);
165        lowergrid->Add(new wxButton(panel,ID_LARGESEQUENCE,wxT("Sequence of 5")),0,wxALL,SPACE_SIZE);
166        lowergrid->Add(new wxTextCtrl(panel, ID_LARGESEQUENCETEXT),1,wxALL,SPACE_SIZE);
167        lowergrid->Add(new wxButton(panel,ID_YAHTZEE,wxT("Yahtzee")),0,wxALL,SPACE_SIZE);
168        lowergrid->Add(new wxTextCtrl(panel, ID_YAHTZEETEXT),1,wxALL,SPACE_SIZE);
169        lowergrid->Add(new wxButton(panel,ID_CHANCE,wxT("Chance")),0,wxALL,SPACE_SIZE);
170        lowergrid->Add(new wxTextCtrl(panel, ID_CHANCETEXT),1,wxALL,SPACE_SIZE);
171        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Yahtzee Bonus")),0,wxALL,SPACE_SIZE);
172        lowergrid->Add(new wxTextCtrl(panel, ID_YAHTZEEBONUSTEXT),1,wxALL,SPACE_SIZE);
173        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total of lower section:")),0,wxALL,SPACE_SIZE);
174        lowergrid->Add(new wxTextCtrl(panel, ID_LOWERTOTAL),1,wxALL,SPACE_SIZE);
175        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Grand Total:")),0,wxALL,SPACE_SIZE);
176        lowergrid->Add(new wxTextCtrl(panel, ID_GRANDTOTAL),1,wxALL,SPACE_SIZE);
177        //END layout for the lower section of the score board
178
179        uppersection->Add(uppergrid);
180        lowersection->Add(lowergrid);
181        sectionsSizer->Add(uppersection,0,wxALL,5);
182        sectionsSizer->Add(lowersection,0,wxALL,5);
183
184        //BEGIN layout for the dice section of the score board
185        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE1,*bitmap_dices[0]),0,wxALL,3);
186        diceSizer->Add(new wxCheckBox(panel, ID_DICE1KEEP, wxT("Keep")),0,wxBOTTOM,10);
187        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE2,*bitmap_dices[1]),0,wxALL,3);
188        diceSizer->Add(new wxCheckBox(panel, ID_DICE2KEEP, wxT("Keep")),0,wxBOTTOM,10);
189        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE3,*bitmap_dices[2]),0,wxALL,3);
190        diceSizer->Add(new wxCheckBox(panel, ID_DICE3KEEP, wxT("Keep")),0,wxBOTTOM,10);
191        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE4,*bitmap_dices[3]),0,wxALL,3);
192        diceSizer->Add(new wxCheckBox(panel, ID_DICE4KEEP, wxT("Keep")),0,wxBOTTOM,10);
193        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE5,*bitmap_dices[4]),0,wxALL,3);
194        diceSizer->Add(new wxCheckBox(panel, ID_DICE5KEEP, wxT("Keep")),0,wxBOTTOM,10);
195        diceSizer->Add(new wxButton(panel, ID_ROLL, wxT("Roll")),0,wxALL,3);
196        /*===> END layout for the dice section of the score board *******/
197
198       
199        topSizer->Add(sectionsSizer);
200        topSizer->Add(diceSizer);       
201
202        panel->SetSizer(topSizer);
203       
204        topSizer->Fit(this);
205        topSizer->SetSizeHints(this);
206       
207        //make the text boxes uneditable to the user   
208        wxTextCtrl *textctrl;
209        for(int i = ID_ACESTEXT;i<=ID_GRANDTOTAL;i++) {
210                textctrl = (wxTextCtrl*) FindWindow(i);
211                textctrl->SetEditable(false);
212        }
213       
214        //disable the undo button
215        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
216
217
218       
219
220        /***************************************/
221        /********* Declare Event Table *********/
222        /***************************************/
223       
224        //BEGIN connecting the menu items' events
225        Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnQuit));
226        Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAbout));
227        Connect(ID_CHECK_FOR_UPDATES, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnCheckForUpdates));
228        Connect(ID_SENDCOMMENT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSendComment));
229        Connect(ID_NEWGAME, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnNewGame));
230        Connect(ID_UNDO, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnUndo));
231        Connect(ID_SHOWHIGHSCORE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnShowHighscore));
232        Connect(ID_SETTINGS, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSettings));
233        //END connecting the menu items' events
234
235        Connect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnRollButton));
236        Connect(ID_ROLL, wxEVT_ENABLE_ROLL, wxCommandEventHandler (MainFrame::OnRollButton));
237
238        //BEGIN connecting the scoreboard buttons to the events
239        Connect(ID_ACES,ID_SIXES, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnUpperButtons));
240        Connect(ID_THREEOFAKIND, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::On3ofakindButton));
241        Connect(ID_FOUROFAKIND, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::On4ofakindButton));
242        Connect(ID_FULLHOUSE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnFullHouseButton));
243        Connect(ID_SMALLSEQUENCE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnSmallSequenceButton));
244        Connect(ID_LARGESEQUENCE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnLargeSequenceButton));
245        Connect(ID_YAHTZEE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnYahtzeeButton));
246        Connect(ID_CHANCE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnChanceButton));
247        Connect(ID_DICE1,ID_DICE5, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnDiceClick));
248        Connect(ID_DICE1KEEP,ID_DICE5KEEP, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (MainFrame::OnKeepClick));
249        //END connecting the scoreboard buttons to the event
250
251        /*** End of Event Table ***/
252
253        ResetRolls();
254        ClearDiceHash();
255        m_yahtzee = false;
256        m_yahtzeebonus = false;
257        m_numofplaysleft = 13;
258
259 }
260
261/*********EVENT PROCCESSING FUNCTIONS********/
262
263
264void MainFrame::OnAbout(wxCommandEvent& event)
265{
266        AboutDialog *about = new AboutDialog(this,wxID_ANY,wxT("About Open Yahtzee"));
267        about->ShowModal();
268}
269
270/**
271 * Connects to the Open Yahtzee website on sourceforge.net and checks for
272 * updates to the game.
273 * \param event
274 */
275void MainFrame::OnCheckForUpdates (wxCommandEvent& event)
276{
277       
278        wxString link = wxT("http://openyahtzee.sourceforge.net/update.php?version=");
279       
280        link += wxT(OY_VERSION);
281
282        LaunchBrowser(link);
283}
284
285
286/**
287 * Starts up the user browser and connects to the Open Yahtzee website's
288 * feedback page.
289 * \param event
290 */
291void MainFrame::OnSendComment (wxCommandEvent& event)
292{
293        wxString link = wxT("http://openyahtzee.sourceforge.net/feedback.php");
294       
295        LaunchBrowser(link);
296}
297
298void MainFrame::OnQuit(wxCommandEvent& event)
299{
300        // Destroy the frame
301        Close();
302}
303
304/**
305 * This is the event handler of the New Game menu item. It starts a new
306 * game and clears the board from the last game.
307 * \param event
308 */
309void MainFrame::OnNewGame(wxCommandEvent& event)
310{
311        //disable the undo button so it won't be enabled when a new game is started.
312        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
313       
314        ResetRolls();
315        ClearDiceHash();
316        m_yahtzee = false;
317        m_numofplaysleft = 13;
318       
319        for (int i = ID_ACESTEXT; i<= ID_GRANDTOTAL; i++)
320                ((wxTextCtrl*) FindWindow(i))->Clear();
321        for (int i = ID_ACES; i<= ID_CHANCE; i++)
322                ((wxButton*) FindWindow(i))->Enable(true);
323}
324
325/**
326 * This function handles the undo events. It's connected to the Undo menu item.
327 *
328 * Note that the function only allows undoing of scoring actions and not dice
329 * rolls. Also it won't allow the undoing of the last move of the game because
330 * of a technical problem relating to the case an high-score was made and then
331 * the user undo the last move and rescore another high-score and so on.
332 * \param event
333 */
334void MainFrame::OnUndo(wxCommandEvent& event)
335{
336        m_rolls = m_rollsundo;
337
338        //after the user scored the button was enabled, check if it should be disabled
339        if (m_rolls <= 0) //we don't have remaining rolls
340                ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
341
342        //restore the 'keep' checkboxes
343        for (int i=0; i<5; i++)
344                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(true);
345       
346        //reset the users last choice
347        FindWindow(m_lastmove)->Enable(true);
348
349        //clear the score;
350        ((wxTextCtrl*)FindWindow(ID_ACESTEXT + (m_lastmove - ID_ACES)))->SetValue(wxT(""));
351
352        //undo also the yahtzee bonus if needed
353        if (m_yahtzeebonus) {
354                long temp;
355                wxString tempstr;
356       
357                tempstr = ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> GetValue();
358                tempstr.ToLong(&temp,10);
359                temp -= 100; //this line reduces the points given for the yahtzee bonus
360                tempstr.Printf(wxT("%i"),temp);
361                ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> SetValue(tempstr);
362        }
363
364        //recalculate the subtotals
365        CalculateSubTotal();
366
367        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
368        //cancel the counting for the choice that was canceled
369        m_numofplaysleft++;
370}
371
372/**
373 * This function enables the undo button and stores the last move
374 * \param id
375 */
376inline void MainFrame::EnableUndo(int id)
377{
378        if (m_numofplaysleft) {
379                (GetMenuBar()->FindItem(ID_UNDO))->Enable(true);
380                m_lastmove = id;
381        }
382}
383
384/**
385 * Shows the high-score dialog. Connected to the Game->"Show High Score" menu item.
386 * \param event
387 */
388void MainFrame::OnShowHighscore(wxCommandEvent& event)
389{
390        HighScoreDialog *dialog = new HighScoreDialog(this,wxID_ANY,m_highscoredb);
391        dialog->ShowModal();
392}
393
394/**
395 * Shows the settings dialog. This event-handler is connected to Game->Settings
396 * menu item.
397 * \param event
398 */
399void MainFrame::OnSettings( wxCommandEvent& event)
400{
401        SettingsDialog *dialog = new SettingsDialog(this,wxID_ANY);
402        SettingsDialogData data;
403        std::ostringstream sstr;
404       
405        data.highscoresize = m_highscoredb->GetSize();
406
407        data.animate = (m_settingsdb->GetKey("animate")=="Yes")?true:false;
408        data.subtotal = (m_settingsdb->GetKey("calculatesubtotal")=="Yes")?true:false;
409       
410        dialog->SetData(data);
411        if(dialog->ShowModal()==wxID_OK) { //user saved Changes
412                data = dialog->GetData();
413
414                if(data.reset)
415                        m_highscoredb->SetSize(0);
416               
417                sstr<<data.highscoresize<<std::flush;
418                m_settingsdb->SetKey("highscoresize",sstr.str());
419                               
420                m_highscoredb->SetSize(data.highscoresize);
421               
422                if (data.animate){
423                        m_settingsdb->SetKey("animate","Yes");
424                        m_animate = true;
425                       
426                } else {
427                        m_settingsdb->SetKey("animate","No");
428                        m_animate = false;
429                }
430                if (data.subtotal){
431                        m_settingsdb->SetKey("calculatesubtotal","Yes");
432                        m_calculatesubtotal = true;
433                       
434                } else {
435                        m_settingsdb->SetKey("calculatesubtotal","No");
436                        m_calculatesubtotal = false;
437                }
438
439        }
440}
441
442/**
443 * Event handler for the Roll button. It checks the settings if it should
444 * animate the dice and then rolls them accordingly. It also checks for the
445 * status of the "keep" checkboxes.
446 * \param event
447 */
448void MainFrame::OnRollButton (wxCommandEvent& event)
449{
450        if (event.GetEventType() == wxEVT_ENABLE_ROLL) {
451                //here we reconnect the event handler. We should recieve this event only after
452                //the dice stopped rolling and all other click events where skipped.
453                Connect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnRollButton));
454                return;
455        }
456        //Disconnect the button so we won't recieve new events untill we finish rolling the dice.
457        Disconnect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnRollButton));
458
459        //roll the dice...
460        if (m_animate) {
461                int dice_throws[5] = {0,0,0,0,0};
462                for (int i=0; i<5; i++) { //set the number of rolls for each dice
463                        if (!((wxCheckBox*) FindWindow(i + ID_DICE1KEEP))->IsChecked()) {
464                                dice_throws[i] = (rand()%15)+3; //ensures the number is at least one.
465                        }
466                }
467                while (dice_throws[0] || dice_throws[1] || dice_throws[2] || dice_throws[3] || dice_throws[4]) {
468                        for (int i=0 ; i<5; i++){
469                                if(dice_throws[i]){
470                                        dice_throws[i]--;
471                                        dice[i] = rand()%6;
472                                        ((wxDynamicBitmap*) FindWindow(i + ID_DICE1)) -> SetBitmap(*bitmap_dices[dice[i]]);
473                                }
474                        }
475                        ::wxMilliSleep(100);
476                }
477        } else {
478                for (int i=0; i<5; i++) {
479                        if (!((wxCheckBox*) FindWindow(i + ID_DICE1KEEP))->IsChecked()) {
480                                dice[i] = rand()%6;
481                                ((wxDynamicBitmap*) FindWindow(i + ID_DICE1)) -> SetBitmap(*bitmap_dices[dice[i]]);
482                        }
483                }
484        }
485       
486        //Clear old dice-hash and create a new one
487        ClearDiceHash();
488        for (int i=0; i<5; i++)
489                dicehash[dice[i]] += 1;
490
491        //if out of rolls disable the roll butoon
492        m_rolls -= 1;
493        #ifndef DEBUG
494        if (m_rolls <= 0)
495                ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
496        #endif
497       
498        //enable the keep checkboxes
499        for (int i=0; i<5; i++)
500                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(true);
501       
502        //we rolled the dices so undoing isn't allowed
503        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
504        m_yahtzeebonus = false; //if we scored yahtzee bonus before we don't care anymore.
505       
506        //queue the event which will cause the event-handler for clicks to be reconnected.
507        event.SetEventType(wxEVT_ENABLE_ROLL);
508        wxEvtHandler::AddPendingEvent(event);
509}
510
511/**
512 * This is the event-handler for all of the scoring buttons of the upper section.
513 *
514 * It gets the id of the button that called the event handler by comparing it
515 * to the id of the aces button it figures what button was pressed, And updates
516 * the suiting score textbox (again by comparing the id to the one of the aces
517 * checbox).
518 * \param event
519 */
520void MainFrame::OnUpperButtons (wxCommandEvent& event)
521{
522        wxString out;
523        int temp;
524        if(m_rolls < 3){
525                YahtzeeBonus();
526                temp = dicehash[(event.GetId() - ID_ACES)] * (event.GetId() - ID_ACES + 1);
527       
528                out.Printf(wxT("%i"),temp);
529                ((wxTextCtrl*) FindWindow(event.GetId() - ID_ACES + ID_ACESTEXT))->SetValue(out);
530               
531                PostScore(event.GetId());
532        }
533        else
534                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
535}
536
537/**
538 * Event handler for the "3 of a kind" score button.
539 * \param event
540 */
541void MainFrame::On3ofakindButton(wxCommandEvent& event)
542{
543        if(m_rolls>=3) {
544                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
545                return;
546        }
547        YahtzeeBonus();
548        bool three = false;
549        wxString out;
550        int temp = 0;   
551
552        //check for the conditions of scoring
553        for (int i=0; i<6; i++)
554                if (dicehash[i] >= 3)
555                        three = true;
556        if (three){
557                for(int i = 0; i<5; i++)
558                        temp += dice[i]+1;
559       
560                out.Printf(wxT("%i"),temp);
561                ((wxTextCtrl*) FindWindow(ID_THREEOFAKINDTEXT))->SetValue(out);
562        } else
563                ((wxTextCtrl*) FindWindow(ID_THREEOFAKINDTEXT))->SetValue(wxT("0"));
564       
565        PostScore(event.GetId());
566}
567
568/**
569 * Event handler for the "4 of a kind" score button.
570 * \param event
571 */
572void MainFrame::On4ofakindButton(wxCommandEvent& event)
573{
574        if(m_rolls>=3) {
575                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
576                return;
577        }
578        YahtzeeBonus();
579        bool four = false;
580        wxString out;
581        int temp = 0;   
582
583        //check for the conditions of scoring
584        for (int i=0; i<6; i++)
585                if (dicehash[i] >= 4)
586                        four = true;
587        if (four){
588                for(int i = 0; i<5; i++)
589                        temp += dice[i]+1;
590       
591                out.Printf(wxT("%i"),temp);
592                ((wxTextCtrl*) FindWindow(ID_FOUROFAKINDTEXT))->SetValue(out);
593        } else
594                ((wxTextCtrl*) FindWindow(ID_FOUROFAKINDTEXT))->SetValue(wxT("0"));
595       
596        PostScore(event.GetId());
597}
598
599/**
600 * Event handler for the full-house score button.
601 * \param event
602 */
603void MainFrame::OnFullHouseButton(wxCommandEvent& event)
604{
605        if(m_rolls>=3) {
606                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
607                return;
608        }
609        YahtzeeBonus();
610        bool two = false;
611        bool three = false;
612
613        //check for the conditions of scoring
614        for (int i=0; i<6; i++)
615                if (dicehash[i] == 2)
616                        two = true;
617        for (int i=0; i<6; i++)
618                if (dicehash[i] == 3)
619                        three = true;
620        if ((two && three) || YahtzeeJoker())
621                ((wxTextCtrl*) FindWindow(ID_FULLHOUSETEXT))->SetValue(wxT("25"));
622        else
623                ((wxTextCtrl*) FindWindow(ID_FULLHOUSETEXT))->SetValue(wxT("0"));
624       
625        PostScore(event.GetId());
626}
627
628/**
629 * Event handler for the small-sequence score button.
630 * \param event
631 */
632void MainFrame::OnSmallSequenceButton(wxCommandEvent& event)
633{
634        if(m_rolls>=3) {
635                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
636                return;
637        }
638
639        YahtzeeBonus();
640        bool sequence = false;
641        //check for the conditions of scoring
642        if ( (dicehash[0]>=1 && dicehash[1]>=1 && dicehash[2]>=1 && dicehash[3]>=1) ||
643                (dicehash[1]>=1 && dicehash[2]>=1 && dicehash[3]>=1 && dicehash[4]>=1) ||
644                (dicehash[2]>=1 && dicehash[3]>=1 && dicehash[4]>=1 && dicehash[5]>=1))
645                        sequence = true;
646        if (sequence || YahtzeeJoker())
647                ((wxTextCtrl*) FindWindow(ID_SMALLSEQUENCETEXT))->SetValue(wxT("30"));
648        else
649                ((wxTextCtrl*) FindWindow(ID_SMALLSEQUENCETEXT))->SetValue(wxT("0"));
650       
651        PostScore(event.GetId());
652}
653
654/**
655 * Event handler for the large-sequence score button.
656 * \param event
657 */
658void MainFrame::OnLargeSequenceButton(wxCommandEvent& event)
659{
660        if(m_rolls>=3) {
661                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
662                return;
663        }
664
665        YahtzeeBonus();
666        bool sequence = false;
667        //check for the conditions of scoring
668        if ( (dicehash[0]==1 && dicehash[1]==1 && dicehash[2]==1 && dicehash[3]==1 && dicehash[4]==1) ||
669                (dicehash[1]==1 && dicehash[2]==1 && dicehash[3]==1 && dicehash[4]==1 && dicehash[5]==1))
670                        sequence = true;
671        if (sequence || YahtzeeJoker())
672                ((wxTextCtrl*) FindWindow(ID_LARGESEQUENCETEXT))->SetValue(wxT("40"));
673        else
674                ((wxTextCtrl*) FindWindow(ID_LARGESEQUENCETEXT))->SetValue(wxT("0"));
675       
676        PostScore(event.GetId());
677}
678
679/**
680 * Event handler for the yahtzee score button.
681 * \param event
682 */
683void MainFrame::OnYahtzeeButton(wxCommandEvent& event)
684{
685        if(m_rolls>=3) {
686                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
687                return;
688        }
689        //give the score
690        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4])){
691                ((wxTextCtrl*) FindWindow(ID_YAHTZEETEXT))->SetValue(wxT("50"));
692                m_yahtzee=true;
693        } else
694                ((wxTextCtrl*) FindWindow(ID_YAHTZEETEXT))->SetValue(wxT("0"));
695
696        PostScore(event.GetId());
697}
698
699/**
700 * Evnet handler for the chance score button.
701 * \param event
702 */
703void MainFrame::OnChanceButton (wxCommandEvent& event)
704{
705        wxString out;
706        int temp = 0;
707        if(m_rolls < 3){
708                YahtzeeBonus();
709                for(int i = 0; i<5; i++)
710                        temp += dice[i]+1;
711       
712                out.Printf(wxT("%i"),temp);
713                ((wxTextCtrl*) FindWindow(ID_CHANCETEXT))->SetValue(out);
714               
715                PostScore(event.GetId());
716        }
717        else
718                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
719
720}
721
722/**
723 * Event handler for mouse clicks on the dice.
724 *
725 * When clicking on the dice this event-handler ticks the appropriate "keep" checkbox.
726 * \param event
727 */
728void MainFrame::OnDiceClick (wxCommandEvent& event)
729{
730        //tick the checkbox
731        if (((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP))->IsEnabled()){
732                bool newvalue = (((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP))->GetValue())?false:true;
733                ((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP)) -> SetValue(newvalue);
734        }
735
736        //dispatch a click event on the checkbox
737        wxCommandEvent clickevent((event.GetId()-ID_DICE1 + ID_DICE1KEEP),wxEVT_COMMAND_CHECKBOX_CLICKED);
738        clickevent.SetEventObject( this );
739        clickevent.SetId(event.GetId()-ID_DICE1 + ID_DICE1KEEP);
740        this->OnKeepClick(clickevent); ///\todo find a better way to call the event handler.
741}
742
743void MainFrame::OnKeepClick (wxCommandEvent& event)
744{
745        wxCheckBox *temp = (wxCheckBox*) FindWindow(event.GetId());
746        ((wxDynamicBitmap*) FindWindow(event.GetId()-ID_DICE1KEEP + ID_DICE1))->SetGrayScale(temp->GetValue());
747}
748
749//********************************************
750//******        General Functions       ******
751//********************************************
752
753/**
754 * This function clears the dice hash.
755 *
756 * The dice hash is just an array that holds how many dices have each value.
757 */
758void MainFrame::ClearDiceHash()
759{
760        for (int i=0; i<6; i++)
761                dicehash[i] = 0;
762}
763
764/**
765 * This function handles everything related to reseting the dice rolls after scoring.
766 */
767void MainFrame::ResetRolls()
768{
769        m_rollsundo = m_rolls;
770        m_rolls = 3;
771        ((wxButton*) FindWindow(ID_ROLL)) -> Enable(true);
772        for (int i=0; i<5; i++){
773                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> SetValue(false);
774                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(false);
775                ((wxDynamicBitmap*) FindWindow(i+ID_DICE1)) -> SetGrayScale(false);
776        }
777}
778
779/**
780 * This function checks for a Yahtzee Bonus situation and if one exists it scores accordingly.
781 */
782void MainFrame::YahtzeeBonus()
783{
784        long temp;
785        wxString tempstr;
786       
787        //if the player didn't have any yathzees yet he can't have the bonus;
788        if (!m_yahtzee)
789                return;
790        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4])) {
791                tempstr = ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> GetValue();
792                tempstr.ToLong(&temp,10);
793                temp += 100;
794                tempstr.Printf(wxT("%i"),temp);
795                ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> SetValue(tempstr);
796                m_yahtzeebonus = true;
797        }       
798}
799
800/**
801 * This function checks whether we have a Yahtzee Joker situation.
802 * \return true if there is Yahtzee Joker, false otherwise.
803 */
804bool MainFrame::YahtzeeJoker()
805{
806        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4]) && !(FindWindow(ID_ACES+dice[0])->IsEnabled()) && !(FindWindow(ID_YAHTZEE)->IsEnabled())) {
807                return true;
808        }
809        return false;
810}
811
812/**
813 * This function handles the end of game.
814 *
815 * When a game ends it calculates the total score and submit it to the high
816 * score list.
817 */
818void MainFrame::EndofGame()
819{
820        if(m_numofplaysleft>0)
821                return;
822       
823        wxString tempstr;
824        long temp;
825        long upperscore = 0;
826        long lowerscore = 0;
827
828        for (int i = ID_ACESTEXT; i<=ID_SIXESTEXT; i++){
829                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
830                tempstr.ToLong(&temp,10);
831                upperscore +=temp;
832        }
833       
834        tempstr.Printf(wxT("%i"),upperscore);
835        ((wxTextCtrl*) FindWindow(ID_UPPERSECTIONTOTAL)) -> SetValue(tempstr);
836       
837        //check for bonus
838        if(upperscore>=63) {
839                ((wxTextCtrl*) FindWindow(ID_BONUS)) -> SetValue(wxT("35"));
840                upperscore +=35;
841        } else
842                ((wxTextCtrl*) FindWindow(ID_BONUS)) -> SetValue(wxT("0"));
843       
844        tempstr.Printf(wxT("%i"),upperscore);
845        ((wxTextCtrl*) FindWindow(ID_UPPERTOTAL)) -> SetValue(tempstr);
846       
847        //calculate total on lower section
848        for (int i = ID_THREEOFAKINDTEXT; i<=ID_YAHTZEEBONUSTEXT; i++) {
849                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
850                tempstr.ToLong(&temp,10);
851                lowerscore +=temp;
852        }
853       
854        tempstr.Printf(wxT("%i"),lowerscore);
855        ((wxTextCtrl*) FindWindow(ID_LOWERTOTAL)) -> SetValue(tempstr);
856        tempstr.Printf(wxT("%i"),upperscore + lowerscore);
857        ((wxTextCtrl*) FindWindow(ID_GRANDTOTAL)) -> SetValue(tempstr);
858
859        //disable the roll button;
860        ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
861
862        tempstr.Printf(wxT("Your final score is %i points!"),lowerscore+upperscore);
863        wxMessageBox(tempstr, wxT("Game Ended"), wxOK | wxICON_INFORMATION, this);
864
865        //submit to high score
866        HighScoreHandler(lowerscore+upperscore);
867       
868}
869
870/**
871 * This function checks if a given score qualifies for the high score list and
872 * adds it to the list if it does.
873 * @param score The score submitted to the high score list.
874 */
875void MainFrame::HighScoreHandler(int score)
876{
877        int place;
878        std::string name,date;
879        wxCommandEvent newevent;
880
881
882        place = m_highscoredb->IsHighScore(score);
883       
884        if(!place)  //if the score didn't make it to the highscore table do nothing
885                return;
886       
887        wxString msg;
888        msg.Printf(wxT("Your score made it to the high score table. Your place is number %i.\nPlease enter your name below:"),place);
889
890        wxTextEntryDialog infodialog(this,msg,wxT("Please enter your name"),wxT(""),wxOK | wxCENTRE);
891        infodialog.ShowModal();
892
893        name = infodialog.GetValue().mb_str();
894
895        //get the date
896        wxDateTime now = wxDateTime::Now();
897        date = now.FormatISOTime().mb_str();
898        date +=" ";
899        date += now.FormatDate().mb_str();
900
901        m_highscoredb->SendHighScore(name,date,score);
902
903        //now show the high score table
904        newevent.SetId(ID_SHOWHIGHSCORE);
905        newevent.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
906        ProcessEvent(newevent);
907
908}
909
910///this function handles all the post scoring stuff such as disabling the right button.
911/**
912 * This function is always called after scoring and it handles all the post-score
913 * stuff such as reseting the dice rolls, enabling the undo button, calculating
914 * the sub-total scores and ending the game if necessary.
915 * \param id
916 */
917void MainFrame::PostScore(int id)
918{
919        //now after the scoring reset the rolls
920        ResetRolls();
921
922        CalculateSubTotal();
923
924        //and disable the button
925        FindWindow(id)->Enable(false);
926        m_numofplaysleft--;
927        EnableUndo(id);
928        EndofGame();
929}
930
931/**
932 * This function calculates the sub-total scores and should be called after
933 * every score. It does so only if this feature is requested in the settings
934 * dialog.
935 */
936void MainFrame::CalculateSubTotal()
937{
938        if (!m_calculatesubtotal)
939                return;
940        long upperscore = 0;
941        long lowerscore = 0;
942        wxString tempstr;
943        long temp;
944
945
946        for (int i = ID_ACESTEXT; i<=ID_SIXESTEXT; i++){
947                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
948                tempstr.ToLong(&temp,10);
949                upperscore +=temp;
950        }
951       
952        tempstr.Printf(wxT("%i"),upperscore);
953        ((wxTextCtrl*) FindWindow(ID_UPPERSECTIONTOTAL)) -> SetValue(tempstr);
954
955        for (int i = ID_THREEOFAKINDTEXT; i<=ID_YAHTZEEBONUSTEXT; i++) {
956                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
957                tempstr.ToLong(&temp,10);
958                lowerscore +=temp;
959        }
960       
961        tempstr.Printf(wxT("%i"),lowerscore);
962        ((wxTextCtrl*) FindWindow(ID_LOWERTOTAL)) -> SetValue(tempstr);
963}
964
965
966/**
967 * Initializes the database and stores default settings if needed.
968 * @return 0 if some error
969 */
970int MainFrame::InitializeDatabase()
971{
972        std::ostringstream sstr;
973
974
975        if (m_settingsdb->GetKey("highscoresize") == "") { //check if we need to create a new high score table
976                m_highscoredb->SetSize(DEF_HIGHSCORESIZE);
977                sstr<<DEF_HIGHSCORESIZE<<std::flush;
978                m_settingsdb->SetKey("highscoresize", sstr.str());
979        } else {
980                int highscoresize = atoi((m_settingsdb->GetKey("highscoresize")).c_str());
981                //m_highscoredb->SetSize((highscoresize>0)?highscoresize:DEF_HIGHSCORESIZE);
982                m_highscoredb->SetSize(highscoresize);
983        }
984       
985        if (m_settingsdb->GetKey("animate") == "Yes") {
986                m_animate = true;
987        } else if (m_settingsdb->GetKey("animate") == "No") {
988                m_animate = false;
989        } else {
990                m_settingsdb->SetKey("animate", "Yes");
991                m_animate = true;
992        }
993        if (m_settingsdb->GetKey("calculatesubtotal") == "Yes") {
994                m_calculatesubtotal = true;
995        } else if (m_settingsdb->GetKey("calculatesubtotal") == "No") {
996                m_calculatesubtotal = false;
997        } else {
998                m_settingsdb->SetKey("calculatesubtotal", "Yes");
999                m_calculatesubtotal = true;
1000        }
1001       
1002        if (m_settingsdb->GetKey("openyahtzeehomepage") == "") {
1003                m_settingsdb->SetKey("openyahtzeehomepage", "http://openyahtzee.sourceforge.net/");
1004        }
1005
1006        if (m_settingsdb->GetKey("updateurl") == "") {
1007                /*the version string will be appended in the end of the
1008                  given url */
1009                m_settingsdb->SetKey("updateurl", "http://openyahtzee.sourceforge.net/update.php?version=");
1010        }
1011       
1012        return 1;
1013}
Note: See TracBrowser for help on using the repository browser.