Bumping version number.
[evilplumber] / src / game.h
1 /* Evil Plumber is a small puzzle game.
2    Copyright (C) 2010 Marja Hassinen
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifndef GAME__H
19 #define GAME__H
20
21 #include <QObject>
22 #include <QHash>
23 #include <QTimer>
24 #include <QStringList>
25
26 class QTableWidget;
27 class QTableWidgetItem;
28 class QLabel;
29 class QWidget;
30 class QPushButton;
31 class QListWidget;
32
33 enum PieceType
34 {
35     PieceNone = 0,
36     PieceStraight,
37     PieceCorner,
38     PieceCross,
39     PieceCorners,
40     PieceStart,
41     PieceEnd,
42     PieceBlock,
43     PiecesEnd
44 };
45
46 enum Direction
47 {
48     DirNone = 0,
49     DirLeft,
50     DirUp,
51     DirRight,
52     DirDown,
53     DirDone,
54     DirFailed,
55     DirPassed
56 };
57
58 typedef struct Piece
59 {
60     PieceType type;
61     int rotation;
62     bool userCanAdd;
63     int uiRow;
64     int uiColumn;
65     Direction flows[4];
66 } Piece;
67
68 static const Piece ppieces[] = {
69     {PieceNone, 0, false, 0, 0,              // 0 
70      {DirNone, DirNone, DirNone, DirNone}},
71     {PieceStraight, 0, true, 0, 0,           // 1
72      {DirUp, DirDown, DirNone, DirNone}},
73     {PieceStraight, 90, true, 0, 1,          // 2
74      {DirLeft, DirRight, DirNone, DirNone}},
75     {PieceCorner, 270, true, 1, 0,           // 3
76      {DirDown, DirRight, DirNone, DirNone}},
77     {PieceCorner, 0, true, 1, 1,             // 4
78      {DirLeft, DirDown, DirNone, DirNone}},
79     {PieceCorner, 180, true, 2, 0,           // 5
80      {DirUp, DirRight, DirNone, DirNone}},
81     {PieceCorner, 90, true, 2, 1,            // 6
82      {DirLeft, DirUp, DirNone, DirNone}},
83     {PieceCross, 0, true, 3, 0,              // 7
84      {DirLeft, DirRight, DirUp, DirDown}},
85     {PieceCorners, 0, true, 4, 0,            // 8
86      {DirLeft, DirDown, DirRight, DirUp}},
87     {PieceCorners, 90, true, 4, 1,          // 9
88      {DirRight, DirDown, DirLeft, DirUp}},
89     {PieceStart, 0, false, 0, 0,             // 10
90      {DirLeft, DirNone, DirNone, DirNone}},
91     {PieceStart, 90, false, 0, 0,            // 11
92      {DirUp, DirNone, DirNone, DirNone}},
93     {PieceStart, 180, false, 0, 0,           // 12
94      {DirRight, DirNone, DirNone, DirNone}},
95     {PieceStart, 270, false, 0, 0,           // 13
96      {DirDown, DirNone, DirNone, DirNone}},
97     {PieceEnd, 0, false, 0, 0,               // 14
98      {DirLeft, DirDone, DirNone, DirNone}},
99     {PieceEnd, 90, false, 0, 0,              // 15
100      {DirUp, DirDone, DirNone, DirNone}},
101     {PieceEnd, 180, false, 0, 0,             // 16
102      {DirRight, DirDone, DirNone, DirNone}},
103     {PieceEnd, 270, false, 0, 0,             // 17
104      {DirDown, DirDone, DirNone, DirNone}},
105     {PieceBlock, 0, false, 0, 0,             // 18
106      {DirNone, DirNone, DirNone, DirNone}},
107     {PiecesEnd, 0, false, 0, 0,              // 19
108      {DirNone, DirNone, DirNone, DirNone}}};
109
110 const int noPieces = 20;
111
112 typedef struct _PlacedPiece
113 {
114     const Piece* piece;
115     bool fixed;
116     bool flow[2]; // which directions the liquid has already flown
117 } PlacedPiece;
118
119 typedef struct _PrePlacedPiece
120 {
121     const Piece* piece;
122     int row;
123     int col;
124 } PrePlacedPiece;
125
126 typedef struct _AvailablePiece
127 {
128     const Piece* piece;
129     int count;
130 } AvailablePiece;
131
132 class GameField : public QObject
133 {
134     Q_OBJECT
135 public:
136     GameField(QTableWidget* ui);
137     void initGame(int rows_, int cols_, int count, PrePlacedPiece* prePlaced);
138
139     bool setPiece(int row, int col, const Piece* piece, bool fixed = false);
140     const Piece* pieceAt(int row, int col);
141     bool isPrePlaced(int row, int col);
142     void indicateFlow(int row, int col, Direction dir);
143
144 signals:
145     void cellClicked(int, int);
146
147 private:
148     int toIndex(int row, int col);
149
150     QTableWidget* fieldUi;
151     PlacedPiece* field;
152     int rows;
153     int cols;
154 };
155
156 class AvailablePieces : public QObject
157 {
158     Q_OBJECT
159 public:
160     AvailablePieces(QTableWidget* pieceTable);
161     void initGame(int count, AvailablePiece* pieces);
162
163 signals:
164     void validPieceSelected(const Piece* piece);
165     void invalidPieceSelected();
166
167 public slots:
168     void onPieceUsed(const Piece* piece);
169
170 private slots:
171     void onItemClicked(QTableWidgetItem* item);
172
173 private:
174     static int pieceToId(const Piece* piece);
175     static const Piece* idToPiece(int id);
176
177     QTableWidget* pieceUi;
178     QHash<const Piece*, int> pieceCounts;
179 };
180
181 class GameController : public QObject
182 {
183     Q_OBJECT
184 public:
185     GameController(AvailablePieces* pieceUi, GameField* fieldUi, 
186                    QLabel* timeLabel, QPushButton* doneButton);
187     void startLevel(QString fileName);
188
189 signals:
190     void pieceUsed(const Piece* piece);
191     void levelPassed(int score);
192     void levelFailed();
193
194 private slots:
195     void onDoneClicked();
196     void onCellClicked(int row, int column);
197     void onValidPieceSelected(const Piece* piece);
198     void onInvalidPieceSelected();
199     void onTimeout();
200     void computeFlow();
201
202 private:
203     void levelEnds();
204
205     AvailablePieces* pieceUi; // Not owned
206     GameField* fieldUi; // Not owned
207     QLabel* timeLabel; // Not owned
208     QPushButton* doneButton; // Not owned
209
210     // Data about the current situation in the game
211     const Piece* currentPiece;
212     int rows, cols;
213     QTimer timer;
214     QTimer flowTimer;
215     int timeLeft;
216     bool levelRunning;
217     // how many times does the liquid need to flow through the pre-placed pieces
218     int neededFlow;
219     int startRow;
220     int startCol;
221     Direction startDir;
222     int flowRow;
223     int flowCol;
224     Direction flowDir;
225     int flowPreplaced;
226     int flowScore;
227     bool animate;
228 };
229
230 class LevelSwitcher : public QObject
231 {
232     Q_OBJECT
233 public:
234     LevelSwitcher(GameController* gameController,
235                   QWidget* levelWidget, QListWidget* levelList, QPushButton* levelStartButton,
236                   QWidget* startWidget, QLabel* startTitle, QLabel* startLabel, QPushButton* startButton,
237                   QWidget* gameWidget, QLabel* levelLabel, QLabel* scoreLabel,
238                   QStringList levels);
239
240 private slots:
241     void onLevelCollectionChosen();
242     void onStartClicked();
243     void onLevelPassed(int score);
244     void onLevelFailed();
245     void chooseLevelCollection();
246
247 private:
248     void initiateLevel();
249     void readSavedGames();
250     void writeSavedGames();
251     void readLevelCollections(QStringList collections);
252
253     GameController* gameController; // Not owned
254     QWidget* levelWidget; // Not owned
255     QListWidget* levelList; // Not owned
256     QPushButton* levelStartButton; // Not owned
257     QWidget* startWidget; // Not owned
258     QLabel* startTitle; // Not owned
259     QLabel* startLabel; // Not owned
260     QPushButton* startButton; // Not owned
261     QWidget* gameWidget; // Not owned
262     QLabel* levelLabel; // Not owned
263     QLabel* scoreLabel; // Not owned
264
265     QString curColl;
266     QStringList levels;
267     int level;
268     int totalScore;
269     QHash<QString, int> savedGames; // level collection -> next level ix
270     QHash<QString, QStringList> levelCollections; // level collection -> level names
271 };
272
273 #endif