File: board.h

package info (click to toggle)
kshisen 4:18.04.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 2,264 kB
  • sloc: cpp: 2,444; xml: 114; makefile: 5; sh: 3
file content (351 lines) | stat: -rw-r--r-- 12,033 bytes parent folder | download
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/***************************************************************************
 *   KShisen - A japanese game similar to mahjongg                         *
 *   Copyright 1997  Mario Weilguni <mweilguni@sime.com>                   *
 *   Copyright 2002-2004  Dave Corrie <kde@davecorrie.com>                 *
 *   Copyright 2007  Mauricio Piacentini <mauricio@tabuleiro.com>          *
 *   Copyright 2009-2016  Frederik Schwarzer <schwarzer@kde.org>           *
 *                                                                         *
 *   This program 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 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/

// KMahjonggLib integration and SVG support for KDE 4: Mauricio Piacentini <mauricio@tabuleiro.com>

#ifndef KSHISEN_BOARD_H
#define KSHISEN_BOARD_H

// STL
#include <memory>
#include <vector>

// Qt
#include <QList>
#include <QSize>
#include <QWidget>

// KDE
#include <KRandomSequence>

// KDEGames
#include <KGameClock>
#include <KgSound>

// LibKMahjongg
#include <kmahjonggbackground.h>
#include <kmahjonggtileset.h>

// KShisen
#include "debug.h"
#include "move.h"
#include "possiblemove.h"

namespace KShisen
{
/**
 * A list of possible moves the player has to choose between
 */
using PossibleMoves = QList<PossibleMove>;

/**
 * @brief Class holding the game board and its functions.
 */
class Board : public QWidget
{
    Q_OBJECT

public:
    explicit Board(QWidget * parent = nullptr);

    /// Number of different kinds of tiles in the game.
    static int constexpr nTiles = 42;

    void paintEvent(QPaintEvent * e) Q_DECL_OVERRIDE;
    void mousePressEvent(QMouseEvent * e) Q_DECL_OVERRIDE;
    void resizeEvent(QResizeEvent * e) Q_DECL_OVERRIDE;

    void setDelay(int);
    int delay() const;

    /// Returns if undo step is available
    bool canUndo() const;
    /// Returns if redo step is available
    bool canRedo() const;
    /// Undoes one step
    void undo();
    /// Redoes one step
    void redo();

    void setSize(int x, int y);
    void resizeBoard();

    void showHint();
    bool hint_I(PossibleMoves & possibleMoves) const;

#ifdef DEBUGGING
    void makeHintMove();
    void finish();
    void dumpBoard() const;
    void dumpBoard(const std::vector<int> & field) const;
#endif

    /// Returns the number of tiles left on the board
    int tilesLeft() const;
    /// Returns the current game time in seconds
    int currentTime() const;

    /// Returns whether the current game is solvable
    bool isSolvable(bool restore); // const?

    bool solvableFlag() const;
    void setSolvableFlag(bool enabled);
    bool gravityFlag() const;
    void setGravityFlag(bool enabled);
    void setChineseStyleFlag(bool enabled);
    void setTilesCanSlideFlag(bool enabled);

    /// Returns possible number of tiles in X direction
    int xTiles() const;
    /// Returns possible number of tiles in Y direction
    int yTiles() const;
    /// Returns overall possible number of tiles in current game board size
    int tiles() const;

    /// Resets the game timer
    void resetTimer();
    /// Resets the undo history
    void resetUndo();
    /// Resets the redo history
    void resetRedo();
    /// Sets whether there are no matching tiles left
    void setGameStuckEnabled(bool enabled);
    /// Sets whether the game is over
    void setGameOverEnabled(bool enabled);
    /// Sets whether the game is in cheat mode
    void setCheatModeEnabled(bool enabled);

    /** Returns whether the game is over.
     * @return True if game is over, False if game is not over
     */
    bool isOver() const;

    /** Returns whether the game is in pause mode.
     * @return True if game is paused, False if game is not paused
     */
    bool isPaused() const;

    /** Returns whether there are still matching tiles left.
     * @return True if there are no matching tiles left, False if there are matching tiles left
     */
    bool isStuck() const;

    /** Returns whether player is in cheat mode.
    * @return True if the player is in cheat mode, False if not
    */
    bool hasCheated() const;

signals:
    void markMatched(); // unused?
    void newGameStarted();
    void changed();
    void tileCountChanged();
    void endOfGame();
    void resized();
    void invalidMove();
    void tilesDoNotMatch();
    void selectATile();
    void selectAMove();
    void selectAMatchingTile();
    void cheatStatusChanged();

public slots:
    /** Does most of the newGame work.
     * This slot is called from the KShisen::invokeNewGame() signal from KShisen and
     * should call KShisen::newGame again to do the work that cannot be done
     * from Board.
     */
    void newGame();

    /// Controls the pause mode
    void setPauseEnabled(bool enabled);

    /** Enables / disables sounds.
     * @param enabled Whether sound shall be enabled
     */
    void setSoundsEnabled(bool enabled);
    /// Loads the game settings
    void loadSettings();
    /// Loads the given tileset
    bool loadTileset(QString const & pathToTileset);
    /// Loads the given background
    bool loadBackground(QString const & pathToBackground);

private slots:
    void undrawConnection();

protected:
    QSize sizeHint() const Q_DECL_OVERRIDE;

private: // functions
    /** Calculates the board's offset.
     * The board is centred inside the main playing area. xOffset()/yOffset()
     * provide the coordinates of the top-left corner of the board.
     */
    int xOffset() const;
    int yOffset() const;

    /** Returns the line width to use.
     * The line width should be relative to the tile size, however, if the tile size is too small, keep a minimum line width.
     */
    int lineWidth() const;

    /** Puts a tile of type @p value to the given position @p tilePos.
     * @param tilePos Position to be modified.
     * @param value Type of the tile to place.
     */
    void setField(TilePos const & tilePos, int value);
    /** Returns the kind of tile residing at the given position @p tilePos
     * @param TilePos Position to look at.
     * @return Type of the tile.
     */
    int field(TilePos const & tilePos) const;
    /** Repaints the area of the given @p TilePos.
     * @param TilePos Position of the tile to repaint.
     */
    void repaintTile(TilePos const & tilePos);
    void showInfoRect(QPainter &, const QString & message);
    void drawTiles(QPainter &, QPaintEvent *);
    void clearHighlight();

    /** Checks if two tiles can match.
     * This is used for connecting them and for highlighting tiles of the same group.
     * @param tile1 type of the first tile
     * @param tile2 type of the second tile
     */
    bool tilesMatch(int tile1, int tile2) const;

    /** Checks if a path between two tiles can be made with a single line.
     * @param tilePos1 coordinates of the first tile
     * @param tilePos2 coordinates of the second tile
     */
    bool canMakePath(TilePos const & tilePos1, TilePos const & tilePos2) const;

    /** Checks if the tile at \p tilePos1 can be slid to \p tilePos2.
     * @param tilePos1 coordinates of the slide's initial position
     * @param tilePos2 coordinates of the slide's final position
     * @param slide The movement of the last tile slid will be stored in @p slide
     */
    bool canSlideTiles(TilePos const & tilePos1, TilePos const & tilePos2, Slide & slide) const;

    /** Checks if a path between two tiles can be made with 2 or 3 lines.
    * @param tilePos1 coordinates of the first tile
    * @param tilePos2 coordinates of the second tile
    * @param possibleMoves All the possible moves are stored here
    * @return The number of paths found
    */
    int findPath(TilePos const & tilePos1, TilePos const & tilePos2, PossibleMoves & possibleMoves) const;

    /** Find a path of 1 or 2 segments between tiles.
     * @param tilePos1 coordinates of the first tile
     * @param tilePos2 coordinates of the second tile
     * @param possibleMoves all the possible moves are stored here
     * @return The number of paths found
     */
    int findSimplePath(TilePos const & tilePos1, TilePos const & tilePos2, PossibleMoves & possibleMoves) const;
    void performMove(PossibleMove & possibleMoves);
    void performSlide(TilePos const & tilePos, Slide const & slide);
    void reverseSlide(TilePos const & tilePos, Slide const & slide);
    bool isTileHighlighted(TilePos const & tilePos) const;
    void drawConnection();
    void drawPossibleMoves(bool b);
    /** Calculated the middle coordinates of the given tile position.
     * @param tilePos tile position
     * @return The middle coordinates of the tile at \p tilePos
     */
    QPoint midCoord(TilePos const & tilePos) const;
    void unmarkTile();
    void marked(TilePos const & tilePos);
    void madeMove(TilePos const & tilePos1, TilePos const & tilePos2, Slide slide = Slide());

    /// Applies gravity to all columns.
    void applyGravity();

    /** Returns True if @p tilePos is a valid position on Board.
     * @return Whether @p tiePos is valid.
     */
    bool isValidPos(TilePos const & tilePos) const;

    /** Returns True if @p tilePos is a valid position on Board including outline.
     * @return Whether @p tiePos is valid.
     */
    bool isValidPosWithOutline(TilePos const & tilePos) const;

    /** Returns True if @p tile is of kind FLOWERS.
     * @return Whether @p tile is within the range of the Flower tiles.
     */
    bool isTileFlower(int tile) const;
    /** Returns True if @p tile is of kind SEASONS.
     * @return Whether @p tile is within the range of the Seasons tiles.
     */
    bool isTileSeason(int tile) const;

private:
    KGameClock m_gameClock;

    KMahjonggTileset m_tiles;
    KMahjonggBackground m_background;

    KRandomSequence m_random;

    std::list<std::unique_ptr<Move>> m_undo; ///< Undo history
    std::list<std::unique_ptr<Move>> m_redo; ///< Redo history

    int m_markX;
    int m_markY;
    Path m_connection;
    PossibleMoves m_possibleMoves;
    std::vector<int> m_field; ///< Matrix holding the game board grid
    int m_xTiles;
    int m_yTiles;
    int m_delay;
    int m_level;
    int m_shuffle;

    // The game can be in one of the following states.
    enum class GameState { Normal,
                           Paused,
                           Stuck,
                           Over };
    GameState m_gameState;
    bool m_cheat; ///< Whether the cheat mode is set

    bool m_gravityFlag; ///< Whether game is played with gravity
    bool m_solvableFlag; ///< Whether game is solvable
    bool m_chineseStyleFlag; ///< Whether game follows Chinese rules
    bool m_tilesCanSlideFlag; ///< Whether tiles can slide when connecting

    int m_highlightedTile;

    bool m_paintConnection;
    bool m_paintPossibleMoves;
    bool m_paintInProgress;
    TilePos m_tileRemove1;
    TilePos m_tileRemove2;
    KgSound m_soundPick; ///< Sound object to play when tile is selected
    KgSound m_soundFall; ///< Sound object to play when tiles fall down in gravity mode
};
} // namespace KShisen

#endif // KSHISEN_BOARD_H

// vim: expandtab:tabstop=4:shiftwidth=4
// kate: space-indent on; indent-width 4