summaryrefslogtreecommitdiff
path: root/noncore/games/tetrix/gtetrix.cpp
Unidiff
Diffstat (limited to 'noncore/games/tetrix/gtetrix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/tetrix/gtetrix.cpp514
1 files changed, 514 insertions, 0 deletions
diff --git a/noncore/games/tetrix/gtetrix.cpp b/noncore/games/tetrix/gtetrix.cpp
new file mode 100644
index 0000000..d1f38b1
--- a/dev/null
+++ b/noncore/games/tetrix/gtetrix.cpp
@@ -0,0 +1,514 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21
22#include "gtetrix.h"
23
24#include <string.h>
25
26GenericTetrix::GenericTetrix(int boardWidth,int boardHeight)
27{
28 int i,j;
29
30 width = boardWidth;
31 height = boardHeight;
32 boardPtr = new int[height*width]; // Note the order, this makes it easier
33 // to remove full lines.
34 for(i = 0 ; i < height ; i++)
35 for(j = 0 ; j < width ; j++)
36 board(j,i) = 0;
37 currentLine = -1; // -1 if no falling piece.
38 currentPos = 0;
39 showNext = 0; // FALSE
40 nLinesRemoved = 0;
41 nPiecesDropped = 0;
42 score = 0;
43 level = 1;
44 gameID = 0;
45 nClearLines = height;
46}
47
48GenericTetrix::~GenericTetrix()
49{
50 delete[] boardPtr;
51}
52
53
54void GenericTetrix::clearBoard(int fillRandomLines)
55{
56 int i,j;
57
58 if (fillRandomLines >= height)
59 fillRandomLines = height - 1;
60
61 erasePiece();
62 for(i = height - nClearLines - 1 ; i >= fillRandomLines ; i--)
63 for(j = 0 ; j < width ; j++)
64 if (board(j,i) != 0) {
65 draw(j,i,0);
66 board(j,i) = 0;
67 }
68 if (fillRandomLines != 0)
69 for (i = 0 ; i < fillRandomLines ; i++) {
70 fillRandom(i);
71 }
72 nClearLines = height - fillRandomLines;
73}
74
75void GenericTetrix::showBoard()
76{
77 int i,j;
78
79 showPiece();
80 for(i = height - nClearLines - 1 ; i >= 0 ; i--)
81 for(j = 0 ; j < width ; j++)
82 if (board(j,i) != 0)
83 draw(j,i,board(j,i));
84}
85
86void GenericTetrix::hideBoard()
87{
88 int i,j;
89
90 erasePiece();
91 for(i = height - nClearLines - 1 ; i >= 0 ; i--)
92 for(j = 0 ; j < width ; j++)
93 if (board(j,i) != 0)
94 draw(j,i,0);
95}
96
97void GenericTetrix::startGame(int gameType,int fillRandomLines)
98{
99 gameID = gameType;
100 clearBoard(fillRandomLines);
101 nLinesRemoved = 0;
102 updateRemoved(nLinesRemoved);
103 nClearLines = height;
104 nPiecesDropped = 0;
105 score = 0;
106 updateScore(score);
107 level = 1;
108 updateLevel(level);
109 newPiece();
110}
111
112void GenericTetrix::revealNextPiece(int revealIt)
113{
114 if (showNext == revealIt)
115 return;
116 showNext = revealIt;
117 if (!showNext)
118 eraseNextPiece();
119 else
120 showNextPiece();
121}
122
123void GenericTetrix::updateBoard(int x1,int y1,int x2, int y2,
124 int dontUpdateBlanks)
125{
126 int i,j;
127 int tmp;
128
129 if (x1 > x2) {
130 tmp = x2;
131 x2 = x1;
132 x1 = tmp;
133 }
134 if (y1 > y2) {
135 tmp = y2;
136 y2 = y1;
137 y1 = tmp;
138 }
139 if (x1 < 0)
140 x1 = 0;
141 if (x2 >= width)
142 x2 = width - 1;
143 if (y1 < 0)
144 y1 = 0;
145 if (y2 >= height)
146 y2 = height - 1;
147 for(i = y1 ; i <= y2 ; i++)
148 for(j = x1 ; j <= x2 ; j++)
149 if (!dontUpdateBlanks || board(j,height - i - 1) != 0)
150 draw(j,height - i - 1,board(j,height - i - 1));
151 showPiece(); // Remember to update piece correctly!!!!
152}
153
154
155void GenericTetrix::fillRandom(int line)
156{
157 int i,j;
158 int holes;
159
160 for(i = 0 ; i < width ; i++)
161 board(i,line) = TetrixPiece::randomValue(7);
162 holes = 0;
163 for(i = 0 ; i < width ; i++)
164 if (board(i,line) == 0) // Count holes in the line.
165 holes++;
166 if (holes == 0) // Full line, make a random hole:
167 board(TetrixPiece::randomValue(width),line) = 0;
168 if (holes == width) // Empty line, make a random square:
169 board(TetrixPiece::randomValue(width),line) =
170 TetrixPiece::randomValue(6) + 1;
171 for(j = 0 ; j < width ; j++)
172 draw(j,i,board(j,i));
173}
174
175void GenericTetrix::moveLeft(int steps)
176{
177 while(steps) {
178 if (!canMoveTo(currentPos - 1,currentLine))
179 return;
180 moveTo(currentPos - 1,currentLine);
181 steps--;
182 }
183}
184
185void GenericTetrix::moveRight(int steps)
186{
187 while(steps) {
188 if (!canMoveTo(currentPos + 1,currentLine))
189 return;
190 moveTo(currentPos + 1,currentLine);
191 steps--;
192 }
193}
194
195void GenericTetrix::rotateLeft()
196{
197 TetrixPiece tmp(currentPiece);
198
199 tmp.rotateLeft();
200 if (!canPosition(tmp))
201 return;
202 position(tmp);
203 currentPiece = tmp;
204}
205
206void GenericTetrix::rotateRight()
207{
208 TetrixPiece tmp(currentPiece);
209
210 tmp.rotateRight();
211 if (!canPosition(tmp))
212 return;
213 position(tmp);
214 currentPiece = tmp;
215}
216
217void GenericTetrix::dropDown()
218{
219 if (currentLine == -1)
220 return;
221
222 int dropHeight = 0;
223 int newLine = currentLine;
224 while(newLine) {
225 if (!canMoveTo(currentPos,newLine - 1))
226 break;
227 newLine--;
228 dropHeight++;
229 }
230 if (dropHeight != 0)
231 moveTo(currentPos,newLine);
232 internalPieceDropped(dropHeight);
233}
234
235void GenericTetrix::oneLineDown()
236{
237 if (currentLine == -1)
238 return;
239 if (canMoveTo(currentPos,currentLine - 1)) {
240 moveTo(currentPos,currentLine - 1);
241 } else {
242 internalPieceDropped(0);
243 }
244}
245
246void GenericTetrix::newPiece()
247{
248 currentPiece = nextPiece;
249 if (showNext)
250 eraseNextPiece();
251 nextPiece.setRandomType();
252 if (showNext)
253 showNextPiece();
254 currentLine = height - 1 + currentPiece.getMinY();
255 currentPos = width/2 + 1;
256 if (!canMoveTo(currentPos,currentLine)) {
257 currentLine = -1;
258 gameOver();
259 } else {
260 showPiece();
261 }
262}
263
264void GenericTetrix::removePiece()
265{
266 erasePiece();
267 currentLine = -1;
268}
269
270void GenericTetrix::drawNextSquare(int,int,int)
271{
272
273}
274
275void GenericTetrix::pieceDropped(int)
276{
277 newPiece();
278}
279
280void GenericTetrix::updateRemoved(int)
281{
282}
283
284void GenericTetrix::updateScore(int)
285{
286}
287
288void GenericTetrix::updateLevel(int)
289{
290}
291
292void GenericTetrix::removeFullLines()
293{
294 int i,j,k;
295 int nFullLines;
296
297 for(i = 0 ; i < height - nClearLines ; i++) {
298 for(j = 0 ; j < width ; j++)
299 if (board(j,i) == 0)
300 break;
301 if (j == width) {
302 nFullLines = 1;
303 for(k = i + 1 ; k < height - nClearLines ; k++) {
304 for(j = 0 ; j < width ; j++)
305 if (board(j,k) == 0)
306 break;
307 if (j == width) {
308 nFullLines++;
309 } else {
310 for(j = 0 ; j < width ; j++) {
311 if (board(j,k - nFullLines) != board(j,k)) {
312 board(j,k - nFullLines) = board(j,k);
313 draw( j,k - nFullLines,
314 board(j,k - nFullLines));
315 }
316 }
317 }
318 }
319 nClearLines = nClearLines + nFullLines;
320 nLinesRemoved = nLinesRemoved + nFullLines;
321 updateRemoved(nLinesRemoved);
322 score = score + 10*nFullLines; // updateScore must be
323 // called by caller!
324 for (i = height - nClearLines ;
325 i < height - nClearLines + nFullLines ;
326 i++)
327 for(j = 0 ; j < width ; j++)
328 if (board(j,i) != 0) {
329 draw(j,i,0);
330 board(j,i) = 0;
331 }
332 }
333 }
334}
335
336void GenericTetrix::showPiece()
337{
338 int x,y;
339
340 if (currentLine == -1)
341 return;
342
343 for(int i = 0 ; i < 4 ; i++) {
344 currentPiece.getCoord(i,x,y);
345 draw(currentPos + x,currentLine - y,currentPiece.getType());
346 }
347}
348
349void GenericTetrix::erasePiece()
350{
351 int x,y;
352
353 if (currentLine == -1)
354 return;
355
356 for(int i = 0 ; i < 4 ; i++) {
357 currentPiece.getCoord(i,x,y);
358 draw(currentPos + x,currentLine - y,0);
359 }
360}
361
362void GenericTetrix::internalPieceDropped(int dropHeight)
363{
364 gluePiece();
365 nPiecesDropped++;
366 if (nPiecesDropped % 25 == 0) {
367 level++;
368 updateLevel(level);
369 }
370 score = score + 7 + dropHeight;
371 removeFullLines();
372 updateScore(score);
373 pieceDropped(dropHeight);
374}
375
376void GenericTetrix::gluePiece()
377{
378 int x,y;
379 int min;
380
381 if (currentLine == -1)
382 return;
383
384 for(int i = 0 ; i < 4 ; i++) {
385 currentPiece.getCoord(i,x,y);
386 board(currentPos + x,currentLine - y) = currentPiece.getType();
387 }
388 min = currentPiece.getMinY();
389 if (currentLine - min >= height - nClearLines)
390 nClearLines = height - currentLine + min - 1;
391}
392
393void GenericTetrix::showNextPiece(int erase)
394{
395 int x,y;
396 int minX = nextPiece.getMinX();
397 int minY = nextPiece.getMinY();
398 int maxX = nextPiece.getMaxX();
399 int maxY = nextPiece.getMaxY();
400
401 int xOffset = (3 - (maxX - minX))/2;
402 int yOffset = (3 - (maxY - minY))/2;
403
404 for(int i = 0 ; i < 4 ; i++) {
405 nextPiece.getCoord(i,x,y);
406 if (erase)
407 drawNextSquare(x + xOffset - minX,
408 y + yOffset - minY,0);
409 else
410 drawNextSquare(x + xOffset - minX,
411 y + yOffset - minY,nextPiece.getType());
412 }
413}
414
415int GenericTetrix::canPosition(TetrixPiece &piece)
416{
417 if (currentLine == -1)
418 return 0;
419
420 int x,y;
421
422 for(int i = 0 ; i < 4 ; i++) {
423 piece.getCoord(i,x,y);
424 x = currentPos + x;
425 y = currentLine - y; // Board and pieces have inverted y-coord. systems.
426 if (x < 0 || x >= width || y < 0 || y >= height)
427 return 0; // Outside board, cannot put piece here.
428 if (board(x,y) != 0)
429 return 0; // Over a non-zero square, cannot put piece here.
430 }
431 return 1; // Inside board and no non-zero squares underneath.
432
433}
434
435int GenericTetrix::canMoveTo(int xPosition,int line)
436{
437 if (currentLine == -1)
438 return 0;
439
440 int x,y;
441
442 for(int i = 0 ; i < 4 ; i++) {
443 currentPiece.getCoord(i,x,y);
444 x = xPosition + x;
445 y = line - y; // Board and pieces have inverted y-coord. systems.
446 if (x < 0 || x >= width || y < 0 || y >= height)
447 return 0; // Outside board, cannot put piece here.
448 if (board(x,y) != 0)
449 return 0; // Over a non-zero square, cannot put piece here.
450 }
451 return 1; // Inside board and no non-zero squares underneath.
452}
453
454void GenericTetrix::moveTo(int xPosition,int line)
455{
456 if (currentLine == -1)
457 return;
458 optimizedMove(xPosition,line,currentPiece);
459 currentPos = xPosition;
460 currentLine = line;
461}
462
463void GenericTetrix::position(TetrixPiece &piece)
464{
465 if (currentLine == -1)
466 return;
467
468 optimizedMove(currentPos,currentLine,piece);
469}
470
471void GenericTetrix::optimizedMove(int newPos, int newLine,
472 TetrixPiece &newPiece)
473{
474 int updates [8][3];
475 int nUpdates;
476 int value;
477 int x,y;
478 int i,j;
479
480 for(i = 0 ; i < 4 ; i++) { // Put the erasing coords into updates
481 currentPiece.getCoord(i,x,y);
482 updates[i][0] = currentPos + x;
483 updates[i][1] = currentLine - y;
484 updates[i][2] = 0;
485 }
486 nUpdates = 4;
487 for(i = 0 ; i < 4 ; i++) { // Any drawing coord same as an erasing one?
488 newPiece.getCoord(i,x,y);
489 x = newPos + x;
490 y = newLine - y;
491 for (j = 0 ; j < 4 ; j++)
492 if (updates[j][0] == x && updates[j][1] == y) { // Same coord,
493 // don't have to erase
494 if (currentPiece.getType() == newPiece.getType())
495 updates[j][2] = -1; // Correct on screen, no update!
496 else
497 updates[j][2] = newPiece.getType();
498 break;
499 }
500 if (j == 4) { // This coord does not overlap an erasing one
501 updates[nUpdates][0] = x;
502 updates[nUpdates][1] = y;
503 updates[nUpdates][2] = newPiece.getType();
504 nUpdates++;
505 }
506 }
507 for (i = 0 ; i < nUpdates ; i++) { // Do the updating
508 x = updates[i][0];
509 y = updates[i][1];
510 value = updates[i][2];
511 if (value != -1) // Only update if new value != current
512 draw(x,y,value);
513 }
514}