home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 3.iso / dist / fw_qt3.idb / usr / freeware / Qt / examples / tetrix / gtetrix.cpp.z / gtetrix.cpp
Encoding:
C/C++ Source or Header  |  2002-04-08  |  11.9 KB  |  504 lines

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