00001 #include <gccore.h>
00002 #include <wiiuse/wpad.h>
00003
00004 #include "defines.h"
00005 #include "globals.h"
00006 #include "prototypes.h"
00007 #include "tetris_input.h"
00008 #include "TetrisPiece.h"
00009
00010 #define EMU
00011
00012 inline int GetWinner();
00013
00014 bool MovePlayfield(int type, int player)
00015 {
00016
00017
00018 cblock& p = block[player];
00019
00020 int oldx = p.xtile;
00021 int width = g_players[player].playfieldWidth;
00022 int height = g_players[player].playfieldHeight;
00023
00024 switch(type)
00025 {
00026 case RIGHT:
00027 p.xtile--;
00028 if (p.xtile < 0)
00029 p.xtile += width;
00030 break;
00031
00032 case LEFT:
00033 p.xtile++;
00034 if (p.xtile >= width)
00035 p.xtile -= width;
00036 break;
00037 }
00038
00039 bool bCanPlace = canPlace(player);
00040
00041
00042 p.xtile = oldx;
00043
00044 if (!bCanPlace)
00045 return false;
00046
00047
00048 u8 *playfield = &map[player][0][0];
00049 u8 tmp;
00050 u8 *prev, *curr;
00051
00052 TetrisPieceBlock *playfieldTPB = &g_players[player].gameData.playfield[0][0];
00053 TetrisPieceBlock tmpTPB;
00054 TetrisPieceBlock *prevTPB, *currTPB;
00055
00056 if (type == LEFT)
00057 {
00058 for (int r = 0; r < height; ++r)
00059 {
00060 prev = playfield + r;
00061 curr = prev + MAX_PLAYFIELD_HEIGHT;
00062 tmp = *prev;
00063
00064 prevTPB = playfieldTPB + r;
00065 currTPB = prevTPB + MAX_PLAYFIELD_HEIGHT;
00066 tmpTPB = *prevTPB;
00067
00068 for (int c = 0; c < width - 1; ++c, prev += MAX_PLAYFIELD_HEIGHT, curr += MAX_PLAYFIELD_HEIGHT, prevTPB += MAX_PLAYFIELD_HEIGHT, currTPB += MAX_PLAYFIELD_HEIGHT)
00069 {
00070 *prev = *curr;
00071 *prevTPB = *currTPB;
00072 }
00073
00074 *prev = tmp;
00075 *prevTPB = tmpTPB;
00076 }
00077 }
00078 else if (type == RIGHT)
00079 {
00080 for (int r = 0; r < height; ++r)
00081 {
00082 prev = playfield + (width - 1) * MAX_PLAYFIELD_HEIGHT + r;
00083 curr = prev - MAX_PLAYFIELD_HEIGHT;
00084 tmp = *prev;
00085
00086 prevTPB = playfieldTPB + (width - 1) * MAX_PLAYFIELD_HEIGHT + r;
00087 currTPB = prevTPB - MAX_PLAYFIELD_HEIGHT;
00088 tmpTPB = *prevTPB;
00089
00090 for (int c = 0; c < width - 1; ++c, prev -= MAX_PLAYFIELD_HEIGHT, curr -= MAX_PLAYFIELD_HEIGHT, prevTPB -= MAX_PLAYFIELD_HEIGHT, currTPB -= MAX_PLAYFIELD_HEIGHT)
00091 {
00092 *prev = *curr;
00093 *prevTPB = *currTPB;
00094 }
00095
00096 *prev = tmp;
00097 *prevTPB = tmpTPB;
00098 }
00099 }
00100
00101 return true;
00102 }
00103
00104 bool MoveBlock(int type, int player, cblock* cp)
00105 {
00106 cblock& p = !cp ? block[player] : *cp;
00107
00108 int oldx = p.xtile;
00109 int oldy = p.ytile;
00110 int width = g_players[player].playfieldWidth;
00111
00112 switch(type)
00113 {
00114 case DOWN:
00115 p.ytile++;
00116 break;
00117
00118 case LEFT:
00119 p.xtile--;
00120 if (p.xtile < 0)
00121 p.xtile += width;
00122 break;
00123
00124 case RIGHT:
00125 p.xtile++;
00126 if (p.xtile >= width)
00127 p.xtile -= width;
00128 break;
00129 }
00130
00131 if (canPlace(player, &p))
00132 return true;
00133
00134 p.xtile = oldx;
00135 p.ytile = oldy;
00136 return false;
00137 }
00138
00139 void DoMovement(int player)
00140 {
00141 if (g_players[player].gameData.isDead)
00142 return;
00143
00144 cblock& p = block[player];
00145
00146 bool move = MoveBlock(DOWN, player);
00147 bool place = canPlace(player);
00148 int width = g_players[player].playfieldWidth;
00149 int height = g_players[player].playfieldHeight;
00150
00151
00152 if (!move)
00153 {
00154 TetrisPieceConnectivityInfo *info = (p.powerupId == POWERUP_ID_NONE) ?
00155 NULL : new TetrisPieceConnectivityInfo(p.powerupId);
00156
00157 for (int y = 0; y < 4; ++y)
00158 {
00159 for (int x = 0; x < 4; ++x)
00160 {
00161 int calcx = p.xtile + x;
00162 int calcy = p.ytile + y;
00163
00164
00165 if (calcx >= width)
00166 calcx -= width;
00167 else if (calcx < 0)
00168 calcx += width;
00169
00170 if (calcx >= 0 && calcx < width && calcy >= 0 && calcy < height && p.map[x][y])
00171 {
00172 map[player][calcx][calcy] = p.gfx;
00173 g_players[player].gameData.playfield[calcx][calcy].SetConnectivityInfo(info);
00174 }
00175 }
00176 }
00177 }
00178
00179
00180 if (!move && !place)
00181 {
00182 if (options.players==1)
00183 {
00184 g_players[player].gameData.isDead = true;
00185 Pause("Game Over");
00186 return;
00187 }
00188
00189 g_players[player].gameData.isDead = true;
00190 int win = GetWinner();
00191 if (win >= 0)
00192 winner(win);
00193
00194 return;
00195 }
00196
00197
00198 if (!move)
00199 {
00200 while (RemoveLines(player)) { p.linesinframe++; }
00201
00202 if (p.linesinframe == 3)
00203 {
00204 g_players[player].gameData.score++;
00205 }
00206 else if (p.linesinframe == 4)
00207 {
00208 g_players[player].gameData.score += 2;
00209 MODPlay_Pause(&play, 1);
00210 g_tetrisCheerSound->Play();
00211 }
00212
00213 p.linesinframe = 0;
00214 NewBlock(player);
00215 }
00216
00217 #ifndef EMU
00218 if(options.netplay==1 && player==0)
00219 GC_BBA_SendUDPE(9003,(unsigned char*)map[0],200);
00220 #endif
00221 }
00222
00223 inline int GetWinner()
00224 {
00225 int ndead = 0;
00226 int winner;
00227
00228 for (int i = 0; i < options.players; ++i)
00229 {
00230 if (g_players[i].gameData.isDead)
00231 ++ndead;
00232 else
00233 winner = i;
00234 }
00235
00236 if (ndead == options.players - 1)
00237 return winner;
00238
00239 return -1;
00240 }