File indexing completed on 2024-11-03 06:55:26
0001 /* 0002 SPDX-FileCopyrightText: 2006 Dmitry Suzdalev <dimsuz@gmail.com> 0003 SPDX-FileCopyrightText: 2013 Denis Kuplaykov <dener.kup@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef KREVERSI_GAME_H 0009 #define KREVERSI_GAME_H 0010 0011 #include <QObject> 0012 #include <QStack> 0013 #include <QTimer> 0014 0015 #include "Engine.h" 0016 #include "commondefs.h" 0017 #include "kreversiplayer.h" 0018 0019 class Engine; 0020 class KReversiPlayer; 0021 0022 /** 0023 * KReversiGame incapsulates all of the game logic. 0024 * Whenever the board state changes it emits corresponding signals. 0025 * The idea is also to abstract from any graphic representation of the game 0026 * process 0027 * 0028 * KReversiGame receives signals from KReversiPlayer classes. 0029 * I.e. it receives commands and emits events when it's internal state changes 0030 * due to this commands dispatching. 0031 * 0032 * See KReversiView, KReversiPlayer, KReversiHumanPlayer 0033 * and KReversiComputerPlayer for example of working with KReversiGame 0034 * 0035 * @see KReversiView, KReversiPlayer, KReversiHumanPlayer 0036 */ 0037 class KReversiGame : public QObject 0038 { 0039 Q_OBJECT 0040 public: 0041 /** 0042 * Constructs game with two specified players. 0043 */ 0044 KReversiGame(KReversiPlayer *blackPlayer, KReversiPlayer *whitePlayer); 0045 ~KReversiGame() override; 0046 /** 0047 * @return if undo is possible 0048 */ 0049 bool canUndo() const; 0050 /** 0051 * Undoes all the opponent of current player moves and one his move 0052 * (so after calling this function it will be still current player turn) 0053 * @return number of undone moves 0054 */ 0055 int undo(); 0056 /** 0057 * @return score (number of chips) of the @p player 0058 */ 0059 int playerScore(ChipColor player) const; 0060 /** 0061 * @return color of the chip at position @p pos 0062 */ 0063 ChipColor chipColorAt(KReversiPos pos) const; 0064 /** 0065 * @return a hint to current player 0066 */ 0067 KReversiMove getHint() const; 0068 /** 0069 * @return last move made 0070 */ 0071 KReversiMove getLastMove() const; 0072 /** 0073 * @return a list of chips which were changed during last move. 0074 * First of them will be the move itself, and the rest - chips which 0075 * were turned by that move 0076 */ 0077 MoveList changedChips() const { 0078 return m_changedChips; 0079 } 0080 /** 0081 * @return a list of possible moves for current player 0082 */ 0083 MoveList possibleMoves() const; 0084 /** 0085 * @return whether the game is already over 0086 */ 0087 bool isGameOver() const; 0088 /** 0089 * @return whether any player move is at all possible 0090 */ 0091 bool isAnyPlayerMovePossible(ChipColor player) const; 0092 /** 0093 * @return a color of the current player 0094 */ 0095 ChipColor currentPlayer() const { 0096 return m_curPlayer; 0097 } 0098 /** 0099 * Sets animation times from players to @p delay milliseconds 0100 */ 0101 void setDelay(int delay); 0102 /** 0103 * Get wait time for given cell before animating. Used for sequental turning of chips 0104 */ 0105 int getPreAnimationDelay(KReversiPos pos) const; 0106 /** 0107 * @return History of moves as MoveList 0108 */ 0109 MoveList getHistory() const; 0110 0111 /** 0112 * @return Is hint allowed for current player 0113 */ 0114 bool isHintAllowed() const; 0115 private Q_SLOTS: 0116 /** 0117 * Starts next player's turn. 0118 */ 0119 void startNextTurn(); 0120 /** 0121 * Slot used to handle moves from black player 0122 * @param move Move of black player 0123 */ 0124 void blackPlayerMove(KReversiMove move); 0125 /** 0126 * Slot used to handle moves from white player 0127 * @param move Move of white player 0128 */ 0129 void whitePlayerMove(KReversiMove move); 0130 /** 0131 * Slot to handle end of animations with m_delayTimer 0132 */ 0133 void onDelayTimer(); 0134 /** 0135 * Slot to handle ready-status of black player 0136 */ 0137 void blackReady(); 0138 /** 0139 * Slot to handle ready-status of white player 0140 */ 0141 void whiteReady(); 0142 0143 Q_SIGNALS: 0144 void gameOver(); 0145 void boardChanged(); 0146 void moveFinished(); 0147 void whitePlayerCantMove(); 0148 void blackPlayerCantMove(); 0149 void whitePlayerTurn(); 0150 void blackPlayerTurn(); 0151 private: 0152 // predefined direction arrays for easy implementation 0153 static const int DIRECTIONS_COUNT = 8; 0154 static const int DX[]; 0155 static const int DY[]; 0156 /** 0157 * Used to make player think about his move again after unpossible move 0158 */ 0159 void kickCurrentPlayer(); 0160 /** 0161 * This will make the player @p move 0162 * If that is possible, of course 0163 */ 0164 void makeMove(KReversiMove move); 0165 /** 0166 * This function will tell you if the move is possible. 0167 */ 0168 bool isMovePossible(KReversiMove move) const; 0169 /** 0170 * Searches for "chunk" in direction @p dirNum for @p move. 0171 * As my English-skills are somewhat limited, let me introduce 0172 * new terminology ;). 0173 * I'll define a "chunk" of chips for color "C" as follows: 0174 * (let "O" be the color of the opponent for color "C") 0175 * CO[O]C <-- this is a chunk 0176 * where [O] is one or more opponent's pieces 0177 */ 0178 bool hasChunk(int dirNum, KReversiMove move) const; 0179 /** 0180 * Performs @p move, i.e. marks all the chips that player wins with 0181 * this move with current player color 0182 */ 0183 void turnChips(KReversiMove move); 0184 /** 0185 * Sets the type of chip according to @p move 0186 */ 0187 void setChipColor(KReversiMove move); 0188 /** 0189 * Delay time 0190 */ 0191 int m_delay; 0192 /** 0193 * Status flags used to know when both players are ready 0194 */ 0195 bool m_isReady[2]; 0196 /** 0197 * Last player who has made a move. Cannot be NoColor after the first move 0198 */ 0199 ChipColor m_lastPlayer; 0200 /** 0201 * The board itself 0202 */ 0203 ChipColor m_cells[8][8]; 0204 /** 0205 * Score of each player 0206 */ 0207 int m_score[2]; 0208 /** 0209 * AI to give hints 0210 */ 0211 Engine *m_engine; 0212 /** 0213 * Color of the current player. 0214 * @c NoColor if it is interchange for animations 0215 */ 0216 ChipColor m_curPlayer; 0217 /** 0218 * This list holds chips that were changed/added during last move 0219 * First of them will be the chip added to the board by the player 0220 * during last move. The rest of them - chips that were turned by that 0221 * move. 0222 */ 0223 MoveList m_changedChips; 0224 /** 0225 * This is an undo stack. 0226 * It contains a lists of chips changed with each turn. 0227 * @see m_changedChips 0228 */ 0229 QStack<MoveList> m_undoStack; 0230 /** 0231 * Used to handle end of player's animations or other stuff 0232 */ 0233 QTimer m_delayTimer; 0234 0235 /** 0236 * Actual players, who play the game 0237 */ 0238 KReversiPlayer *m_player[2]; 0239 }; 0240 #endif