~ubuntu-branches/ubuntu/precise/kdegames/precise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*******************************************************************
 *
 * 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.
 *
 ********************************************************************/
#ifndef KREVERSI_GAME_H
#define KREVERSI_GAME_H

#include <QObject>
#include <QStack>

#include "commondefs.h"

class Engine;

namespace KGGZMod
{
    class Module;
}

class KGGZRaw;

/**
 *  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
 *
 *  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:
 *  startNextTurn() and  makePlayerMove()
 *
 *  See KReversiScene for example of working with KReversiGame
 */
class KReversiGame : public QObject
{
    Q_OBJECT
public:
    KReversiGame();
    ~KReversiGame();
    /**
     *  Starts next player turn.
     *  If game isn't over yet, then this function does the following:
     *  - 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.
     *
     *  If game is over it'll emit gameOver()
     *
     *  If it's still unclear how to use it please see KReversiScene for working example.
     *  In short: KReversiScene calls startNextTurn() at the end of each turn and makePlayerMove()
     *  in mouseReleaseEvent()
     *
     *  @param demoMode if true then computer will decide for player turn
     */
    void startNextTurn(bool demoMode);
    /**
     *  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
     *  (so after calling this function it will be player turn)
     *  @return number of undone moves
     */
    int undo();
    /**
     *  Sets the computer skill level. From 1 to 7
     */
    void setComputerSkill(int skill);
    /**
     * @return whether the game is currently computing turn
     */
    bool isThinking() const;
    /**
     *  @return whether the game is already over
     */
    bool isGameOver() const; // perhaps this doesn't need to be public
    /**
     *  @return whether any player move is at all possible
     */
    bool isAnyPlayerMovePossible() const;// perhaps this doesn't need to be public
    /**
     *  @return whether any computer move is at all possible
     */
    bool isAnyComputerMovePossible() const;// perhaps this doesn't need to be public
    /**
     *  @return a color of the current player
     */
    ChipColor currentPlayer() const { return m_curPlayer; }

    /**
     *  @return score (number of chips) of the player
     */
    int playerScore( ChipColor player ) const;
    /**
     *  @return color of the chip at position [row, col]
     */
    ChipColor chipColorAt( int row, int col ) const;
    /**
     *  @return if undo is possible
     */
    bool canUndo() const { return !m_undoStack.isEmpty(); }
    /**
     *  @return a hint to current player
     */
    KReversiPos getHint() const;
    /**
     *  @return last move made
     */
    KReversiPos getLastMove() const;
    /**
     *  @return true, if it's computer's turn now
     */
    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
     */
    PosList changedChips() const { return m_changedChips; }
    /**
     *  @return a list of possible moves for current player
     */
    PosList possibleMoves() const;
signals:
    void gameOver();
    void boardChanged();
    void moveFinished();
    void computerCantMove();
    void playerCantMove();
    void networkError();
private slots:
    void networkData(int fd);
    void networkErrorHandler();
private:
    enum Direction { Up, Down, Right, Left, UpLeft, UpRight, DownLeft, DownRight };
    /**
     * This function will tell you if the move is possible.
     * That's why it was given such a name ;)
     */
    bool isMovePossible( const KReversiPos& move ) const;
    /**
     *  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:
     *  (let "O" be the color of the opponent for color "C")
     *  CO[O]C <-- this is a chunk
     *  where [O] is one or more opponent's pieces
     */
    bool hasChunk( Direction dir, const KReversiPos& move) const;
    /**
     *  Performs move, i.e. marks all the chips that player wins with
     *  this move with current player color
     */
    void makeMove( const KReversiPos& move );
    /**
     *  Requests a move from the game server
     */
    void makeNetworkMove( int row, int col );
    /**
     *  Sets the type of chip at (row,col)
     */
    void setChipColor(ChipColor type, int row, int col);
    /**
     *  The board itself
     */
    ChipColor m_cells[8][8];
    /**
     *  Score of each player
     */
    int m_score[2];
    /**
     *  Color of the current player
     */
    ChipColor m_curPlayer;
    /**
     *  The color of the human played chips
     */
    ChipColor m_playerColor;
    /**
     *  The color of the computer played chips
     */
    ChipColor m_computerColor;
    /**
     *  Our AI
     */
    Engine *m_engine;
     // 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 :)
    /**
     *  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.
     */
    PosList m_changedChips;
    /**
     *  This is an undo stack.
     *  It contains a lists of chips changed with each turn.
     *  @see m_changedChips
     */
    QStack<PosList> m_undoStack;
    /**
     *  Network connection to GGZ
     */
    KGGZMod::Module *m_mod;
    KGGZRaw *m_raw;
};
#endif