1 //
2 // Cross-platform free Puyo-Puyo clone.
3 // Copyright (C) 2006, 2007 Emma's Software
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 #if !defined (AMOEBAX_GRID_H)
20 #define AMOEBAX_GRID_H
21 
22 #include <list>
23 #include <memory>
24 #include <set>
25 #include <stdint.h>
26 #include <vector>
27 #include "Amoeba.h"
28 #include "Sound.h"
29 
30 namespace Amoebax
31 {
32     // Forward declarations.
33     class Amoeba;
34     class ChainLabel;
35     class GridStatus;
36     class PairGenerator;
37 
38     ///
39     /// \class Grid
40     /// \brief An amoebas' grid for a single player.
41     ///
42     class Grid
43     {
44         public:
45             /// The first height (starting from above) that an amoeba is
46             /// visible.
47             static const uint16_t k_FirstVisibleHeight = 3;
48             /// The grid's height in amoebas.
49             static const uint16_t k_GridHeight = 12 + k_FirstVisibleHeight;
50             /// The grid's width in amoebas.
51             static const uint16_t k_GridWidth = 6;
52             /// The maximum number of silhouette frames.
53             static const uint16_t k_MaxSilhouetteFrames = 5;
54             /// The height that is visible to the user.
55             static const uint16_t k_VisibleHeight = k_GridHeight -
56                                                     k_FirstVisibleHeight;
57 
58             ///
59             /// \brief The grid's orientation.
60             ///
61             enum Layout
62             {
63                 /// The grid is horizontal.
64                 LayoutHorizontal,
65                 /// The grid is vertical.
66                 LayoutVertical
67             };
68 
69             ///
70             /// \brief The grid's side of the queue.
71             ///
72             enum QueueSide
73             {
74                 /// The queue is at grid's left.
75                 QueueSideLeft,
76                 /// The queue is at grid's right.
77                 QueueSideRight
78             };
79 
80             ///
81             /// \struct FallingAmoeba
82             /// \brief An amoeba that is floating in the grid.
83             ///
84             /// A falling amoeba is just an amoeba that lost its support
85             /// amoeba (i.e., the amoeba just below it died) and now must
86             /// fall. Both amoebas in the FallingPair are also falling amoebas.
87             ///
88             struct FallingAmoeba
89             {
90                 /// The falling amoeba.
91                 Amoeba *amoeba;
92                 /// The amoeba's X position in the grid.
93                 int16_t x;
94                 /// The amoeba's Y position in the grid.
95                 int16_t y;
96             };
97 
98             Grid (uint16_t gridPositionX, uint16_t gridPositionY,
99                   uint16_t queuePositionX, uint16_t queuePositionY,
100                   uint16_t waitingGhostPositionX,
101                   uint16_t waitingGhostPositionY, uint16_t amoebaSize,
102                   QueueSide queueSide, uint32_t score = 0,
103                   Layout layout = LayoutVertical);
104             ~Grid (void);
105 
106             void addNewPair (Amoeba *main, Amoeba *satellite);
107             const std::list<Amoeba *> &getActiveAmoebas (void) const;
108             const std::list<ChainLabel *> &getChainLabels (void) const;
109             uint16_t getGridPositionX (void) const;
110             uint16_t getGridPositionY (void) const;
111             FallingAmoeba getFallingMainAmoeba (void) const;
112             FallingAmoeba getFallingSatelliteAmoeba (void) const;
113             FallingAmoeba getFollowingFallingMainAmoeba (void) const;
114             FallingAmoeba getFollowingFallingSatelliteAmoeba (void) const;
115             FallingAmoeba getNextFallingMainAmoeba (void) const;
116             FallingAmoeba getNextFallingSatelliteAmoeba (void) const;
117             uint8_t getOpponentGhostAmoebas (void) const;
118             const std::list<Amoeba *> &getQueuedAmoebas (void) const;
119             uint16_t getQueuePositionX (void) const;
120             uint16_t getQueuePositionY (void) const;
121             uint32_t getScore (void) const;
122             int8_t getSilhouetteFrame (void) const;
123             GridStatus getState (void) const;
124             uint16_t getWaitingGhostPositionX (void) const;
125             uint16_t getWaitingGhostPositionY (void) const;
126             const std::vector<Amoeba *> &getWaitingGhostAmoebas (void) const;
127             bool hasNewFallingPair (void) const;
128             void incrementNumberOfWaitingGhosts (uint8_t amount = 1);
129             bool isFilled (void) const;
130             bool isQueueMoving (void) const;
131             void moveLeft (void);
132             void moveRight (void);
133             void rotateClockwise (void);
134             void rotateCounterClockwise (void);
135             void update (uint32_t elapsedTime);
136             void updateQueue (uint32_t elapsedTime);
137             void scheduleFallingPair (void);
138             void setGenerator (PairGenerator *generator);
139             void setMaxFallingSpeed (void);
140             void setNormalFallingSpeed (void);
141 
142         private:
143             /// Default blinking time (ms).
144             static const int32_t k_DefaultBlinkTime = 25;
145             /// Default dying time (ms).
146             static const int32_t k_DefaultDyingTime = 250;
147             /// Default falling time (ms).
148             static const int32_t k_DefaultFallingTime = 500;
149             /// The time required for the silhouette to be shown (ms.)
150             static const int32_t k_SilhouetteTime = 100;
151 
152             ///
153             /// \struct FallingPair
154             /// \brief A pair of amoebas falling and controlled by a player.
155             ///
156             /// This pair of the amoabes are the ones the player (either
157             /// a human player or an A.I. player) controls so can move
158             /// and rotate them around.
159             ///
160             struct FallingPair
161             {
162                 /// The main falling amoeba.
163                 FallingAmoeba main;
164                 /// The amoeba that can be rotated around the main amoeba.
165                 FallingAmoeba satellite;
166                 /// The time remaining before the pair falls an step.
167                 int32_t fallingTime;
168                 /// The offset of the amoebas in their respective grid position.
169                 int16_t verticalOffset;
170             };
171 
172             void addChainLabel (uint8_t stepChain, int16_t x, int16_t y);
173             void clearDyingAmoebas (void);
174             void findFloatingAmoebas (void);
175             Amoeba *getAmoebaAt (int16_t x, int16_t y) const;
176             uint16_t getAmoebaSize (void) const;
177             uint8_t getCurrentStepChain (void) const;
178             int16_t getCurrentRotationDegree (void) const;
179             Layout getLayout (void) const;
180             uint8_t getNumberOfWaitingGhosts (void) const;
181             void getNextPair (void);
182             QueueSide getQueueSide (void) const;
183             void incrementCurrentStepChain (uint8_t amount = 1);
184             void incrementScore (uint16_t amount = 1);
185             bool isOfSameColour (int16_t x, int16_t y, Amoeba *amoeba) const;
186             bool isSatelliteRotating (void) const;
187             void makeGhostsFall (void);
188             void makeGroup (std::vector<FallingAmoeba> &group,
189                             std::vector<FallingAmoeba> &ghosts,
190                             int16_t x, int16_t y,
191                             std::set<std::pair<int16_t, int16_t> > &visitedPositions,
192                             Amoeba::Colour colour = Amoeba::ColourNone,
193                             bool initialAmoeba = true);
194             void makeChain (void);
195             void markAsFilled (void);
196             void setAmoebaAt (int16_t x, int16_t y, Amoeba *amoeba);
197             void setAmoebaStateAt (int16_t x, int16_t y, bool neighbors = true);
198             void setCurrentStepChain (uint8_t stepChain);
199             void setFallingAmoebaScreenPosition (FallingAmoeba &fallingAmoeba,
200                                                  int16_t verticalOffset,
201                                                  bool rotating);
202             void setHasNewFallingPair (bool hasNewFallingPair);
203             void setNumberOfWaitingGhosts (uint8_t number);
204             void setOpponentGhostAmoebas (uint8_t ghostAmoebas);
205             void setScore (uint32_t score);
206             void setSilhouetteFrame (int8_t frame);
207             void setupFallingPair (void);
208             uint8_t removeGhostAmoebas (uint8_t newGhostAmoebas);
209             void rotateSatelliteAmoeba (float degreesToRotate);
210             void updateWaitingGhosts (void);
211 
212             /// The list of amoebas that are in the grid, not waiting.
213             std::list<Amoeba *> m_ActiveAmoebas;
214             /// The size (width and height are the same) of a single amoeba.
215             uint16_t m_AmoebaSize;
216             /// The time need to switch the blink of dying amoebas.
217             int32_t m_BlinkTime;
218             /// The list of chain labels.
219             std::list<ChainLabel *> m_ChainLabels;
220             /// The current chain step.
221             uint8_t m_CurrentStepChain;
222             /// The current satellite amoeba's rotation degrees.
223             float m_CurrentRotationDegrees;
224             /// The remaing degrees until the rotation is done.
225             float m_DegreesUntilRotationDone;
226             /// Dying sound.
227             std::auto_ptr<Sound> m_DieSound;
228             /// Dying amoebas.
229             std::vector<FallingAmoeba> m_DyingAmoebas;
230             /// Dying time.
231             int32_t m_DyingTime;
232             /// The falling pair
233             FallingPair m_FallingPair;
234             /// The grid is filled (i.e., the player lost.)
235             bool m_Filled;
236             /// Tells that we are just making fall the first pair.
237             bool m_FirstFallingPair;
238             /// The amoebas that have lost they lowe neighbor and are floating.
239             std::list<FallingAmoeba> m_FloatingAmoebas;
240             /// The verical offset of all floating amoebas.
241             int16_t m_FloatingAmoebasVerticalOffset;
242             /// This grid's amoebas pair generator.
243             PairGenerator *m_Generator;
244             /// The actual amoeba's grid.
245             std::vector<Amoeba *> m_Grid;
246             /// The X position of the top-left corner of the grid.
247             uint16_t m_GridPositionX;
248             /// The Y position of the top-left corner of the grid.
249             uint16_t m_GridPositionY;
250             /// Tells the if falling pair is new in this update or not.
251             bool m_HasNewFallingPair;
252             /// The list of amoebas that are waiting to be in play.
253             std::list<Amoeba *> m_InactiveAmoebas;
254             /// The grid's layout.
255             Layout m_Layout;
256             /// Tells if we are falling at max speed.
257             bool m_MaxFallingSpeed;
258             /// The number of ghost amoebas to send to the opponent.
259             uint8_t m_OpponentGhostAmoebas;
260             /// The queue, amoebas waiting to fall.
261             std::list<FallingPair> m_Queue;
262             /// The list of pointer to the amoebas in the queue.
263             std::list<Amoeba *> m_QueuedAmoebas;
264             /// Tells if the queue is moving.
265             bool m_QueueIsMoving;
266             /// The side of the queue.
267             QueueSide m_QueueSide;
268             /// The X position of the top-left corner of the wait queue.
269             uint16_t m_QueuePositionX;
270             /// The Y position of the top-left corner of the wait queue.
271             uint16_t m_QueuePositionY;
272             /// The remaining horizontal offset to move the queued amoebas.
273             uint16_t m_RemainingQueueHorizontalOffset;
274             /// The remaining vertical offset to move the queued amoebas.
275             uint16_t m_RemainingQueueVerticalOffset;
276             /// The direction (clockwise or anti-clockwise) of the satellite rotation.
277             float m_RotationDirection;
278             /// The current player's score.
279             uint32_t m_Score;
280             /// The current silhouette frame.
281             int8_t m_SilhouetteFrame;
282             /// The silhouette frame direction, up or down.
283             int8_t m_SilhouetteFrameDirection;
284             /// The time required for the silhouette to change.
285             int32_t m_SilhouetteTime;
286             /// Tell if we are waiting for the initial 3 pairs.
287             bool m_WaitingInitialAmoebas;
288             /// The ghost amoebas waiting to fall to the grid.
289             std::vector<Amoeba *> m_WaitingGhostAmoebas;
290             /// The number of ghost amoebas waiting. Max. is 30.
291             uint8_t m_WaitingGhostAmoebasNumber;
292             /// The X position of where the ghost amoebas wait.
293             uint16_t m_WaitingGhostPositionX;
294             /// The Y position of where the ghost amoebas wait.
295             uint16_t m_WaitingGhostPositionY;
296     };
297 
298     ///
299     /// \brief Gets the list of the active amoebas.
300     ///
301     /// The active amoebas are those amoebas that are currently
302     /// on the game field. They are the alredy fallen amoebas and the
303     /// falling pair. The two pairs waiting to fall are not active, are
304     /// queued. \see getQueuedAmoebas() for more information.
305     ///
306     /// \return The list of amoebas that are active.
307     ///
308     inline const std::list<Amoeba *> &
getActiveAmoebas(void)309     Grid::getActiveAmoebas (void) const
310     {
311         return m_ActiveAmoebas;
312     }
313 
314     ///
315     /// \brief Gets the amoeba's size.
316     ///
317     /// \return The size (both height and width, as they are equal) of the
318     ///         amoebas.
319     ///
320     inline uint16_t
getAmoebaSize(void)321     Grid::getAmoebaSize (void) const
322     {
323         return m_AmoebaSize;
324     }
325 
326     ///
327     /// \brief Gets the list of chain labels.
328     ///
329     /// \return The list of chain labels to show to the user.
330     ///
331     inline const std::list<ChainLabel *> &
getChainLabels(void)332     Grid::getChainLabels (void) const
333     {
334         return m_ChainLabels;
335     }
336 
337     ///
338     /// \brief Gets the current step chain.
339     ///
340     /// \return The current step chain value, starting from 0.
341     ///
342     inline uint8_t
getCurrentStepChain(void)343     Grid::getCurrentStepChain (void) const
344     {
345         return m_CurrentStepChain;
346     }
347 
348     ///
349     /// \brief Gets the grid's top-left corner X position.
350     ///
351     /// \return The X position of grid's top-left corner.
352     ///
353     inline uint16_t
getGridPositionX(void)354     Grid::getGridPositionX (void) const
355     {
356         return m_GridPositionX;
357     }
358 
359     ///
360     /// \brief Gets the grid's top-left corner Y position.
361     ///
362     /// \return The Y position of grid's top-left corner.
363     ///
364     inline uint16_t
getGridPositionY(void)365     Grid::getGridPositionY (void) const
366     {
367         return m_GridPositionY;
368     }
369 
370     ///
371     /// \brief Gets the layout.
372     ///
373     /// \return the current grid layout.
374     ///
375     inline Grid::Layout
getLayout(void)376     Grid::getLayout (void) const
377     {
378         return m_Layout;
379     }
380 
381     ///
382     /// \brief Gets the number of waiting ghosts.
383     ///
384     /// \return The number of ghosts amoebas that are waiting to fall into
385     ///         the grid.
386     ///
387     inline uint8_t
getNumberOfWaitingGhosts(void)388     Grid::getNumberOfWaitingGhosts (void) const
389     {
390         return m_WaitingGhostAmoebasNumber;
391     }
392 
393     ///
394     /// \brief Gets the number of ghost amoebas to send to the opponent.
395     ///
396     /// \return The number of ghost amoebas for the opponent.
397     ///
398     inline uint8_t
getOpponentGhostAmoebas(void)399     Grid::getOpponentGhostAmoebas (void) const
400     {
401         return m_OpponentGhostAmoebas;
402     }
403 
404     ///
405     /// \brief Gets the list of the queued amoebas.
406     ///
407     /// The active amoebas are the two pairs of amoebas waiting to fall.
408     ///
409     /// \return The list of amoebas that are active.
410     ///
411     inline const std::list<Amoeba *> &
getQueuedAmoebas(void)412     Grid::getQueuedAmoebas (void) const
413     {
414         return m_QueuedAmoebas;
415     }
416 
417 
418     ///
419     /// \brief Gets the current player's score.
420     ///
421     /// \return The current player's score.
422     ///
423     inline uint32_t
getScore(void)424     Grid::getScore (void) const
425     {
426         return m_Score;
427     }
428 
429     ///
430     /// \brief Gets the current sihouette frame.
431     ///
432     /// \return The current silhouette frame.
433     ///
434     inline int8_t
getSilhouetteFrame(void)435     Grid::getSilhouetteFrame (void) const
436     {
437         return m_SilhouetteFrame;
438     }
439 
440     ///
441     /// \brief Gets the list of the waiting ghost amoebas.
442     ///
443     /// The list of waiting amoebas is just 6 amoebas, but each amoeba's
444     /// neighbour state indicates how many ghost amoebas will fall. The
445     /// maximum number of ghost to fall for each one is 5, hence the
446     /// maximum ghosts to fall is 30.
447     ///
448     /// \return The vector of 6 ghost amoebas with it's "weight" state.
449     ///
450     inline const std::vector<Amoeba *> &
getWaitingGhostAmoebas(void)451     Grid::getWaitingGhostAmoebas (void) const
452     {
453         return m_WaitingGhostAmoebas;
454     }
455 
456     ///
457     /// \brief Tells if the falling pair is new.
458     ///
459     /// A falling pair is new when at the last call to update()
460     /// the previous falling pair felt and there was not floating amoebas.
461     /// Of course, every time a new falling pair starts to fall, this
462     /// function returns \a true.
463     ///
464     /// \return \a true if at the previous call to update() a new pair
465     ///         started to fall, \a false otherwise.
466     ///
467     inline bool
hasNewFallingPair(void)468     Grid::hasNewFallingPair (void) const
469     {
470         return m_HasNewFallingPair;
471     }
472 
473     ///
474     /// \brief Increments the current step chain.
475     ///
476     /// \param amount The amount to increment the current step chain.
477     ///
478     inline void
incrementCurrentStepChain(uint8_t amount)479     Grid::incrementCurrentStepChain (uint8_t amount)
480     {
481         setCurrentStepChain (getCurrentStepChain () + amount);
482     }
483 
484     ///
485     /// \brief Increments the current score.
486     ///
487     /// \param amount The amount increments the score.
488     ///
489     inline void
incrementScore(uint16_t amount)490     Grid::incrementScore (uint16_t amount)
491     {
492         setScore (getScore () + amount);
493     }
494 
495     ///
496     /// \brief Tells if the grid is filled.
497     ///
498     /// The grid is considered filled when the falling pair can't
499     /// fall because the grid's position (3, 0) has a non-floating
500     /// amoeba (i.e., the falling amoebas can't fall inside the
501     /// grid.)
502     ///
503     /// When the grid is filled, the game is over and the player
504     /// lost.
505     ///
506     /// \return \a true if the grid is filled, \a false otherwise.
507     ///
508     inline bool
isFilled(void)509     Grid::isFilled (void) const
510     {
511         return m_Filled;
512     }
513 
514     ///
515     /// \brief Sets the current step chain.
516     ///
517     /// \param stepChain The new step chain to set.
518     ///
519     inline void
setCurrentStepChain(uint8_t stepChain)520     Grid::setCurrentStepChain (uint8_t stepChain)
521     {
522         m_CurrentStepChain = stepChain;
523     }
524 
525     ///
526     /// \brief Sets the number of waiting ghosts.
527     ///
528     /// \param number The new number of ghosts amoebas that are waiting
529     ///               to fall into the grid. It can't be greater than 30,
530     ///               if it's then it gets clapped.
531     ///
532     inline void
setNumberOfWaitingGhosts(uint8_t number)533     Grid::setNumberOfWaitingGhosts (uint8_t number)
534     {
535         if ( number > 30 )
536         {
537             m_WaitingGhostAmoebasNumber = 30;
538         }
539         else
540         {
541             m_WaitingGhostAmoebasNumber = number;
542         }
543     }
544 
545     ///
546     /// \brief Sets the number of amoebas to send to the opponent grid.
547     ///
548     /// \param ghostAmoebas The number of ghost amoebas to send.
549     ///
550     inline void
setOpponentGhostAmoebas(uint8_t ghostAmoebas)551     Grid::setOpponentGhostAmoebas (uint8_t ghostAmoebas)
552     {
553         m_OpponentGhostAmoebas = ghostAmoebas;
554     }
555 
556     ///
557     /// \brief Sets the score of the grid.
558     ///
559     /// \param score  The new score value.
560     ///
561     inline void
setScore(uint32_t score)562     Grid::setScore (uint32_t score)
563     {
564         m_Score = score;
565     }
566 
567 }
568 
569 #endif // !AMOEBAX_GRID_H
570