File indexing completed on 2024-11-24 03:43:18
0001 /******************************************************************* 0002 * 0003 * Copyright 2007 Aron Boström <c02ab@efd.lth.se> 0004 * 0005 * Bovo is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation; either version 2, or (at your option) 0008 * any later version. 0009 * 0010 * Bovo is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with Bovo; see the file COPYING. If not, write to 0017 * the Free Software Foundation, 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 * 0020 ********************************************************************/ 0021 0022 /** @file game.h declares class Game in namespace bovo */ 0023 0024 #ifndef BOVO_GAME_H 0025 #define BOVO_GAME_H 0026 0027 #include <KGameDifficulty> 0028 #include <QList> 0029 #include <QObject> 0030 #include <QStringList> 0031 0032 #include "common.h" 0033 #include "move.h" 0034 0035 0036 /** namespace for ai */ 0037 namespace ai 0038 { 0039 class Ai; 0040 class AiFactory; 0041 } /* namespace ai */ 0042 0043 using namespace ai; 0044 0045 /** namespace for game engine */ 0046 namespace bovo 0047 { 0048 class Board; 0049 class Dimension; 0050 class Coord; 0051 0052 /** 0053 * The Game engine 0054 * 0055 * This class is supposed to replace the gui/Game class and the game/board 0056 * class. 0057 * 0058 * It keeps track of the both players (AI, network, gui or whatever). 0059 * It keeps track of the playing board, and its playing history. 0060 * It can walk up or down the playing history (undo). 0061 * It can call an AI player of its own, to give the active player a hint. 0062 * It decides if a game has ended (someone has won or it is a draw). 0063 * It can tell which is the winning line and the winning move. 0064 * 0065 * @code 0066 * Dimension dimension(width, height); 0067 * Game game(dimension, X); 0068 * MoveStatus status = game.move(Coord(x, y)); 0069 * if (status.error()) { 0070 * qDebug() << status.toQString() << endl; 0071 * // status.turn() == true => not your turn 0072 * // status.busy() == true => tried to play an already busy coordinate 0073 * // status.gameOver() == true => game is already over 0074 * } 0075 * @endcode 0076 */ 0077 class Game : public QObject 0078 { 0079 Q_OBJECT 0080 public: 0081 /** 0082 * @brief Constructs a Game 0083 * @description Constructs a Game object with a playing board with 0084 * width and height specified by a given Dimension, a starting Player and 0085 * an AI skill level 0086 * @param dimension the Dimension specifying the width and height 0087 * @param startingPlayer the player who starts 0088 * @param skill the skill (difficulty level) of the AI 0089 * @param demoMode whether this game is a demo or not 0090 * @param playTime time in ms for space between turns in demo and replay 0091 * @param aiFactory provider of AI implementations 0092 */ 0093 Game(const Dimension &dimension, 0094 Player startingPlayer, 0095 KGameDifficultyLevel::StandardLevel skill, 0096 DemoMode demoMode, 0097 unsigned int playTime, 0098 AiFactory *aiFactory); 0099 0100 /** 0101 * @brief Re-Constructs a saved Game 0102 * @description Constructs a Game object with a playing board with 0103 * width and height specified by a given Dimension, a game history and 0104 * an AI skill level 0105 * @param dimension the Dimension specifying the width and height 0106 * @param restoreGame the game history to restore 0107 * @param skill the skill (difficulty level) of the AI 0108 * @param playTime time in ms for space between turns in demo and replay 0109 * @param aiFactory provider of AI implementations 0110 */ 0111 Game(const Dimension &dimension, const QStringList &restoreGame, KGameDifficultyLevel::StandardLevel skill, unsigned int playTime, AiFactory *aiFactory); 0112 0113 /** 0114 * @brief destructs this Game 0115 * @description destructs this Game object 0116 */ 0117 ~Game() override; 0118 0119 /** 0120 * @brief is it the computer's turn? 0121 * @description tells whether the computer is the one with the current turn 0122 * @return \c true if computer is at turn, \c false otherwise 0123 */ 0124 bool computerTurn() const; 0125 0126 /** 0127 * @brief is game in demo mode? 0128 * @return \c Demo if game is in demo mode, \c NotDemo otherwise 0129 */ 0130 DemoMode demoMode() const; 0131 0132 /** 0133 * @brief is Game Over? 0134 * @description tells whether game is over (someone has won) or not 0135 * @return \c true if game has ended, \c false if game is still on 0136 */ 0137 bool isGameOver() const; 0138 0139 /** 0140 * @brief the game history 0141 * @description gives the history as a linked list, starting with oldest 0142 * moves first. 0143 * @return the game history 0144 */ 0145 QList<Move> history() const; 0146 0147 /** 0148 * @brief the latest move 0149 * @description returns the latest move that has been performed 0150 * @return the latest move performed 0151 */ 0152 Move latestMove() const; 0153 0154 /** 0155 * @brief is this coordinate on board? 0156 * @description tells whether this coordinate is within the limits of the 0157 * playing board. 0158 * @param coord coordinate to verify 0159 * @return \c true if coordinate is ok, \c false otherwise 0160 */ 0161 bool ok(const Coord &coord) const; 0162 0163 /** 0164 * @brief the player id 0165 * @return the player id 0166 */ 0167 Player player() const; 0168 0169 /** 0170 * @brief sets the AI skill 0171 * @description sets the skill level of the AI 0172 * @param skill new skill (difficulty level) for the AI 0173 */ 0174 void setSkill(KGameDifficultyLevel::StandardLevel skill); 0175 0176 /** 0177 * @brief starts a new turn 0178 * @description starts a new turn 0179 */ 0180 void start(); 0181 0182 /** 0183 * @brief gets the player of a coordinate 0184 * @description returns the player id of a coordinate in the playing board 0185 * @param coord coordinate to query 0186 * @return \c X, \c O, or \c No 0187 */ 0188 Player player(const Coord &coord) const; 0189 0190 /** 0191 * @brief save game 0192 * Saves this game to a file 0193 * @param filename savegame file 0194 * @return \c true if game was saved successfully, \c false otherwise 0195 */ 0196 bool save(const QString &filename) const; 0197 0198 /** 0199 * @brief return game history if it is not over yet 0200 * This is used for saving an unfinished game upon quitting bovo, 0201 * so we can continue this game next time. 0202 * @return formatted savefile without line breaks 0203 */ 0204 QStringList saveLast() const; 0205 0206 /** 0207 * @brief start a game that have been restored. 0208 */ 0209 void startRestored(); 0210 0211 /** 0212 * @brief in which direction was the winning line? 0213 * @description tells in what direction the gameover was caused, or -1 if 0214 * game is still on. 0215 * @return @c -1 if game isn't over, @c 0 for horizontal, 0216 * @c 1 for vertical, @c 2 for diagonal upperleft downwards right, 0217 * @c 3 for bottomleft upwards right 0218 */ 0219 short winDir() const; 0220 0221 /** 0222 * @brief returns if the board is full 0223 * @description returns true if every field on the table is occupied 0224 */ 0225 bool boardFull() const; 0226 0227 /** 0228 * @brief cancel the AI if it is thinking and wait for actual cancellation 0229 * @description interrupts the thinking of the AI if it is thinking, and 0230 * does not return until the AI thread has really finished 0231 */ 0232 void cancelAndWait(); 0233 0234 public Q_SLOTS: 0235 /** 0236 * @brief make a move 0237 * @param move move to make 0238 */ 0239 void move(const Move &move); 0240 0241 /** 0242 * @brief start replaying game 0243 * Starts the replay of this game, emitting the signal \c replayBegin() 0244 */ 0245 void replay(); 0246 0247 /** 0248 * @brief undo the latest move in the history 0249 */ 0250 void undoLatest(); 0251 0252 Q_SIGNALS: 0253 /** 0254 * @brief emitted at game over 0255 * @param moves Winning moves (winning line) 0256 */ 0257 void gameOver(const QList<Move> &moves); 0258 0259 /** 0260 * @brief emitted when board has changed (needs repainting) 0261 * @param move the Move that has changed the board, player()==No means undo 0262 */ 0263 void boardChanged(const Move &move); 0264 0265 /** 0266 * @brief emitted when it is the player's turn 0267 */ 0268 void playerTurn(); 0269 0270 /** 0271 * @brief emitted when it is the player's turn 0272 */ 0273 void oposerTurn(); 0274 0275 /** 0276 * @brief emitted at replay, signaling the UI to clear itself 0277 */ 0278 void replayBegin(); 0279 0280 /** 0281 * @brief emitted when replay ends 0282 * @param moves winning line 0283 */ 0284 void replayEnd(const QList<Move> &moves); 0285 0286 /** 0287 * @brief emitted once this game is allowed to be undoed 0288 */ 0289 void undoAble(); 0290 0291 /** 0292 * @brief emitted once this game no longer is allowed to be undoed 0293 */ 0294 void undoNotAble(); 0295 0296 private Q_SLOTS: 0297 void replayNext(); 0298 0299 private: 0300 /** 0301 * @brief make a move 0302 * @description performs the specified move. 0303 * @param move move to make 0304 */ 0305 void makeMove(const Move &move); 0306 0307 /* get a neighbour coord in a given direction */ 0308 Coord next(const Coord &coord, usi direction) const; 0309 0310 /* calculates if a coord is part of a winning line */ 0311 short win(const Coord &coord) const; 0312 0313 /* returns the winning line */ 0314 QList<Move> winningMoves() const; 0315 0316 /* AI */ 0317 Ai *m_ai; 0318 0319 /* AI factory */ 0320 AiFactory *m_aiFactory; 0321 0322 /* playing board */ 0323 Board *m_board; 0324 0325 /* Current player */ 0326 Player m_curPlayer; 0327 0328 /* computer player id */ 0329 Player m_computerMark; 0330 0331 /* Whether this is a demo game or not */ 0332 DemoMode m_demoMode; 0333 0334 /* is game over? */ 0335 bool m_gameOver; 0336 0337 /* game history */ 0338 QList<Move> m_history; 0339 0340 /* if game is in Undo state */ 0341 bool m_inUndoState; 0342 0343 /* user player id */ 0344 Player m_playerMark; 0345 0346 /* time in between two moves in replay and demo mode, in milliseconds */ 0347 unsigned int m_playTime; 0348 0349 /* is game in replay mode? */ 0350 bool m_replaying; 0351 0352 /* replay iterator for history list */ 0353 QList<Move>::const_iterator m_replayIterator; 0354 0355 /* replay iterator for the end of the history */ 0356 QList<Move>::const_iterator m_replayIteratorEnd; 0357 0358 /* winning direction, or -1 if game isn't won */ 0359 short m_winDir; 0360 0361 /* the number of marks on the board */ 0362 short m_stepCount; 0363 }; 0364 0365 } /* namespace bovo */ 0366 0367 #endif // BOVO_GAME_H