kreversigame.h 6.49 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 30
#include <KDebug>
#include <QTimer>
31

Denis Kuplyakov's avatar
Denis Kuplyakov committed
32
#include "Engine.h"
33
class Engine;
Denis Kuplyakov's avatar
Denis Kuplyakov committed
34 35 36
#include "commondefs.h"
#include "kreversiplayer.h"
class KReversiPlayer;
37 38 39 40 41

/**
 *  KReversiGame incapsulates all of the game logic.
 *  Whenever the board state changes it emits corresponding signals.
 *  The idea is also to abstract from any graphic representation of the game process
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
42 43 44 45 46
 *
 *  KReversiGame is supposed to be driven by someone from outside.
 *  I.e. it receives commands and emits events when it's internal state changes
 *  due to this commands dispatching.
 *  The main commands are:
47
 *  startNextTurn() and  makePlayerMove()
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
48
 *
49
 *  See KReversiView for example of working with KReversiGame
50 51 52
 */
class KReversiGame : public QObject
{
53
    Q_OBJECT
54
public:
Denis Kuplyakov's avatar
Denis Kuplyakov committed
55
    KReversiGame(KReversiPlayer *blackPlayer, KReversiPlayer *whitePlayer);
56
    ~KReversiGame();
57
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
58
     *  @return if undo is possible
59
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
60 61 62
    bool canUndo() const {
        return !m_undoStack.isEmpty();
    }
63
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
64 65
     *  Undoes all the opponent of current player moves and one his move
     *  (so after calling this function it will be still current player turn)
66
     *  @return number of undone moves
67
     */
68
    int undo();
69
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
70
     *  @return score (number of chips) of the player
71
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
72
    int playerScore(ChipColor player) const;
73
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
74
     *  @return color of the chip at position [row, col]
75
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
76
    ChipColor chipColorAt(KReversiPos pos) const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
77
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
78
     *  @return a hint to current player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
79
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
80
    KReversiMove getHint() const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
81
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
82
     *  @return last move made
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
83
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
84
    KReversiMove getLastMove() const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
85
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
86 87 88
     *  @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
89
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
90 91 92
    MoveList changedChips() const {
        return m_changedChips;
    }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
93
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
94
     *  @return a list of possible moves for current player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
95
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
96
    MoveList possibleMoves() const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
97
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
98
     *  @return whether the game is already over
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
99
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
100
    bool isGameOver() const;
101
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
102
     *  @return whether any player move is at all possible
103
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
104
    bool isAnyPlayerMovePossible(ChipColor player) const;
105
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
106
     *  @return a color of the current player
107
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
108 109 110
    ChipColor currentPlayer() const {
        return m_curPlayer;
    }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
111
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
112
     *  Sets animation times from players
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
113
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
114 115
    void setDelay(int delay);
private slots:
116
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
117
     *  Starts next player turn.
118
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
119
    void startNextTurn();
120
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
121 122
     *  Slot used to handle moves from black player
     *  @param move Move of black player
123
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
124
    void blackPlayerMove(KReversiMove move);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
125
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
126 127
     *  Slot used to handle moves from white player
     *  @param move Move of white player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
128
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
129
    void whitePlayerMove(KReversiMove move);
130
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
131
     *  Slot to handle end of animations with m_delayTimer
132
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
133
    void onDelayTimer();
134
signals:
135
    void gameOver();
136
    void boardChanged();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
137
    void moveFinished();
Denis Kuplyakov's avatar
Denis Kuplyakov committed
138 139 140 141
    void whitePlayerCantMove();
    void blackPlayerCantMove();
    void whitePlayerTurn();
    void blackPlayerTurn();
142
private:
Denis Kuplyakov's avatar
Denis Kuplyakov committed
143 144 145 146 147 148 149 150 151
    static const int DIRECTIONS_COUNT = 8;
    static const int DX[];
    static const int DY[];
    void kickCurrentPlayer();
    /**
     *  This will make the player move
     *  If that is possible of course
     */
    void makeMove(const KReversiMove &move);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
152 153 154 155
    /**
     * This function will tell you if the move is possible.
     * That's why it was given such a name ;)
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
156
    bool isMovePossible(const KReversiMove &move) const;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
157 158
    /**
     *  Searches for "chunk" in direction dir for move.
159
     *  As my English-skills are somewhat limited, let me introduce
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
160 161
     *  new terminology ;).
     *  I'll define a "chunk" of chips for color "C" as follows:
162
     *  (let "O" be the color of the opponent for color "C")
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
163 164 165
     *  CO[O]C <-- this is a chunk
     *  where [O] is one or more opponent's pieces
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
166
    bool hasChunk(int dirNum, const KReversiMove &move) const;
167 168 169 170
    /**
     *  Performs move, i.e. marks all the chips that player wins with
     *  this move with current player color
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
171 172 173 174 175
    void turnChips(const KReversiMove &move);
    /**
     *  Sets the type of chip acording to KReversiMove
     */
    void setChipColor(const KReversiMove &move);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
176
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
177
     *  Delay time
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
178
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
179 180
    int m_delay;
    ChipColor m_lastPlayer;
181 182 183 184 185 186 187 188
    /**
     *  The board itself
     */
    ChipColor m_cells[8][8];
    /**
     *  Score of each player
     */
    int m_score[2];
189
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
190
     *  AI to give hints
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
191
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
192
    Engine *m_engine;
193
    /**
Denis Kuplyakov's avatar
Denis Kuplyakov committed
194
     *  Color of the current player
195
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
196
    ChipColor m_curPlayer;
Denis Kuplyakov's avatar
Denis Kuplyakov committed
197 198 199 200
    // Well I'm not brief at all :). That's because I think that my
    // English is not well shaped sometimes, so I try to describe things
    // so that me and others can understand. Even simple things.
    // Specially when I think that my description sucks :)
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
201 202 203 204 205 206
    /**
     *  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
207
    MoveList m_changedChips;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
208
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
209
     *  This is an undo stack.
210 211
     *  It contains a lists of chips changed with each turn.
     *  @see m_changedChips
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
212
     */
Denis Kuplyakov's avatar
Denis Kuplyakov committed
213 214 215 216 217 218 219
    QStack<MoveList> m_undoStack;
    /**
     *  Used to handle end of player's animations or other stuff
     */
    QTimer m_delayTimer;

    KReversiPlayer *m_player[2];
220 221
};
#endif