1/* ****************************************************************************
2 This file is part of the game 'KJumpingCube'
3
4 Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
5 Copyright (C) 2012-2013 by Ian Wadham <iandw.au@gmail.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20**************************************************************************** */
21#ifndef GAME_H
22#define GAME_H
23
24#include "ai_globals.h"
25
26#include <QTime> // IDW test.
27
28#include <KUrl>
29#include <QList>
30
31class KConfigGroup;
32class KCubeBoxWidget;
33class SettingsWidget;
34class AI_Main;
35class AI_Box;
36class QTimer;
37
38/**
39* Codes for actions available to users of the Game class.
40*/
41enum Action {NEW, HINT, BUTTON, UNDO, REDO, SAVE, SAVE_AS, LOAD};
42
43class Game : public QObject
44{
45 Q_OBJECT
46public:
47 explicit Game (const int dim, KCubeBoxWidget * view, QWidget * parent = 0);
48
49 virtual ~Game();
50
51 /**
52 * Make sure all animation and AI activity is over before closing a game.
53 * */
54 void shutdown();
55
56public slots:
57
58 /**
59 * Perform one of the game-actions listed in enum type Action.
60 *
61 * @param action The action to be performed, taken from enum Action.
62 * This parameter must be of type int because KJumpingCube
63 * invokes gameActions() via a QSignalMapper of int type.
64 */
65 void gameActions (const int action);
66
67private:
68 /**
69 * Show the winner when the game ends, either after a move or a redo.
70 */
71 void showWinner();
72
73private slots:
74 /**
75 * Pop up the settings/preferences/configuration dialog window.
76 */
77 void showSettingsDialog (bool show = true);
78
79 /**
80 * Check changes in the user's preferences or settings. Some settings can
81 * be used immediately, some must wait until the start of the next turn and
82 * a change in box size may require the user's OK (or not) to abandon a game
83 * in progress and start a new game.
84 */
85 void newSettings();
86
87 /**
88 * Check if cube at [x, y] is available to the current (human) player.
89 * If it is, make a move using doMove() and the cube at [x, y], animating
90 * the move, if required.
91 */
92 void startHumanMove (int x, int y);
93
94private:
95 /**
96 * Check if the current player is a computer player and, if so, start the
97 * next move or perhaps wait for the user to click the button to show that
98 * he or she is ready. Otherwise, wait for a human player to move.
99 */
100 void setUpNextTurn();
101
102 /**
103 * Starts calculating a computer move or hint (using asynchronous AI thread).
104 */
105 void computeMove();
106
107private slots:
108 /**
109 * Deliver a computer-move or hint calculated by the AI thread and start an
110 * animation to show which cube is to move.
111 *
112 * @param index The position of the move in the array of cubes. If the box
113 * has n x n cubes, index = x * n + y for co-ordinates [x, y].
114 */
115 void moveCalculationDone (int index);
116
117private:
118 /**
119 * Finish showing a computer move or hint. If it is a computer move, use
120 * doMove() to make the actual move and animate it, if required.
121 */
122 void showingDone (int index);
123
124 /**
125 * Increase the cube at 'index' and start the animation loop, if required.
126 */
127 void doMove (int index);
128
129 /**
130 * Perform and display one or more steps of a move, with breaks for animation
131 * if required, finishing when all steps have been done or the current player
132 * has won the game. If there is no animation or if the user clicks the
133 * action button to interrupt the animation, perform all steps at full speed.
134 */
135 void doStep();
136
137 /**
138 * Finish one step of a move, if animating, and use doStep() to continue.
139 */
140 void stepAnimationDone (int index);
141
142 /**
143 * Finish an entire move.
144 */
145 void moveDone();
146
147 /**
148 * Switch to the other player, human or computer, after a non-winning move.
149 */
150 Player changePlayer();
151
152 /**
153 * Initiate or interrupt computer-move or animation activities. This is used
154 * when the computer is first to move or when the user wishes to interrupt
155 * or step through moves, as in a computer v. computer game or a complex
156 * series of cascade moves.
157 */
158 void buttonClick();
159
160 /**
161 * Set the action-button to be red, enabled and with text relevant to
162 * stopping the current activity (AI v AI game OR computing, showing or
163 * animating a move).
164 */
165 void setStopAction();
166
167 /**
168 * Act on changes in settings that can be used immediately. Color changes
169 * can take effect when control returns to the event loop, the other settings
170 * next time they are used. They include animation settings, AI players and
171 * their skill levels.
172 */
173 void loadImmediateSettings();
174
175 /**
176 * Act on changes in the user's choice of players and computer-player pause.
177 * These can take effect only at the start of a turn.
178 */
179 void loadPlayerSettings();
180
181private slots:
182 /**
183 * Indicate that showing a move or animating a move-step has finished.
184 *
185 * @param index The position of the move in the array of cubes. If the box
186 * has n x n cubes, index = x * n + y for co-ordinates [x, y].
187 */
188 void animationDone (int index);
189
190signals:
191 /**
192 * Request that the current player be shown in the KJumpingCube main window.
193 *
194 * @param player The ID of the player (= 1 or 2).
195 */
196 void playerChanged (int newPlayer);
197
198 /**
199 * Request a change of appearance or text of the general-purpose action
200 * button in the KJumpingCube main window.
201 *
202 * @param enabled True = button is active, false = button is inactive.
203 * @param stop If active, true = use STOP style, false = use GO style.
204 * @param caption Translated text to appear on the button.
205 */
206 void buttonChange (bool enabled, bool stop = false,
207 const QString & caption = QString(""));
208
209 /**
210 * Request enabling or disabling of an action by KJumpingCube main window.
211 *
212 * @param a The game-action to be enabled or disabled.
213 * @param onOff True = enable the action, false = disable it.
214 */
215 void setAction (const Action a, const bool onOff);
216
217 /**
218 * Request display of a status message.
219 *
220 * @param message The message to be displayed (translated).
221 * @param timed If true, display the message for a limited time.
222 */
223 void statusMessage (const QString & message, bool timed);
224
225protected:
226 void saveProperties(KConfigGroup&);
227 void readProperties(const KConfigGroup&);
228
229private:
230 void loadSavedSettings (const KConfigGroup& config);
231
232private:
233 QTime t; // IDW test.
234
235 enum Activity {Idle, Computing, Stopping, Aborting,
236 ShowingMove, AnimatingMove};
237 enum WaitingState {Nil, WaitingToStep, ComputerToMove};
238
239 Activity m_activity; // Current computer activity.
240 WaitingState m_waitingState; // Current pause state.
241 bool m_waitingToMove; // If true, AI paused or human to move.
242 int m_moveNo; // Current move number, 0 = not started.
243 int m_endMoveNo; // Winning move number, if game is over.
244 bool m_interrupting; // If user has interrupted AI v. AI.
245 bool m_newSettings; // If new player settings during a move.
246
247 QWidget * m_parent; // Game object's parent (main window).
248 KCubeBoxWidget * m_view; // Displayed cubes.
249
250 // A pointer to the Settings widget defined in Qt Designer, when the
251 // Preferences dialog is first created by Game::showSettingsDialog().
252 SettingsWidget * m_settingsPage; // Displayed settings, 0 = not yet used.
253
254 AI_Box * m_box; // Game engine's cubes.
255 int m_side; // Cube box size, from Prefs::cubeDim().
256 Player m_currentPlayer; // Current player: One or Two.
257 QList<int> * m_steps; // Steps in a move to be displayed.
258
259 AI_Main * m_ai; // Current computer player.
260
261 int m_index; // Location of move.
262 bool m_fullSpeed; // If true, no animation of moves.
263
264 bool computerPlOne; // If true, Player 1 is an AI.
265 bool computerPlTwo; // If true, Player 2 is an AI.
266
267 bool m_pauseForComputer; // If true, pause before each AI move.
268 bool m_pauseForStep; // If true, pause before animation step.
269
270 KUrl m_gameURL; // Location of load/save file.
271
272private slots:
273 void newGame(); // Slot needed for queued invocation.
274
275private:
276 void saveGame (bool saveAs); // Standard save-game action.
277 void loadGame(); // Standard load-game action.
278 void undo(); // Standard undo-move action.
279 void redo(); // Standard redo-move action.
280
281 /**
282 * Check if it is OK to start a new game, maybe ending a current game.
283 */
284 bool newGameOK();
285
286 /**
287 * Reset cubebox for a new game.
288 */
289 void reset();
290
291 /**
292 * Undo or redo a move.
293 *
294 * @param change -1 = undo, +1 = redo
295 *
296 * @return true = More moves to undo/redo, false = No more to undo/redo.
297 */
298 bool undoRedo (int change);
299
300 /**
301 * Set the number of cubes in a row or column. If the number has changed,
302 * delete the existing set of cubes and create a new one.
303 */
304 virtual void setDim (int dim);
305
306 /**
307 * Returns true if the player is a computer player.
308 */
309 bool isComputer (Player player) const;
310
311 inline void restoreGame(const KConfigGroup&c) { readProperties(c); }
312};
313
314#endif // GAME_H
315