00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "gtetrix.h"
00023
00024 #include <string.h>
00025
00026 GenericTetrix::GenericTetrix(int boardWidth,int boardHeight)
00027 {
00028 int i,j;
00029
00030 width = boardWidth;
00031 height = boardHeight;
00032 boardPtr = new int[height*width];
00033
00034 for(i = 0 ; i < height ; i++)
00035 for(j = 0 ; j < width ; j++)
00036 board(j,i) = 0;
00037 currentLine = -1;
00038 currentPos = 0;
00039 showNext = 0;
00040 nLinesRemoved = 0;
00041 nPiecesDropped = 0;
00042 score = 0;
00043 level = 1;
00044 gameID = 0;
00045 nClearLines = height;
00046 }
00047
00048 GenericTetrix::~GenericTetrix()
00049 {
00050 delete[] boardPtr;
00051 }
00052
00053
00054 void GenericTetrix::clearBoard(int fillRandomLines)
00055 {
00056 int i,j;
00057
00058 if (fillRandomLines >= height)
00059 fillRandomLines = height - 1;
00060
00061 erasePiece();
00062 for(i = height - nClearLines - 1 ; i >= fillRandomLines ; i--)
00063 for(j = 0 ; j < width ; j++)
00064 if (board(j,i) != 0) {
00065 draw(j,i,0);
00066 board(j,i) = 0;
00067 }
00068 if (fillRandomLines != 0)
00069 for (i = 0 ; i < fillRandomLines ; i++) {
00070 fillRandom(i);
00071 }
00072 nClearLines = height - fillRandomLines;
00073 }
00074
00075 void GenericTetrix::showBoard()
00076 {
00077 int i,j;
00078
00079 showPiece();
00080 for(i = height - nClearLines - 1 ; i >= 0 ; i--)
00081 for(j = 0 ; j < width ; j++)
00082 if (board(j,i) != 0)
00083 draw(j,i,board(j,i));
00084 }
00085
00086 void GenericTetrix::hideBoard()
00087 {
00088 int i,j;
00089
00090 erasePiece();
00091 for(i = height - nClearLines - 1 ; i >= 0 ; i--)
00092 for(j = 0 ; j < width ; j++)
00093 if (board(j,i) != 0)
00094 draw(j,i,0);
00095 }
00096
00097 void GenericTetrix::startGame(int gameType,int fillRandomLines)
00098 {
00099 gameID = gameType;
00100 clearBoard(fillRandomLines);
00101 nLinesRemoved = 0;
00102 updateRemoved(nLinesRemoved);
00103 nClearLines = height;
00104 nPiecesDropped = 0;
00105 score = 0;
00106 updateScore(score);
00107 level = 1;
00108 updateLevel(level);
00109 newPiece();
00110 }
00111
00112 void GenericTetrix::revealNextPiece(int revealIt)
00113 {
00114 if (showNext == revealIt)
00115 return;
00116 showNext = revealIt;
00117 if (!showNext)
00118 eraseNextPiece();
00119 else
00120 showNextPiece();
00121 }
00122
00123 void GenericTetrix::updateBoard(int x1,int y1,int x2, int y2,
00124 int dontUpdateBlanks)
00125 {
00126 int i,j;
00127 int tmp;
00128
00129 if (x1 > x2) {
00130 tmp = x2;
00131 x2 = x1;
00132 x1 = tmp;
00133 }
00134 if (y1 > y2) {
00135 tmp = y2;
00136 y2 = y1;
00137 y1 = tmp;
00138 }
00139 if (x1 < 0)
00140 x1 = 0;
00141 if (x2 >= width)
00142 x2 = width - 1;
00143 if (y1 < 0)
00144 y1 = 0;
00145 if (y2 >= height)
00146 y2 = height - 1;
00147 for(i = y1 ; i <= y2 ; i++)
00148 for(j = x1 ; j <= x2 ; j++)
00149 if (!dontUpdateBlanks || board(j,height - i - 1) != 0)
00150 draw(j,height - i - 1,board(j,height - i - 1));
00151 showPiece();
00152 }
00153
00154
00155 void GenericTetrix::fillRandom(int line)
00156 {
00157 int i,j;
00158 int holes;
00159
00160 for(i = 0 ; i < width ; i++)
00161 board(i,line) = TetrixPiece::randomValue(7);
00162 holes = 0;
00163 for(i = 0 ; i < width ; i++)
00164 if (board(i,line) == 0)
00165 holes++;
00166 if (holes == 0)
00167 board(TetrixPiece::randomValue(width),line) = 0;
00168 if (holes == width)
00169 board(TetrixPiece::randomValue(width),line) =
00170 TetrixPiece::randomValue(6) + 1;
00171 for(j = 0 ; j < width ; j++)
00172 draw(j,i,board(j,i));
00173 }
00174
00175 void GenericTetrix::moveLeft(int steps)
00176 {
00177 while(steps) {
00178 if (!canMoveTo(currentPos - 1,currentLine))
00179 return;
00180 moveTo(currentPos - 1,currentLine);
00181 steps--;
00182 }
00183 }
00184
00185 void GenericTetrix::moveRight(int steps)
00186 {
00187 while(steps) {
00188 if (!canMoveTo(currentPos + 1,currentLine))
00189 return;
00190 moveTo(currentPos + 1,currentLine);
00191 steps--;
00192 }
00193 }
00194
00195 void GenericTetrix::rotateLeft()
00196 {
00197 TetrixPiece tmp(currentPiece);
00198
00199 tmp.rotateLeft();
00200 if (!canPosition(tmp))
00201 return;
00202 position(tmp);
00203 currentPiece = tmp;
00204 }
00205
00206 void GenericTetrix::rotateRight()
00207 {
00208 TetrixPiece tmp(currentPiece);
00209
00210 tmp.rotateRight();
00211 if (!canPosition(tmp))
00212 return;
00213 position(tmp);
00214 currentPiece = tmp;
00215 }
00216
00217 void GenericTetrix::dropDown()
00218 {
00219 if (currentLine == -1)
00220 return;
00221
00222 int dropHeight = 0;
00223 int newLine = currentLine;
00224 while(newLine) {
00225 if (!canMoveTo(currentPos,newLine - 1))
00226 break;
00227 newLine--;
00228 dropHeight++;
00229 }
00230 if (dropHeight != 0)
00231 moveTo(currentPos,newLine);
00232 internalPieceDropped(dropHeight);
00233 }
00234
00235 void GenericTetrix::oneLineDown()
00236 {
00237 if (currentLine == -1)
00238 return;
00239 if (canMoveTo(currentPos,currentLine - 1)) {
00240 moveTo(currentPos,currentLine - 1);
00241 } else {
00242 internalPieceDropped(0);
00243 }
00244 }
00245
00246 void GenericTetrix::newPiece()
00247 {
00248 currentPiece = nextPiece;
00249 if (showNext)
00250 eraseNextPiece();
00251 nextPiece.setRandomType();
00252 if (showNext)
00253 showNextPiece();
00254 currentLine = height - 1 + currentPiece.getMinY();
00255 currentPos = width/2 + 1;
00256 if (!canMoveTo(currentPos,currentLine)) {
00257 currentLine = -1;
00258 gameOver();
00259 } else {
00260 showPiece();
00261 }
00262 }
00263
00264 void GenericTetrix::removePiece()
00265 {
00266 erasePiece();
00267 currentLine = -1;
00268 }
00269
00270 void GenericTetrix::drawNextSquare(int,int,int)
00271 {
00272
00273 }
00274
00275 void GenericTetrix::pieceDropped(int)
00276 {
00277 newPiece();
00278 }
00279
00280 void GenericTetrix::updateRemoved(int)
00281 {
00282 }
00283
00284 void GenericTetrix::updateScore(int)
00285 {
00286 }
00287
00288 void GenericTetrix::updateLevel(int)
00289 {
00290 }
00291
00292 void GenericTetrix::removeFullLines()
00293 {
00294 int i,j,k;
00295 int nFullLines;
00296
00297 for(i = 0 ; i < height - nClearLines ; i++) {
00298 for(j = 0 ; j < width ; j++)
00299 if (board(j,i) == 0)
00300 break;
00301 if (j == width) {
00302 nFullLines = 1;
00303 for(k = i + 1 ; k < height - nClearLines ; k++) {
00304 for(j = 0 ; j < width ; j++)
00305 if (board(j,k) == 0)
00306 break;
00307 if (j == width) {
00308 nFullLines++;
00309 } else {
00310 for(j = 0 ; j < width ; j++) {
00311 if (board(j,k - nFullLines) != board(j,k)) {
00312 board(j,k - nFullLines) = board(j,k);
00313 draw( j,k - nFullLines,
00314 board(j,k - nFullLines));
00315 }
00316 }
00317 }
00318 }
00319 nClearLines = nClearLines + nFullLines;
00320 nLinesRemoved = nLinesRemoved + nFullLines;
00321 updateRemoved(nLinesRemoved);
00322 score = score + 10*nFullLines;
00323
00324 for (i = height - nClearLines ;
00325 i < height - nClearLines + nFullLines ;
00326 i++)
00327 for(j = 0 ; j < width ; j++)
00328 if (board(j,i) != 0) {
00329 draw(j,i,0);
00330 board(j,i) = 0;
00331 }
00332 }
00333 }
00334 }
00335
00336 void GenericTetrix::showPiece()
00337 {
00338 int x,y;
00339
00340 if (currentLine == -1)
00341 return;
00342
00343 for(int i = 0 ; i < 4 ; i++) {
00344 currentPiece.getCoord(i,x,y);
00345 draw(currentPos + x,currentLine - y,currentPiece.getType());
00346 }
00347 }
00348
00349 void GenericTetrix::erasePiece()
00350 {
00351 int x,y;
00352
00353 if (currentLine == -1)
00354 return;
00355
00356 for(int i = 0 ; i < 4 ; i++) {
00357 currentPiece.getCoord(i,x,y);
00358 draw(currentPos + x,currentLine - y,0);
00359 }
00360 }
00361
00362 void GenericTetrix::internalPieceDropped(int dropHeight)
00363 {
00364 gluePiece();
00365 nPiecesDropped++;
00366 if (nPiecesDropped % 25 == 0) {
00367 level++;
00368 updateLevel(level);
00369 }
00370 score = score + 7 + dropHeight;
00371 removeFullLines();
00372 updateScore(score);
00373 pieceDropped(dropHeight);
00374 }
00375
00376 void GenericTetrix::gluePiece()
00377 {
00378 int x,y;
00379 int min;
00380
00381 if (currentLine == -1)
00382 return;
00383
00384 for(int i = 0 ; i < 4 ; i++) {
00385 currentPiece.getCoord(i,x,y);
00386 board(currentPos + x,currentLine - y) = currentPiece.getType();
00387 }
00388 min = currentPiece.getMinY();
00389 if (currentLine - min >= height - nClearLines)
00390 nClearLines = height - currentLine + min - 1;
00391 }
00392
00393 void GenericTetrix::showNextPiece(int erase)
00394 {
00395 int x,y;
00396 int minX = nextPiece.getMinX();
00397 int minY = nextPiece.getMinY();
00398 int maxX = nextPiece.getMaxX();
00399 int maxY = nextPiece.getMaxY();
00400
00401 int xOffset = (3 - (maxX - minX))/2;
00402 int yOffset = (3 - (maxY - minY))/2;
00403
00404 for(int i = 0 ; i < 4 ; i++) {
00405 nextPiece.getCoord(i,x,y);
00406 if (erase)
00407 drawNextSquare(x + xOffset - minX,
00408 y + yOffset - minY,0);
00409 else
00410 drawNextSquare(x + xOffset - minX,
00411 y + yOffset - minY,nextPiece.getType());
00412 }
00413 }
00414
00415 int GenericTetrix::canPosition(TetrixPiece &piece)
00416 {
00417 if (currentLine == -1)
00418 return 0;
00419
00420 int x,y;
00421
00422 for(int i = 0 ; i < 4 ; i++) {
00423 piece.getCoord(i,x,y);
00424 x = currentPos + x;
00425 y = currentLine - y;
00426 if (x < 0 || x >= width || y < 0 || y >= height)
00427 return 0;
00428 if (board(x,y) != 0)
00429 return 0;
00430 }
00431 return 1;
00432
00433 }
00434
00435 int GenericTetrix::canMoveTo(int xPosition,int line)
00436 {
00437 if (currentLine == -1)
00438 return 0;
00439
00440 int x,y;
00441
00442 for(int i = 0 ; i < 4 ; i++) {
00443 currentPiece.getCoord(i,x,y);
00444 x = xPosition + x;
00445 y = line - y;
00446 if (x < 0 || x >= width || y < 0 || y >= height)
00447 return 0;
00448 if (board(x,y) != 0)
00449 return 0;
00450 }
00451 return 1;
00452 }
00453
00454 void GenericTetrix::moveTo(int xPosition,int line)
00455 {
00456 if (currentLine == -1)
00457 return;
00458 optimizedMove(xPosition,line,currentPiece);
00459 currentPos = xPosition;
00460 currentLine = line;
00461 }
00462
00463 void GenericTetrix::position(TetrixPiece &piece)
00464 {
00465 if (currentLine == -1)
00466 return;
00467
00468 optimizedMove(currentPos,currentLine,piece);
00469 }
00470
00471 void GenericTetrix::optimizedMove(int newPos, int newLine,
00472 TetrixPiece &newPiece)
00473 {
00474 int updates [8][3];
00475 int nUpdates;
00476 int value;
00477 int x,y;
00478 int i,j;
00479
00480 for(i = 0 ; i < 4 ; i++) {
00481 currentPiece.getCoord(i,x,y);
00482 updates[i][0] = currentPos + x;
00483 updates[i][1] = currentLine - y;
00484 updates[i][2] = 0;
00485 }
00486 nUpdates = 4;
00487 for(i = 0 ; i < 4 ; i++) {
00488 newPiece.getCoord(i,x,y);
00489 x = newPos + x;
00490 y = newLine - y;
00491 for (j = 0 ; j < 4 ; j++)
00492 if (updates[j][0] == x && updates[j][1] == y) {
00493
00494 if (currentPiece.getType() == newPiece.getType())
00495 updates[j][2] = -1;
00496 else
00497 updates[j][2] = newPiece.getType();
00498 break;
00499 }
00500 if (j == 4) {
00501 updates[nUpdates][0] = x;
00502 updates[nUpdates][1] = y;
00503 updates[nUpdates][2] = newPiece.getType();
00504 nUpdates++;
00505 }
00506 }
00507 for (i = 0 ; i < nUpdates ; i++) {
00508 x = updates[i][0];
00509 y = updates[i][1];
00510 value = updates[i][2];
00511 if (value != -1)
00512 draw(x,y,value);
00513 }
00514 }