kreversigame.h 7.23 KB
Newer Older
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
1 2 3
/*******************************************************************
 *
 * Copyright 2006 Dmitry Suzdalev <dimsuz@gmail.com>
Denis Kuplyakov's avatar
Denis Kuplyakov committed
4
 * Copyright 2013 Denis Kuplaykov <dener.kup@gmail.com>
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This file is part of the KDE project "KReversi"
 *
 * KReversi is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * KReversi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with KReversi; see the file COPYING.  If not, write to
 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 ********************************************************************/
24 25 26 27
#ifndef KREVERSI_GAME_H
#define KREVERSI_GAME_H

#include <QObject>
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
28
#include <QStack>
Denis Kuplyakov's avatar
Denis Kuplyakov committed
29
#include <QTimer>
30

31 32 33 34
#include "Engine.h"
#include "commondefs.h"
#include "kreversiplayer.h"

35
class Engine;
Denis Kuplyakov's avatar
Denis Kuplyakov committed
36
class KReversiPlayer;
37 38 39 40

/**
 *  KReversiGame incapsulates all of the game logic.
 *  Whenever the board state changes it emits corresponding signals.
41 42
 *  The idea is also to abstract from any graphic representation of the game
 *  process
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
43
 *
44
 *  KReversiGame receives signals from KReversiPlayer classes.
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
45 46 47
 *  I.e. it receives commands and emits events when it's internal state changes
 *  due to this commands dispatching.
 *
48 49 50 51
 *  See KReversiView, KReversiPlayer, KReversiHumanPlayer
 *  and KReversiComputerPlayer for example of working with KReversiGame
 *
 *  @see KReversiView, KReversiPlayer, KReversiHumanPlayer
52 53 54
 */
class KReversiGame : public QObject
{
55
    Q_OBJECT
56
public:
57 58 59
    /**
     * Constructs game with two specified players.
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
60
    KReversiGame(KReversiPlayer *blackPlayer, KReversiPlayer *whitePlayer);
61
    ~KReversiGame();
62
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
63
     *  @return if undo is possible
64
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
65
    bool canUndo() const;
66
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
67 68
     *  Undoes all the opponent of current player moves and one his move
     *  (so after calling this function it will be still current player turn)
69
     *  @return number of undone moves
70
     */
71
    int undo();
72
    /**
73
     *  @return score (number of chips) of the @p player
74
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
75
    int playerScore(ChipColor player) const;
76
    /**
77
     *  @return color of the chip at position @p pos
78
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
79
    ChipColor chipColorAt(KReversiPos pos) const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
80
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
81
     *  @return a hint to current player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
82
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
83
    KReversiMove getHint() const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
84
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
85
     *  @return last move made
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
86
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
87
    KReversiMove getLastMove() const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
88
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
89 90 91
     *  @return a list of chips which were changed during last move.
     *  First of them will be the move itself, and the rest - chips which
     *  were turned by that move
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
92
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
93 94 95
    MoveList changedChips() const {
        return m_changedChips;
    }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
96
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
97
     *  @return a list of possible moves for current player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
98
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
99
    MoveList possibleMoves() const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
100
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
101
     *  @return whether the game is already over
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
102
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
103
    bool isGameOver() const;
104
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
105
     *  @return whether any player move is at all possible
106
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
107
    bool isAnyPlayerMovePossible(ChipColor player) const;
108
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
109
     *  @return a color of the current player
110
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
111 112 113
    ChipColor currentPlayer() const {
        return m_curPlayer;
    }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
114
    /**
115
     *  Sets animation times from players to @p delay milliseconds
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
116
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
117
    void setDelay(int delay);
Denis Kuplyakov's avatar
Denis Kuplyakov committed
118 119 120 121
    /**
     *  Get wait time for given cell before animating. Used for sequental turning of chips
     */
    int getPreAnimationDelay(KReversiPos pos) const;
122 123 124 125
    /**
     *  @return History of moves as MoveList
     */
    MoveList getHistory() const;
Denis Kuplyakov's avatar
Denis Kuplyakov committed
126 127 128 129 130

    /**
     *  @return Is hint allowed for current player
     */
    bool isHintAllowed() const;
131
private Q_SLOTS:
132
    /**
133
     *  Starts next player's turn.
134
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
135
    void startNextTurn();
136
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
137 138
     *  Slot used to handle moves from black player
     *  @param move Move of black player
139
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
140
    void blackPlayerMove(KReversiMove move);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
141
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
142 143
     *  Slot used to handle moves from white player
     *  @param move Move of white player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
144
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
145
    void whitePlayerMove(KReversiMove move);
146
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
147
     *  Slot to handle end of animations with m_delayTimer
148
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
149
    void onDelayTimer();
150 151 152 153 154 155 156 157 158
    /**
     *  Slot to handle ready-status of black player
     */
    void blackReady();
    /**
     *  Slot to handle ready-status of white player
     */
    void whiteReady();

159
Q_SIGNALS:
160
    void gameOver();
161
    void boardChanged();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
162
    void moveFinished();
Denis Kuplyakov's avatar
Denis Kuplyakov committed
163 164 165 166
    void whitePlayerCantMove();
    void blackPlayerCantMove();
    void whitePlayerTurn();
    void blackPlayerTurn();
167
private:
168
    // predefined direction arrays for easy implementation
Denis Kuplyakov's avatar
Denis Kuplyakov committed
169 170 171
    static const int DIRECTIONS_COUNT = 8;
    static const int DX[];
    static const int DY[];
172 173 174
    /**
     *  Used to make player think about his move again after unpossible move
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
175 176
    void kickCurrentPlayer();
    /**
177 178
     *  This will make the player @p move
     *  If that is possible, of course
Denis Kuplyakov's avatar
Denis Kuplyakov committed
179
     */
Laurent Montel's avatar
Laurent Montel committed
180
    void makeMove(KReversiMove move);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
181 182 183
    /**
     * This function will tell you if the move is possible.
     */
Laurent Montel's avatar
Laurent Montel committed
184
    bool isMovePossible(KReversiMove move) const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
185
    /**
186
     *  Searches for "chunk" in direction @p dirNum for @p move.
187
     *  As my English-skills are somewhat limited, let me introduce
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
188 189
     *  new terminology ;).
     *  I'll define a "chunk" of chips for color "C" as follows:
190
     *  (let "O" be the color of the opponent for color "C")
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
191 192 193
     *  CO[O]C <-- this is a chunk
     *  where [O] is one or more opponent's pieces
     */
Laurent Montel's avatar
Laurent Montel committed
194
    bool hasChunk(int dirNum, KReversiMove move) const;
195
    /**
196
     *  Performs @p move, i.e. marks all the chips that player wins with
197 198
     *  this move with current player color
     */
Laurent Montel's avatar
Laurent Montel committed
199
    void turnChips(KReversiMove move);
Denis Kuplyakov's avatar
Denis Kuplyakov committed
200
    /**
201
     *  Sets the type of chip according to @p move
Denis Kuplyakov's avatar
Denis Kuplyakov committed
202
     */
Laurent Montel's avatar
Laurent Montel committed
203
    void setChipColor(KReversiMove move);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
204
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
205
     *  Delay time
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
206
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
207
    int m_delay;
208 209 210 211 212
    /**
     *  Status flags used to know when both players are ready
     */
    bool m_isReady[2];
    /**
213
     *  Last player who has made a move. Cannot be NoColor after the first move
214
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
215
    ChipColor m_lastPlayer;
216 217 218 219 220 221 222 223
    /**
     *  The board itself
     */
    ChipColor m_cells[8][8];
    /**
     *  Score of each player
     */
    int m_score[2];
224
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
225
     *  AI to give hints
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
226
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
227
    Engine *m_engine;
228
    /**
229 230
     *  Color of the current player.
     *  @c NoColor if it is interchange for animations
231
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
232
    ChipColor m_curPlayer;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
233 234 235 236 237 238
    /**
     *  This list holds chips that were changed/added during last move
     *  First of them will be the chip added to the board by the player
     *  during last move. The rest of them - chips that were turned by that
     *  move.
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
239
    MoveList m_changedChips;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
240
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
241
     *  This is an undo stack.
242 243
     *  It contains a lists of chips changed with each turn.
     *  @see m_changedChips
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
244
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
245 246 247 248 249 250
    QStack<MoveList> m_undoStack;
    /**
     *  Used to handle end of player's animations or other stuff
     */
    QTimer m_delayTimer;

251 252 253
    /**
     *  Actual players, who play the game
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
254
    KReversiPlayer *m_player[2];
255 256
};
#endif