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