kreversigame.h 7.67 KB
Newer Older
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*******************************************************************
 *
 * Copyright 2006 Dmitry Suzdalev <dimsuz@gmail.com>
 *
 * 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.
 *
 ********************************************************************/
23 24 25 26
#ifndef KREVERSI_GAME_H
#define KREVERSI_GAME_H

#include <QObject>
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
27
#include <QStack>
28

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
29 30
#include "commondefs.h"

31
class Engine;
32

33 34 35
namespace KGGZMod
{
    class Module;
Dirk Mueller's avatar
Dirk Mueller committed
36
}
37 38 39

class KGGZRaw;

40 41 42 43
/**
 *  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
44 45 46 47 48
 *
 *  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:
49
 *  startNextTurn() and  makePlayerMove()
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
50 51
 *
 *  See KReversiScene for example of working with KReversiGame
52 53 54
 */
class KReversiGame : public QObject
{
55
    Q_OBJECT
56
public:
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
57
    KReversiGame();
58
    ~KReversiGame();
59
    /**
60
     *  Starts next player turn.
61
     *  If game isn't over yet, then this function does the following:
62 63 64 65 66 67 68 69
     *  - if it is computer turn and computer can move, it'll make that move.
     *  - if it is computer turn and computer can't move it'll emit "computerCantMove"
     *  signal and exit
     *  - if it is player turn and player can move then this function 
     *  will do nothing - you can call makePlayerMove(row,col) to make player move (but see last item)
     *  - if it is player turn and player can't move it'll make a computer move
     *  - in demo mode this function will make computer play player moves,
     *  so you don't need to call makePlayerMove.
70 71
     *
     *  If game is over it'll emit gameOver()
72 73
     *  
     *  If it's still unclear how to use it please see KReversiScene for working example.
74
     *  In short: KReversiScene calls startNextTurn() at the end of each turn and makePlayerMove() 
75
     *  in mouseReleaseEvent()
76 77 78
     *
     *  @param demoMode if true then computer will decide for player turn
     */
79
    void startNextTurn(bool demoMode);
80 81 82 83 84 85 86 87 88 89 90 91 92 93
    /**
     *  This will make the player move at row, col.
     *  If that is possible of course
     *  If demoMode is true, the computer will decide on what move to take.
     *  row and col values do not matter in that case.
     */
    void makePlayerMove(int row, int col, bool demoMode);
    /**
     *  This function will make computer decide where he 
     *  wants to put his chip... and he'll put it there!
     */
    void makeComputerMove();
    /**
     *  Undoes all the computer moves and one player move
94
     *  (so after calling this function it will be player turn)
95
     *  @return number of undone moves
96
     */
97
    int undo();
98 99 100 101
    /**
     *  Sets the computer skill level. From 1 to 7
     */
    void setComputerSkill(int skill);
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
102 103 104
    /**
     *  @return whether the game is already over
     */
105
    bool isGameOver() const; // perhaps this doesn't need to be public
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
106 107 108
    /**
     *  @return whether any player move is at all possible
     */
109
    bool isAnyPlayerMovePossible() const;// perhaps this doesn't need to be public
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
110 111 112
    /**
     *  @return whether any computer move is at all possible
     */
113
    bool isAnyComputerMovePossible() const;// perhaps this doesn't need to be public
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
114 115 116
    /**
     *  @return a color of the current player
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
117
    ChipColor currentPlayer() const { return m_curPlayer; }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
118 119 120 121
    
    /**
     *  @return score (number of chips) of the player
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
122
    int playerScore( ChipColor player ) const;
123 124 125
    /**
     *  @return color of the chip at position [row, col]
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
126
    ChipColor chipColorAt( int row, int col ) const;
127 128 129 130
    /**
     *  @return if undo is possible
     */
    bool canUndo() const { return !m_undoStack.isEmpty(); }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
131
    /**
132
     *  @return a hint to current player
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
133
     */
134
    KReversiPos getHint() const;
135 136 137
    /**
     *  @return last move made
     */
138
    KReversiPos getLastMove() const;
139
    /**
140
     *  @return true, if it's computer's turn now
141
     */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
142 143 144 145 146 147
    bool isComputersTurn() const { return m_curPlayer == m_computerColor; }
    /**
     *  @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
     */
148
    PosList changedChips() const { return m_changedChips; }
149 150 151
    /**
     *  @return a list of possible moves for current player
     */
152
    PosList possibleMoves() const;
153
signals:
154
    void gameOver();
155
    void boardChanged();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
156
    void moveFinished();
157
    void computerCantMove();
158 159 160 161
    void networkError();
private slots:
    void networkData(int fd);
    void networkErrorHandler();
162
private:
163
    enum Direction { Up, Down, Right, Left, UpLeft, UpRight, DownLeft, DownRight };
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
164 165 166 167
    /**
     * This function will tell you if the move is possible.
     * That's why it was given such a name ;)
     */
168
    bool isMovePossible( const KReversiPos& move ) const; 
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
169 170 171 172 173
    /**
     *  Searches for "chunk" in direction dir for move.
     *  As my English-skills are somewhat limited, let me introduce 
     *  new terminology ;).
     *  I'll define a "chunk" of chips for color "C" as follows:
174
     *  (let "O" be the color of the opponent for color "C")
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
175 176 177
     *  CO[O]C <-- this is a chunk
     *  where [O] is one or more opponent's pieces
     */
178
    bool hasChunk( Direction dir, const KReversiPos& move) const;
179 180 181 182
    /**
     *  Performs move, i.e. marks all the chips that player wins with
     *  this move with current player color
     */
183
    void makeMove( const KReversiPos& move );
184 185 186 187
    /**
     *  Requests a move from the game server
     */
    void makeNetworkMove( int row, int col );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
188
    /**
189
     *  Sets the type of chip at (row,col)
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
190
     */
191 192 193 194 195 196 197 198 199
    void setChipColor(ChipColor type, int row, int col);
    /**
     *  The board itself
     */
    ChipColor m_cells[8][8];
    /**
     *  Score of each player
     */
    int m_score[2];
200 201 202 203 204
    /**
     *  Color of the current player
     */
    ChipColor m_curPlayer;
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
205 206 207 208
     *  The color of the human played chips
     */
    ChipColor m_playerColor;
    /**
209 210 211
     *  The color of the computer played chips
     */
    ChipColor m_computerColor;
212 213 214 215
    /**
     *  Our AI
     */
    Engine *m_engine;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
216 217 218 219 220 221 222 223 224 225
     // 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.
     // Espesially when I think that my description sucks :)
    /**
     *  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.
     */
226
    PosList m_changedChips;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
227
    /**
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
228
     *  This is an undo stack.
229 230
     *  It contains a lists of chips changed with each turn.
     *  @see m_changedChips
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
231
     */
232
    QStack<PosList> m_undoStack;
233 234 235 236 237
    /**
     *  Network connection to GGZ
     */
    KGGZMod::Module *m_mod;
    KGGZRaw *m_raw;
238 239
};
#endif