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