• Main Page
  • Classes
  • Files
  • File List
  • File Members

code/source/Player.cpp

Go to the documentation of this file.
00001 /*
00002  * TetriCycle
00003  * Copyright (C) 2009, 2010 Cale Scholl
00004  *
00005  * This file is part of TetriCycle.
00006  *
00007  * TetriCycle is free software: you can redistribute it and/or modify
00008  * it under the terms of the GNU Lesser General Public License as published
00009  * by the Free Software Foundation, either version 3 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * TetriCycle is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with TetriCycle.  If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 /** @file Player.cpp
00022  * @author Cale Scholl / calvinss4
00023  */
00024 
00025 #include "Player.h"
00026 
00027 #include <gcmodplay.h>     // for MODPlay
00028 #include "libwiigui/gui.h" // for GuiSound
00029 #include "Options.h"       // for Options
00030 #include "tcyc_menu.h"     // for TCYC_MenuPause
00031 #include "main.h"          // for GX_Cube
00032 
00033 extern MODPlay g_modPlay; ///< used for playing the game music
00034 extern GuiSound *g_tetrisCheerSound; ///< the tetris sound effect
00035 extern Options *g_options;  ///< the global options
00036 extern Player *g_players;   ///< the player instances
00037 extern GXRModeObj *g_vmode; ///< the video mode
00038 extern Mtx g_view; ///< the global view matrix
00039 extern bool g_isClassicMode; ///< classic mode
00040 
00041 // Reset all state associated with this player.
00042 void Player::Reset()
00043 {
00044   memset(&gameData, 0, sizeof(PlayerGameData));
00045   gameData.pieces = -1;
00046   gameData.speed = START_SPEED;
00047 
00048   for (int y = 0; y < MAX_PLAYFIELD_HEIGHT; ++y)
00049   {
00050     for (int x = 0; x < MAX_PLAYFIELD_WIDTH; ++x)
00051       gameData.playfield[x][y].pieceId = TETRISPIECE_ID_NONE;
00052   }
00053 
00054   nextPiece.InitPiece(TetrisPiece::GetNextId());
00055   nextPiece.SetPowerupId(PowerupUtils::GetNextId(*this));
00056   _SpawnNextPiece();
00057 
00058   PowerupId *tmpPowerupStartQueue = !isHandicapEnabled ? 
00059     g_options->profile.powerupStartQueue : profile.powerupStartQueue;
00060   
00061   for (int i = 0; i < MAX_ACQUIRED_POWERUPS; ++i)
00062   {
00063     PowerupId pid = tmpPowerupStartQueue[i];
00064     if (pid != POWERUP_ID_NONE)
00065       gameData.powerupQueue[i] = PowerupUtils::GetStaticInstance(pid);
00066   }
00067 }
00068 
00069 // Draw the playfield (all the static tetris pieces).
00070 void Player::DrawPlayfield()
00071 {
00072   TetrisPieceConnectivityInfo *connectivityInfo = NULL;
00073   GuiImageData *imgData = NULL;
00074 
00075   for (int y = 0; y < playfieldHeight; ++y)
00076   {
00077     for (int x = 0; x < playfieldWidth; ++x)
00078     {
00079       TetrisPieceId pieceId = gameData.playfield[x][y].pieceId;
00080       if (pieceId == TETRISPIECE_ID_NONE)
00081         continue;
00082 
00083       ColorId gfx = (ColorId)pieceId;
00084 
00085       if (gameData.isDead)
00086       {
00087         gfx = COLOR_ID_DEAD;
00088       }
00089       else
00090       {
00091         connectivityInfo = gameData.playfield[x][y].connectivityInfo;
00092         imgData = !connectivityInfo ?
00093           NULL : PowerupUtils::GetImageData(connectivityInfo->powerupId);
00094       }
00095 
00096       DrawBlockAsCube(x, y, gfx, 255, imgData);
00097     }
00098   }
00099 }
00100 
00101 /** If no piece is specified, then the player's current piece is drawn. */
00102 void Player::DrawPiece(TetrisPiece* cp, u8 alpha)
00103 {
00104   TetrisPiece &piece = !cp ? currPiece : *cp;
00105   const TetrisPieceDesc &desc = piece.GetPieceDescription();
00106 
00107   ColorId gfx = (ColorId)piece.GetPieceId();
00108   GuiImageData *imgData = (piece.GetPowerupId() == POWERUP_ID_NONE) ? 
00109     NULL : PowerupUtils::GetImageData(piece.GetPowerupId());
00110 
00111   if (gameData.isDead)
00112   {
00113     gfx = COLOR_ID_DEAD;
00114     imgData = NULL;
00115   }
00116 
00117   // Every tetris piece fits into a 4x4 grid.
00118   for (int y = 0; y < 4; ++y)
00119   {
00120     for (int x = 0; x < 4; ++x)
00121     {
00122       // The playfield is a playfield_width x playfield_height grid 
00123       // (default: 10x20); the upper left corner corresponds to (0,0).
00124       // (piece.x, piece.y) is a playfield coordinate that corresponds to the 
00125       // upper left corner of the tetris piece's 4x4 grid. Thus,
00126       // (calcx, calcy) gives the playfield coordinate for each of the 
00127       // tetris piece's 4x4 grid elements.
00128       int calcx = piece.GetX() + x;
00129       int calcy = piece.GetY() + y;
00130 
00131       // Allow the screen to wrap horizontally.
00132       if (calcx >= playfieldWidth)
00133         calcx -= playfieldWidth;
00134       else if (calcx < 0)
00135         calcx += playfieldWidth;
00136 
00137       if (desc.map[x][y] && calcx >= 0 && calcy >= 0)
00138         DrawBlockAsCube(calcx, calcy, gfx, alpha, imgData);
00139     }
00140   }
00141 }
00142 
00143 // Draw where the current piece will end up if dropped.
00144 void Player::DrawPieceShadow()
00145 {
00146   if (guide == GUIDE_OFF)
00147     return;
00148 
00149   int y = 0;
00150   if (guide == GUIDE_SHADOW)
00151   {
00152     // Create a copy of the current piece, move it down as much as possible, 
00153     // then draw it. Only draw the shadow piece if it is more than x spaces 
00154     // away from the actual piece.
00155     TetrisPiece piece = currPiece;
00156     y = piece.GetY();
00157     while (MovePiece(DOWN, &piece));
00158     if (y < 7 && piece.GetY() > 11)
00159       DrawPiece(&piece, 145);
00160 
00161     return;
00162   }
00163   
00164   // else: GUIDE_LINE
00165   int x = 0;
00166   const TetrisPieceDesc &desc = currPiece.GetPieceDescription();
00167 
00168   // Calculate the leftmost lowest block.
00169   for (int my = 0; my < 4; ++my)
00170   {
00171     for (int mx = 0; mx < 4; ++mx)
00172     {
00173       if (desc.map[mx][my])
00174       {
00175         x = currPiece.GetX() + mx;
00176         y = currPiece.GetY() + my + 1;
00177         break;
00178       }
00179     }
00180   }
00181 
00182   if (x < 0)
00183     x += playfieldWidth;
00184   else if (x >= playfieldWidth)
00185     x -= playfieldWidth;
00186   
00187   for (; y < playfieldHeight; ++y)
00188   {
00189     if (gameData.playfield[x][y].pieceId == TETRISPIECE_ID_NONE)
00190       DrawBlockAsCube(x, y, COLOR_ID_RED, 128, NULL, true);
00191   }
00192 }
00193 
00194 // Draw the base of the TetriCycle.
00195 void Player::DrawBase()
00196 {
00197   GXColor color;
00198 
00199   for (int x = 0; x < playfieldWidth; ++x)
00200   {
00201     int idx = (x + gameData.cycleIdx) % playfieldWidth;
00202     u8 c = idx * 8; // black to white
00203     color = (GXColor){c, c, c, 255};
00204     _SetBaseColor(color);
00205     DrawBlockAsCube(x, playfieldHeight, COLOR_ID_BASE);
00206   }
00207 }
00208 
00209 // Move the playfield.
00210 bool Player::MovePlayfield(int type)
00211 {
00212   TetrisPiece &piece = currPiece;
00213 
00214   int oldx = piece.GetX();
00215   int x = oldx;
00216 
00217   // First move the current piece and check that it's a valid move.
00218   // Moving the playfield right is equivalent to moving the piece left.
00219   switch (type)
00220   {
00221     case RIGHT:
00222       --x;
00223       if (x < 0)
00224         x += playfieldWidth;
00225       piece.SetX(x);
00226       break;
00227 
00228     case LEFT:
00229       ++x;
00230       if (x >= playfieldWidth)
00231         x -= playfieldWidth;
00232       piece.SetX(x);
00233       break;
00234   }
00235 
00236   bool canPlace = _CanPlacePiece();
00237 
00238   // Move the piece back to where it was.
00239   piece.SetX(oldx);
00240 
00241   if (!canPlace)
00242     return false;
00243 
00244   // Move the playfield.
00245   TetrisPieceBlock *playfieldTPB = &gameData.playfield[0][0];
00246   TetrisPieceBlock tmpTPB;
00247   TetrisPieceBlock *prevTPB, *currTPB;
00248 
00249   if (type == LEFT)
00250   {
00251     for (int r = 0; r < playfieldHeight; ++r)
00252     {
00253       prevTPB = playfieldTPB + r;
00254       currTPB = prevTPB + MAX_PLAYFIELD_HEIGHT;
00255       tmpTPB = *prevTPB;
00256 
00257       for (int c = 0; c < playfieldWidth - 1; ++c, prevTPB += MAX_PLAYFIELD_HEIGHT, currTPB += MAX_PLAYFIELD_HEIGHT)
00258         *prevTPB = *currTPB;
00259 
00260       *prevTPB = tmpTPB;
00261     }
00262   }
00263   else if (type == RIGHT)
00264   {
00265     for (int r = 0; r < playfieldHeight; ++r)
00266     {
00267       prevTPB = playfieldTPB + (playfieldWidth - 1) * MAX_PLAYFIELD_HEIGHT + r;
00268       currTPB = prevTPB - MAX_PLAYFIELD_HEIGHT;
00269       tmpTPB = *prevTPB;
00270 
00271       for (int c = 0; c < playfieldWidth - 1; ++c, prevTPB -= MAX_PLAYFIELD_HEIGHT, currTPB -= MAX_PLAYFIELD_HEIGHT)
00272         *prevTPB = *currTPB;
00273 
00274       *prevTPB = tmpTPB;
00275     }
00276   }
00277 
00278   return true;
00279 }
00280 
00281 /** If no piece is specified then the player's current piece is used. */
00282 bool Player::MovePiece(int type, TetrisPiece *cp)
00283 {
00284   TetrisPiece &piece = !cp ? currPiece : *cp;
00285 
00286   int oldx = piece.GetX();
00287   int oldy = piece.GetY();
00288   int x = oldx;
00289 
00290   switch (type)
00291   {
00292     case DOWN:
00293       piece.SetY(oldy + 1);
00294       break;
00295 
00296     case LEFT:
00297       --x;
00298       if (!g_isClassicMode && x < 0)
00299         x += playfieldWidth;
00300       piece.SetX(x);
00301       break;
00302 
00303     case RIGHT:
00304       ++x;
00305       if (!g_isClassicMode && x >= playfieldWidth)
00306         x -= playfieldWidth;
00307       piece.SetX(x);
00308       break;
00309   }
00310 
00311   if (_CanPlacePiece(&piece))
00312     return true;
00313 
00314   piece.SetX(oldx);
00315   piece.SetY(oldy);
00316   return false;
00317 }
00318 
00319 // Move the current piece down automatically.
00320 void Player::DoMovement()
00321 {
00322   const TetrisPieceDesc &desc = currPiece.GetPieceDescription();
00323 
00324   gameData.frame = 0;
00325   currPiece.IncrementDownCounter();
00326 
00327   bool canMove  = MovePiece(DOWN);
00328   bool canplace = _CanPlacePiece();
00329 
00330   // Write piece to map if it can't be moved more.
00331   if (!canMove)
00332   {
00333     int nblocks = (currPiece.GetPieceId() != TETRISPIECE_ID_JUNK) ? DEFAULT_BLOCKS_PER_PIECE : 8;
00334     TetrisPieceConnectivityInfo *info = (currPiece.GetPowerupId() == POWERUP_ID_NONE) ? 
00335       NULL : new TetrisPieceConnectivityInfo(currPiece.GetPowerupId(), nblocks);
00336 
00337     for (int y = 0; y < 4; ++y)
00338     {
00339       for (int x = 0; x < 4; ++x)
00340       {
00341         // The playfield is a playfield_width x playfield_height grid 
00342         // (default: 10x20); the upper left corner corresponds to (0,0).
00343         // (piece.x, piece.y) is a playfield coordinate that corresponds to the 
00344         // upper left corner of the tetris piece's 4x4 grid. Thus,
00345         // (calcx, calcy) gives the playfield coordinate for each of the 
00346         // tetris piece's 4x4 grid elements.
00347         int calcx = currPiece.GetX() + x;
00348         int calcy = currPiece.GetY() + y;
00349 
00350         // Allow the screen to wrap horizontally.
00351         if (calcx >= playfieldWidth)
00352           calcx -= playfieldWidth;
00353         else if (calcx < 0)
00354           calcx += playfieldWidth;
00355 
00356         if (calcx >= 0 && calcx < playfieldWidth && calcy >= 0 
00357             && calcy < playfieldHeight && desc.map[x][y])
00358         {
00359           gameData.playfield[calcx][calcy].pieceId = currPiece.GetPieceId();
00360           gameData.playfield[calcx][calcy].SetConnectivityInfo(info);
00361         }
00362       }
00363     }
00364   }
00365 
00366   // Player can't move or place ==> dead.
00367   if (!canMove && !canplace)
00368   {
00369     if (g_options->players == 1)
00370     {
00371       gameData.isDead = true;
00372       TCYC_MenuPause("Game Over");
00373       return;
00374     }
00375 
00376     gameData.isDead = true;
00377     _GetWinner();
00378     return;
00379   }
00380 
00381   // Can't move, make a new block.
00382   if (!canMove) 
00383   {
00384     int linesInFrame = 0;
00385     
00386     while (_RemoveLines())
00387       ++linesInFrame;
00388 
00389     if (linesInFrame == 3)
00390     {
00391       gameData.score++; // add one bonus point if you cleared 3 lines
00392     }
00393     else if (linesInFrame == 4)
00394     {
00395       gameData.score += 2;          // add two bonus points if you get a tetris
00396       MODPlay_Pause(&g_modPlay, 1); // pause music
00397       g_tetrisCheerSound->Play();   // Yay you got a tetris!
00398     }
00399 
00400     _SpawnNextPiece();
00401   }
00402 
00403 //#ifndef EMU
00404 //  if (g_options->netplay == 1 && plyrIdx == 0)
00405 //    GC_BBA_SendUDPE(9003, (unsigned char*)map[0], 200);
00406 //#endif
00407 }
00408 
00409 // Draw each tetris piece block as a cube.
00410 void Player::DrawBlockAsCube(float x, float y, ColorId colorIdx, u8 alpha, GuiImageData *imgData, bool isGuideDot)
00411 {
00412   float scale = _GetScale() / (float)DEFAULT_PLAYFIELD_SCALE;
00413   if (g_isClassicMode)
00414     scale -= 0.1;
00415 
00416   float vx = 0;
00417 
00418   if (g_options->players == 1 && !g_options->isNetplay)
00419   {
00420     
00421   }
00422   else if (g_options->players == 2)
00423   {
00424     if (id == 0)
00425       vx = -106.6;
00426     else
00427       vx = 213.4;
00428   }
00429   else if (g_options->players == 3)
00430   {
00431     if (id == 0)
00432       vx = -210;
00433     else if (id == 2)
00434       vx = 210;
00435   }
00436   else if (g_options->players == 4)
00437   {
00438     if (id == 0)
00439       vx = -240;
00440     else if (id == 1)
00441       vx = -80;
00442     else if (id == 2)
00443       vx = 80;
00444     else
00445       vx = 240;
00446   }
00447 
00448   GX_SetViewport(vx + playfieldDX, playfieldDY, g_vmode->fbWidth, g_vmode->efbHeight, 0, 1);
00449 
00450   // x should be a value in {0,...,playfield_width - 1}
00451   // y should be a value in {0,...,playfield_height - 1}
00452   
00453   // Calculate the offset from the center of the playfield.
00454   int centerRight = playfieldWidth >> 1; // playfield_width / 2
00455   int centerLeft  = centerRight - 1;
00456   int offsetFromCenter = (x > centerLeft) ? x - centerLeft : x - centerRight;
00457 
00458   // Convert y to an offset from the bottom, and scale it.
00459   y = ((playfieldHeight >> 1) - 1 - y) * scale; // (playfield_height / 2) - 1
00460 
00461   // The half-cube z-translation.
00462   float hz = scale / 2;
00463 
00464   // TRS ==> Scale should be multiplied last.
00465   static Mtx mscale;
00466   guMtxIdentity(mscale);
00467   if (!isGuideDot)
00468   {
00469     guMtxScale(mscale, scale, scale, scale);
00470   }
00471   else
00472   {
00473     float dotScale = scale * 0.35;
00474     guMtxScale(mscale, dotScale, dotScale, dotScale);
00475   }
00476   
00477   // The angle between cubes in degrees.
00478   float cubeRotation = !g_isClassicMode ? cubeAngle : 0;
00479 
00480   if (offsetFromCenter < 0)
00481   {
00482     scale *= -1;
00483     cubeRotation *= -1;
00484     offsetFromCenter *= -1;
00485   }
00486   
00487   // The cube translation matrix.
00488   // Translate the cube along the x-axis by its length.
00489   static Mtx mtrans;
00490   guMtxIdentity(mtrans);
00491   guMtxTransApply(mtrans, mtrans, scale, 0.f, 0.f); // src, dst, x, y, z
00492 
00493   // The cube rotation matrix.
00494   // Rotate the cube about the y-axis by cubeRotation degrees.
00495   static guVector cubeAxis = {0, 1, 0}; // y-axis
00496   static Mtx mrot;
00497   guMtxIdentity(mrot);
00498   guMtxRotAxisDeg(mrot, &cubeAxis, cubeRotation);
00499 
00500   static Mtx mrottrans;
00501   guMtxIdentity(mrottrans);
00502   guMtxConcat(mrot, mtrans, mrottrans);
00503 
00504   static Mtx model;
00505   static Mtx modelview;
00506 
00507   guMtxIdentity(model);
00508 
00509   for (int i = 0; i < offsetFromCenter - 1; ++i)
00510   {
00511     guMtxConcat(model, mrottrans, model);
00512   }
00513 
00514   guMtxConcat(model, mrot, model);
00515 
00516   // This halfcubetrans is applied before all other translations and rotations.
00517   static Mtx halfcubetrans;
00518   guMtxIdentity(halfcubetrans);
00519   guMtxTransApply(halfcubetrans, halfcubetrans, scale / 2, 0.f, -hz);
00520 
00521   guMtxConcat(model, halfcubetrans, model);
00522   guMtxConcat(model, mscale, model);
00523   
00524   // Translate the cube to the correct y and z position.
00525   static Mtx trans;
00526   guMtxIdentity(trans);
00527   guMtxTransApply(trans, trans, 0, y, -32); // src, dst, x, y, z
00528   
00529   guMtxConcat(trans, model, model);
00530   guMtxConcat(g_view, model, modelview);
00531 
00532   // load the modelview matrix into matrix memory
00533   GX_LoadPosMtxImm(modelview, GX_PNMTX0);
00534   GX_Cube(colorIdx, alpha, imgData);
00535   GX_SetViewport(0, 0, g_vmode->fbWidth, g_vmode->efbHeight, 0, 1);
00536 }
00537 
00538 //--- PRIVATE ---
00539 
00540 void Player::_GetWinner()
00541 {
00542   int ndead = 0;
00543   int winner = 0;
00544 
00545   for (int i = 0; i < g_options->players; ++i)
00546   {
00547     if (g_players[i].gameData.isDead)
00548       ++ndead;
00549     else
00550       winner = i;
00551   }
00552 
00553   if (ndead == g_options->players - 1)
00554     _DisplayWinner(winner);
00555 }
00556 
00557 void Player::_DisplayWinner(int winner)
00558 {
00559   char buf[15];
00560   sprintf(buf, "Player %d wins!", winner + 1);
00561   TCYC_MenuPause(buf);
00562 }
00563 
00564 void Player::_IncreaseLevelAllBut(int plyrIdx)
00565 {
00566   for (int i = 0; i < g_options->players; ++i)
00567   {
00568     if (i != plyrIdx)
00569       g_players[i]._IncreaseLevel();
00570   }
00571 }
00572 
00573 /** If no piece is specified then the player's current piece is used. */
00574 bool Player::_CanPlacePiece(TetrisPiece *cp)
00575 {
00576   TetrisPiece &piece = !cp ? currPiece : *cp;
00577   const TetrisPieceDesc &desc = piece.GetPieceDescription();
00578 
00579   for (int y = 0; y < 4; y++)
00580   {
00581     for (int x = 0; x < 4; x++)
00582     {
00583       // Only check squares that are set in the map
00584       if (desc.map[x][y])
00585       {
00586         // The playfield is a playfield_width x playfield_height grid 
00587         // (default: 10x20); the upper left corner corresponds to (0,0).
00588         // (piece.x, piece.y) is a playfield coordinate that corresponds to the 
00589         // upper left corner of the tetris piece's 4x4 grid. Thus,
00590         // (calcx, calcy) gives the playfield coordinate for each of the 
00591         // tetris piece's 4x4 grid elements.
00592         int calcx = piece.GetX() + x;
00593         int calcy = piece.GetY() + y;
00594 
00595         // Outside the map?
00596         // Allow the screen to wrap horizontally.
00597         
00598         if (calcx >= playfieldWidth)
00599         {
00600           if (!g_isClassicMode)
00601             calcx -= playfieldWidth;
00602           else
00603             return false;
00604         }
00605         else if (calcx < 0)
00606         {
00607           if (!g_isClassicMode)
00608             calcx += playfieldWidth;
00609           else
00610             return false;
00611         }
00612 
00613         if (calcy >= playfieldHeight)
00614           return false;
00615 
00616         // On top of something else?
00617         if (calcy >= 0 
00618             && gameData.playfield[calcx][calcy].pieceId != TETRISPIECE_ID_NONE)
00619           return false;
00620       }
00621     }
00622   }
00623 
00624   return true;
00625 }
00626 
00627 // Removes all the completed lines.
00628 bool Player::_RemoveLines()
00629 {
00630   int blocksInLine = 0;
00631 
00632   for (int y = 0; y < playfieldHeight; ++y)
00633   {
00634     for (int x = 0; x < playfieldWidth; ++x)
00635     {
00636       if (gameData.playfield[x][y].pieceId != TETRISPIECE_ID_NONE)
00637         ++blocksInLine;
00638     }
00639 
00640     if (blocksInLine == playfieldWidth)
00641     {
00642       _RemoveLine(y);
00643       return true;
00644     }
00645 
00646     blocksInLine = 0;
00647   }
00648 
00649   return false;
00650 }
00651 
00652 // Removes the line at the given row.
00653 void Player::_RemoveLine(int line)
00654 {
00655   TetrisPieceConnectivityInfo *connectivityInfo = NULL;
00656 
00657   for (int x = 0; x < playfieldWidth; ++x)
00658   {
00659     // If a block has connectivity info then it belongs to a powerup piece.
00660     connectivityInfo = gameData.playfield[x][line].connectivityInfo;
00661     if (connectivityInfo)
00662     {
00663       connectivityInfo->counter--;
00664 
00665       if (connectivityInfo->counter == 0)
00666       {
00667         // Add powerup to powerup queue.
00668         int slot = GetPowerupQueueSlot();
00669         if (slot >= 0)
00670         {
00671           Powerup *powerup = PowerupUtils::GetStaticInstance(connectivityInfo->powerupId);
00672           QueuePowerup(powerup, slot);
00673         }
00674 
00675         gameData.playfield[x][line].Free();
00676       }
00677     }
00678   }
00679 
00680   for (int y = line; y > 0; --y)
00681   {
00682     for (int x = 0; x < playfieldWidth; ++x)
00683     {
00684       gameData.playfield[x][y] = gameData.playfield[x][y-1];
00685     }
00686   }
00687 
00688   for (int x = 0; x < playfieldWidth; ++x)
00689   {
00690     gameData.playfield[x][0].pieceId = TETRISPIECE_ID_NONE;
00691     gameData.playfield[x][0].SetConnectivityInfo(NULL);
00692   }
00693 
00694   gameData.lines++;
00695   gameData.score++;
00696 
00697   if (g_options->players == 1)
00698   {
00699     if (gameData.lines % 10 == 0)
00700       _IncreaseLevel();
00701 
00702     return;
00703   }
00704 
00705   int tmpMaxLines = isHandicapEnabled ? profile.maxLines : g_options->profile.maxLines;
00706 
00707   if (tmpMaxLines && gameData.lines == tmpMaxLines)
00708   {
00709     _DisplayWinner(id);
00710     return;
00711   }
00712 
00713   int tmpAttackRate = isHandicapEnabled ? profile.attackRate : g_options->profile.attackRate;
00714 
00715   // Attack opponents whenever score is a multiple of attack rate.
00716   if (tmpAttackRate && gameData.score % tmpAttackRate == 0)
00717   {
00718     _IncreaseLevelAllBut(id);
00719   }     
00720 }

Generated on Wed Oct 20 2010 17:06:58 for TetriCycle by  doxygen 1.7.1