1 /* FloboPuyo
2 * Copyright (C) 2004
3 * Florent Boudet <flobo@ios-software.com>,
4 * Jean-Christophe Hoelt <jeko@ios-software.com>,
5 * Guillaume Borios <gyom@ios-software.com>
6 *
7 * iOS Software <http://www.ios-software.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 *
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "PuyoGame.h"
29 #include "audio.h"
30 #include "glSDL.h"
31
32
33 static int fallingTable[PUYODIMX] = {0, 3, 1, 4, 2, 5};
34
PuyoRandomSystem()35 PuyoRandomSystem::PuyoRandomSystem()
36 {
37 srandom(SDL_GetTicks());
38 }
39
getPuyoForSequence(int sequence)40 PuyoState PuyoRandomSystem::getPuyoForSequence(int sequence)
41 {
42 if (sequenceItems.getSize() <= sequence) {
43 int newItem = (random() % 5) + PUYO_FALLINGBLUE;
44 sequenceItems.addElement((void *)newItem);
45 return (PuyoState)newItem;
46 }
47 else
48 return (PuyoState)(long)(sequenceItems.getElementAt(sequence));
49 }
50
PuyoPuyo(PuyoState state)51 PuyoPuyo::PuyoPuyo(PuyoState state)
52 {
53 this->state = state;
54 X = 0; Y = 0;
55 }
56
isFalling()57 bool PuyoPuyo::isFalling()
58 {
59 return (state < PUYO_EMPTY);
60 }
61
getPuyoState()62 PuyoState PuyoPuyo::getPuyoState()
63 {
64 if (this != NULL)
65 return state;
66 return PUYO_EMPTY;
67 }
68
setPuyoState(PuyoState state)69 void PuyoPuyo::setPuyoState(PuyoState state)
70 {
71 if (this != NULL)
72 this->state = state;
73 }
74
getPuyoX() const75 int PuyoPuyo::getPuyoX() const
76 {
77 if (this != NULL)
78 return X;
79 return 0;
80 }
81
getPuyoY() const82 int PuyoPuyo::getPuyoY() const
83 {
84 if (this != NULL)
85 return Y;
86 return 0;
87 }
88
setPuyoXY(int X,int Y)89 void PuyoPuyo::setPuyoXY(int X, int Y)
90 {
91 if (this != NULL)
92 {
93 this->X = X; this->Y = Y;
94 }
95 }
96
PuyoGame(PuyoRandomSystem * attachedRandom,PuyoFactory * attachedFactory)97 PuyoGame::PuyoGame(PuyoRandomSystem *attachedRandom,
98 PuyoFactory *attachedFactory)
99 {
100 this->attachedFactory = attachedFactory;
101 InitGame(attachedRandom);
102 }
103
PuyoGame(PuyoRandomSystem * attachedRandom)104 PuyoGame::PuyoGame(PuyoRandomSystem *attachedRandom)
105 {
106 attachedFactory = new PuyoDefaultFactory();
107 InitGame(attachedRandom);
108 }
109
InitGame(PuyoRandomSystem * attachedRandom)110 void PuyoGame::InitGame(PuyoRandomSystem *attachedRandom)
111 {
112 nbFalled = 0;
113 int i, j;
114 unmoveablePuyo = attachedFactory->createPuyo(PUYO_UNMOVEABLE);
115 for (i = 0 ; i < PUYODIMX ; i++) {
116 for (j = 0 ; j <= PUYODIMY ; j++) {
117 if (j == PUYODIMY)
118 setPuyoAt(i, j, unmoveablePuyo);
119 else
120 setPuyoAt(i, j, NULL);
121 }
122 }
123 this->attachedRandom = attachedRandom;
124 sequenceNr = 0;
125 semiMove = 0;
126 neutralPuyos = 0;
127 delegate = NULL;
128 endOfCycle = false;
129 gameRunning = true;
130 setFallingAtTop(true);
131 points = 0;
132 }
133
~PuyoGame()134 PuyoGame::~PuyoGame()
135 {
136 delete unmoveablePuyo;
137 }
138
setDelegate(PuyoDelegate * delegate)139 void PuyoGame::setDelegate(PuyoDelegate *delegate)
140 {
141 this->delegate = delegate;
142 }
143
cycle()144 void PuyoGame::cycle()
145 {
146 if (!gameRunning)
147 return;
148
149 semiMove = 1 - semiMove;
150 if (semiMove == 0)
151 return;
152
153 if (endOfCycle) {
154 cycleEnding();
155 if (delegate != NULL)
156 notifyReductions();
157 return;
158 }
159 if ((fallingY >= 0)&&(getPuyoCellAt(fallingX, fallingY+1) > PUYO_EMPTY) || (getPuyoCellAt(getFallingCompanionX(), getFallingCompanionY()+1) > PUYO_EMPTY)) {
160 setPuyoAt(fallingX, getFallY(fallingX, fallingY), fallingPuyo);
161 fallingPuyo->setPuyoState((PuyoState)(fallingPuyo->getPuyoState()+PUYO_STILL));
162 setPuyoAt(getFallingCompanionX(), getFallY(getFallingCompanionX(), getFallingCompanionY()), companionPuyo);
163 companionPuyo->setPuyoState((PuyoState)(companionPuyo->getPuyoState()+PUYO_STILL));
164 if (delegate != NULL) {
165 delegate->puyoDidFall(fallingPuyo, fallingX, fallingY);
166 delegate->puyoDidFall(companionPuyo, getFallingCompanionX(), getFallingCompanionY());
167 fallingY = -10;
168 notifyReductions();
169 }
170 endOfCycle = true;
171 }
172 else {
173 fallingY++;
174 fallingPuyo->setPuyoXY(fallingX, fallingY);
175 companionPuyo->setPuyoXY(getFallingCompanionX(), getFallingCompanionY());
176 }
177 }
178
179 // Get the state of the puyo at the indicated coordinates
getPuyoCellAt(int X,int Y) const180 PuyoState PuyoGame::getPuyoCellAt(int X, int Y) const
181 {
182 PuyoPuyo *thePuyo = getPuyoAt(X, Y);
183 if (thePuyo)
184 return thePuyo->getPuyoState();
185 return PUYO_EMPTY;
186 }
187
188 // Get the puyo at the indicated coordinates
getPuyoAt(int X,int Y) const189 PuyoPuyo *PuyoGame::getPuyoAt(int X, int Y) const
190 {
191 if ((X >= PUYODIMX) || (Y >= PUYODIMY) || (X < 0) || (Y < 0))
192 return unmoveablePuyo;
193 if (!endOfCycle) {
194 if ((X == fallingX) && (Y == fallingY))
195 return fallingPuyo;
196 if ((X == getFallingCompanionX()) && (Y == getFallingCompanionY()))
197 return companionPuyo;
198 }
199 return puyoCells[X + Y * PUYODIMX];
200 }
201
202 // List access to the PuyoPuyo objects
getPuyoCount() const203 int PuyoGame::getPuyoCount() const
204 {
205 return puyoVector.getSize();
206 }
207
getPuyoAtIndex(int index) const208 PuyoPuyo *PuyoGame::getPuyoAtIndex(int index) const
209 {
210 return (PuyoPuyo *)(puyoVector.getElementAt(index));
211 }
212
moveLeft()213 void PuyoGame::moveLeft()
214 {
215 if (endOfCycle) {
216 return;
217 }
218 if (((fallingY<0)&&(fallingX>0))||((getPuyoCellAt(fallingX-1, fallingY) <= PUYO_EMPTY)
219 && (getPuyoCellAt(getFallingCompanionX()-1, getFallingCompanionY()) <= PUYO_EMPTY)))
220 {
221 fallingX--;
222 }
223 fallingPuyo->setPuyoXY(fallingX, fallingY);
224 companionPuyo->setPuyoXY(getFallingCompanionX(), getFallingCompanionY());
225 }
226
moveRight()227 void PuyoGame::moveRight()
228 {
229 if (endOfCycle) {
230 return;
231 }
232 if (((fallingY<0)&&(fallingX<PUYODIMX-1))||((getPuyoCellAt(fallingX+1, fallingY) <= PUYO_EMPTY)
233 && (getPuyoCellAt(getFallingCompanionX()+1, getFallingCompanionY()) <= PUYO_EMPTY)))
234 fallingX++;
235 fallingPuyo->setPuyoXY(fallingX, fallingY);
236 companionPuyo->setPuyoXY(getFallingCompanionX(), getFallingCompanionY());
237 }
238
rotate(bool left)239 void PuyoGame::rotate(bool left)
240 {
241 if (endOfCycle) {
242 return;
243 }
244 unsigned char backupCompanion = fallingCompanion;
245 /*int backupX = fallingX;
246 int backupY = fallingY;*/
247 int newX, newY;
248 bool moved = true;
249 fallingCompanion = (unsigned char)(fallingCompanion + (left?3:1)) % 4;
250 unsigned char newCompanion = fallingCompanion;
251 int newCompanionX = getFallingCompanionX();
252 int newCompanionY = getFallingCompanionY();
253 fallingCompanion = backupCompanion;
254 if (getPuyoCellAt(newCompanionX, newCompanionY) > PUYO_EMPTY) {
255 //if (((fallingY<0)&&(fallingX>0)&&(fallingX<PUYODIMX-1))||(getPuyoCellAt(newCompanionX, newCompanionY) > PUYO_EMPTY)) {
256 newX = fallingX + (fallingX - newCompanionX);
257 newY = fallingY + (fallingY - newCompanionY);
258 // if ((fallingY >= 0) && (getPuyoCellAt(newX, newY) > PUYO_EMPTY)) {
259 if (getPuyoCellAt(newX, newY) > PUYO_EMPTY) {
260 moved = false;
261 }
262 else {
263 fallingCompanion = newCompanion;
264 fallingX = newX;
265 if (fallingY != newY)
266 {
267 semiMove = 0;
268 fallingY = newY;
269 }
270 fallingPuyo->setPuyoXY(fallingX, fallingY);
271 }
272 }
273 else
274 fallingCompanion = newCompanion;
275
276 companionPuyo->setPuyoXY(getFallingCompanionX(), getFallingCompanionY());
277
278 if ((delegate != NULL) && (moved))
279 delegate->companionDidTurn(companionPuyo, fallingCompanion, !left);
280
281 }
282
rotateLeft()283 void PuyoGame::rotateLeft()
284 {
285 rotate(true);
286 }
287
rotateRight()288 void PuyoGame::rotateRight()
289 {
290 rotate(false);
291 }
292
getNextFalling()293 PuyoState PuyoGame::getNextFalling()
294 {
295 return attachedRandom->getPuyoForSequence(sequenceNr);
296 }
297
getNextCompanion()298 PuyoState PuyoGame::getNextCompanion()
299 {
300 return attachedRandom->getPuyoForSequence(sequenceNr+1);
301 }
302
increaseNeutralPuyos(int incr)303 void PuyoGame::increaseNeutralPuyos(int incr)
304 {
305 neutralPuyos += incr;
306 }
307
getNeutralPuyos() const308 int PuyoGame::getNeutralPuyos() const
309 {
310 return neutralPuyos;
311 }
312
313
314
315 // Set the state of the puyo at the indicated coordinates (not recommanded)
setPuyoCellAt(int X,int Y,PuyoState value)316 void PuyoGame::setPuyoCellAt(int X, int Y, PuyoState value)
317 {
318 /*if ((X > PUYODIMX) || (Y > PUYODIMY))
319 return;*/
320 if (puyoCells[X + Y * PUYODIMX])
321 puyoCells[X + Y * PUYODIMX]->setPuyoState(value);
322 };
323
324 // Set the puyo at the indicated coordinates
setPuyoAt(int X,int Y,PuyoPuyo * newPuyo)325 void PuyoGame::setPuyoAt(int X, int Y, PuyoPuyo *newPuyo)
326 {
327 puyoCells[X + Y * PUYODIMX] = newPuyo;
328 if (newPuyo != NULL)
329 newPuyo->setPuyoXY(X, Y);
330 }
331
dropNeutrals()332 void PuyoGame::dropNeutrals()
333 {
334 if (neutralPuyos < 0) {
335 extern int gameLevel;
336 points -= gameLevel * neutralPuyos * 1000;
337 }
338
339 int idNeutral = 0;
340 while (neutralPuyos > 0)
341 {
342 int cycleNeutral;
343 if (neutralPuyos >= PUYODIMX)
344 cycleNeutral = PUYODIMX;
345 else
346 cycleNeutral = neutralPuyos;
347 for (int i = 0 ; i < cycleNeutral ; i++)
348 {
349 int posX = fallingTable[(nbFalled++) % PUYODIMX];
350 int posY = getFallY(posX, 2);
351 neutralPuyos -= 1;
352 if (getPuyoCellAt(posX, posY) != PUYO_EMPTY)
353 continue;
354 // Creating a new neutral puyo
355 PuyoPuyo *newNeutral = attachedFactory->createPuyo(PUYO_NEUTRAL);
356 puyoVector.addElement(newNeutral);
357 setPuyoAt(posX, posY, newNeutral);
358 if (delegate != NULL)
359 delegate->gameDidAddNeutral(newNeutral, idNeutral++);
360 }
361 }
362 neutralPuyos = 0;
363 }
364
setFallingAtTop(bool gameConstruction)365 void PuyoGame::setFallingAtTop(bool gameConstruction)
366 {
367 if (delegate != NULL)
368 delegate->gameDidEndCycle();
369
370 if (!gameConstruction) {
371 dropNeutrals();
372 if (getPuyoCellAt((PUYODIMX-1)/2, 1) != PUYO_EMPTY) {
373 gameRunning = false;
374 if (delegate != NULL)
375 delegate->gameLost();
376 return;
377 }
378 }
379
380 // Creating the new falling puyo and its companion
381 fallingX = (PUYODIMX-1)/2;
382 fallingY = 1;
383 fallingCompanion = 2;
384 fallingPuyo = attachedFactory->createPuyo(attachedRandom->getPuyoForSequence(sequenceNr++));
385 companionPuyo = attachedFactory->createPuyo(attachedRandom->getPuyoForSequence(sequenceNr++));
386 fallingPuyo->setPuyoXY(fallingX, fallingY);
387 companionPuyo->setPuyoXY(getFallingCompanionX(), getFallingCompanionY());
388 puyoVector.addElement(fallingPuyo);
389 puyoVector.addElement(companionPuyo);
390
391 endOfCycle = false;
392 semiMove = 0;
393 phase = 0;
394 }
395
getFallingCompanionX() const396 int PuyoGame::getFallingCompanionX() const
397 {
398 if (fallingCompanion == 1)
399 return fallingX - 1;
400 if (fallingCompanion == 3)
401 return fallingX + 1;
402 return fallingX;
403 }
404
getFallingCompanionY() const405 int PuyoGame::getFallingCompanionY() const
406 {
407 if (fallingCompanion == 0)
408 return fallingY + 1;
409 if (fallingCompanion == 2)
410 return fallingY - 1;
411 return fallingY;
412 }
413
getFallY(int X,int Y) const414 int PuyoGame::getFallY(int X, int Y) const
415 {
416 int result = Y + 1;
417 while (getPuyoCellAt(X, result) == PUYO_EMPTY)
418 result++;
419 return result - 1;
420 }
421
getColumnHeigth(int colNum) const422 int PuyoGame::getColumnHeigth(int colNum) const
423 {
424 int result = 0;
425 for (int i = 0 ; i < PUYODIMY ; i++) {
426 if (getPuyoCellAt(colNum, i) > PUYO_EMPTY)
427 result++;
428 }
429 return result;
430 }
431
getMaxColumnHeight() const432 int PuyoGame::getMaxColumnHeight() const
433 {
434 int max = 0;
435 for (int i=0;i<PUYODIMX;++i) {
436 int v = getColumnHeigth(i);
437 if (v>max) max=v;
438 }
439 return max;
440 }
441
getSamePuyoAround(int X,int Y,PuyoState color)442 int PuyoGame::getSamePuyoAround(int X, int Y, PuyoState color)
443 {
444 char marked[PUYODIMX][PUYODIMY];
445 int mx[PUYODIMY*PUYODIMX];
446 int my[PUYODIMX*PUYODIMY];
447 int nFound = 1;
448 bool again = true;
449 mx[0] = X;
450 my[0] = Y;
451
452 for (int x=0;x<PUYODIMX;++x)
453 for (int y=0;y<PUYODIMY;++y)
454 marked[x][y] = 0;
455 marked[X][Y] = 1;
456
457 while (again) {
458 again = false;
459 for (int i=nFound-1;i>=0;--i) {
460 X = mx[i];
461 Y = my[i];
462 if ((Y+1<PUYODIMY)&&!marked[X][Y+1] && (getPuyoCellAt(X,Y+1) == color)) {
463 again = true;
464 mx[nFound] = X;
465 my[nFound] = Y+1;
466 marked[X][Y+1] = 1;
467 nFound++;
468 }
469 if ((X+1<PUYODIMX) && !marked[X+1][Y] && (getPuyoCellAt(X+1,Y) == color)) {
470 again = true;
471 mx[nFound] = X+1;
472 my[nFound] = Y;
473 marked[X+1][Y] = 1;
474 nFound++;
475 }
476 if ((X-1>=0) && !marked[X-1][Y] && (getPuyoCellAt(X-1,Y) == color)) {
477 again = true;
478 mx[nFound] = X-1;
479 my[nFound] = Y;
480 marked[X-1][Y] = 1;
481 nFound++;
482 }
483 if ((Y-1>=0) && !marked[X][Y-1] && (getPuyoCellAt(X,Y-1) == color)) {
484 again = true;
485 mx[nFound] = X;
486 my[nFound] = Y-1;
487 marked[X][Y-1] = 1;
488 nFound++;
489 }
490 }
491 }
492 return nFound;
493 }
494
markPuyoAt(int X,int Y,PuyoState color,bool includeNeutral)495 void PuyoGame::markPuyoAt(int X, int Y, PuyoState color, bool includeNeutral)
496 {
497 PuyoState currentPuyo = getPuyoCellAt(X, Y);
498 setPuyoCellAt(X, Y, color);
499 if (getPuyoCellAt(X-1, Y) == currentPuyo)
500 markPuyoAt(X-1, Y, color, includeNeutral);
501 if (getPuyoCellAt(X+1, Y) == currentPuyo)
502 markPuyoAt(X+1, Y, color, includeNeutral);
503 if (getPuyoCellAt(X, Y-1) == currentPuyo)
504 markPuyoAt(X, Y-1, color, includeNeutral);
505 if (getPuyoCellAt(X, Y+1) == currentPuyo)
506 markPuyoAt(X, Y+1, color, includeNeutral);
507 if (includeNeutral) {
508 if (getPuyoCellAt(X-1, Y) == PUYO_NEUTRAL)
509 setPuyoCellAt(X-1, Y, color);
510 if (getPuyoCellAt(X+1, Y) == PUYO_NEUTRAL)
511 setPuyoCellAt(X+1, Y, color);
512 if (getPuyoCellAt(X, Y-1) == PUYO_NEUTRAL)
513 setPuyoCellAt(X, Y-1, color);
514 if (getPuyoCellAt(X, Y+1) == PUYO_NEUTRAL)
515 setPuyoCellAt(X, Y+1, color);
516 }
517 }
518
519 // delete the marked puyos and the neutral next to them
deleteMarkedPuyosAt(int X,int Y)520 void PuyoGame::deleteMarkedPuyosAt(int X, int Y)
521 {
522 PuyoState currentPuyo = getPuyoCellAt(X, Y);
523 puyoVector.removeElement(getPuyoAt(X, Y));
524 if (getPuyoAt(X,Y) == companionPuyo) {
525 attachedFactory->deletePuyo(getPuyoAt(X, Y));
526 companionPuyo = NULL;
527 }
528 else if (getPuyoAt(X,Y) == fallingPuyo) {
529 attachedFactory->deletePuyo(getPuyoAt(X, Y));
530 fallingPuyo = NULL;
531 } else {
532 attachedFactory->deletePuyo(getPuyoAt(X, Y));
533 }
534 setPuyoAt(X, Y, NULL);
535 if (getPuyoCellAt(X-1, Y) == currentPuyo)
536 deleteMarkedPuyosAt(X-1, Y);
537 if (getPuyoCellAt(X+1, Y) == currentPuyo)
538 deleteMarkedPuyosAt(X+1, Y);
539 if (getPuyoCellAt(X, Y-1) == currentPuyo)
540 deleteMarkedPuyosAt(X, Y-1);
541 if (getPuyoCellAt(X, Y+1) == currentPuyo)
542 deleteMarkedPuyosAt(X, Y+1);
543 if (getPuyoCellAt(X-1, Y) == PUYO_NEUTRAL) {
544 puyoVector.removeElement(getPuyoAt(X-1, Y));
545 attachedFactory->deletePuyo(getPuyoAt(X-1, Y));
546 setPuyoAt(X-1, Y, NULL);
547 }
548 if (getPuyoCellAt(X+1, Y) == PUYO_NEUTRAL) {
549 puyoVector.removeElement(getPuyoAt(X+1, Y));
550 attachedFactory->deletePuyo(getPuyoAt(X+1, Y));
551 setPuyoAt(X+1, Y, NULL);
552 }
553 if (getPuyoCellAt(X, Y-1) == PUYO_NEUTRAL) {
554 puyoVector.removeElement(getPuyoAt(X, Y-1));
555 attachedFactory->deletePuyo(getPuyoAt(X, Y-1));
556 setPuyoAt(X, Y-1, NULL);
557 }
558 if (getPuyoCellAt(X, Y+1) == PUYO_NEUTRAL) {
559 puyoVector.removeElement(getPuyoAt(X, Y+1));
560 attachedFactory->deletePuyo(getPuyoAt(X, Y+1));
561 setPuyoAt(X, Y+1, NULL);
562 }
563 }
564
removePuyos()565 int PuyoGame::removePuyos()
566 {
567 int globalRemovedPuyos = 0;
568 /* First, we will mark all the puyos that need to be removed */
569 for (int i = 0 ; i < PUYODIMX ; i++) {
570 for (int j = 0 ; j <= PUYODIMY ; j++) {
571 PuyoState currentPuyo = getPuyoCellAt(i, j);
572 if ((currentPuyo >= PUYO_BLUE) && (currentPuyo <= PUYO_YELLOW)) {
573 int removedPuyos = 0;
574 markPuyoAt(i, j, PUYO_MARKED, false);
575 for (int u = 0 ; u < PUYODIMX ; u++) {
576 for (int v = 0 ; v <= PUYODIMY ; v++) {
577 if (getPuyoCellAt(u, v) == PUYO_MARKED) {
578 removedPuyos++;
579 }
580 }
581 }
582 //printf("Removed for %d, %d : %d\n", i, j, removedPuyos);
583 if (removedPuyos >= 4) {
584 globalRemovedPuyos += removedPuyos;
585 deleteMarkedPuyosAt(i, j);
586 }
587 else
588 markPuyoAt(i, j, currentPuyo, false);
589 }
590 }
591 }
592
593 /* Next we make the other puyos fall */
594 for (int i = 0 ; i < PUYODIMX ; i++) {
595 for (int j = PUYODIMY - 1 ; j > 0 ; j--) {
596 PuyoState currentPuyoState = getPuyoCellAt(i, j);
597 if ((currentPuyoState >= PUYO_BLUE) && (currentPuyoState <= PUYO_NEUTRAL)) {
598 int newJ = getFallY(i, j);
599 if (newJ != j) {
600 PuyoPuyo *currentPuyo = getPuyoAt(i, j);
601 setPuyoAt(i, j, NULL);
602 setPuyoAt(i, newJ, currentPuyo);
603 if (delegate != NULL) {
604 delegate->puyoDidFall(currentPuyo, i, j);
605 }
606 }
607 }
608 }
609 }
610
611 return globalRemovedPuyos;
612 }
613
614
notifyReductions()615 void PuyoGame::notifyReductions()
616 {
617 IosVector removedPuyos;
618
619 // Clearing every puyo's flag
620 for (int i = 0, j = getPuyoCount() ; i < j ; i++) {
621 getPuyoAtIndex(i)->unsetFlag();
622 }
623 // Search for groupped puyos
624 int puyoGroupNumber = 0;
625 for (int j = 0 ; j < PUYODIMY ; j++) {
626 for (int i = 0 ; i <= PUYODIMX ; i++) {
627 PuyoPuyo *puyoToMark = getPuyoAt(i, j);
628 // If the puyo exists and is not flagged, then
629 if ((puyoToMark != NULL) && (! puyoToMark->getFlag())) {
630 PuyoState initialPuyoState = puyoToMark->getPuyoState();
631 // I really would have liked to skip this stupid test
632 if ((initialPuyoState >= PUYO_BLUE) && (initialPuyoState <= PUYO_YELLOW)) {
633 markPuyoAt(i, j, PUYO_MARKED, false);
634
635 // Collecting every marked puyo in a vector
636 removedPuyos.removeAllElements();
637 for (int u = 0 ; u < PUYODIMX ; u++) {
638 for (int v = 0 ; v <= PUYODIMY ; v++) {
639 PuyoPuyo *markedPuyo = getPuyoAt(u, v);
640 if (markedPuyo->getPuyoState() == PUYO_MARKED) {
641 // mark the puyo so we wont'do the job twice
642 markedPuyo->setFlag();
643 removedPuyos.addElement(markedPuyo);
644 }
645 }
646 }
647
648
649 // If there is more than 4 puyo in the group, let's notify it
650 if (removedPuyos.getSize() >= 4) {
651 markPuyoAt(i, j, initialPuyoState, false);
652 if (delegate != NULL)
653 delegate->puyoWillVanish(removedPuyos, puyoGroupNumber++, phase);
654 }
655 else {
656 markPuyoAt(i, j, initialPuyoState, false);
657 }
658 }
659 }
660 }
661 }
662 }
663
cycleEnding()664 void PuyoGame::cycleEnding()
665 {
666 static int cmpt = 0;
667 int score = removePuyos();
668
669 if (score >= 4) {
670 #ifdef DESACTIVE
671 audio_sound_play(sound_splash[phase>7?7:phase]);
672 #endif
673 score -= 3;
674 if (phase > 0) {
675 neutralPuyos -= PUYODIMX;
676 }
677 phase++;
678 }
679
680 extern int gameLevel;
681 points += gameLevel * 100 + gameLevel * (phase>0?phase-1:0) * 5000;
682
683 neutralPuyos -= score;
684 if (score == 0)
685 setFallingAtTop();
686 }
687