/* =========================================================================== blockattack - Block Attack - Rise of the Blocks Copyright (C) 2005-2012 Poul Sander This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ Source information and contacts persons can be found at http://www.blockattack.net =========================================================================== */ #ifndef BLOCKGAME_HPP #define BLOCKGAME_HPP 1 #include "stats.h" #include "common.h" #define NUMBEROFCHAINS 100 #define BLOCKWAIT 100000 #define BLOCKHANG 1000 enum stageButton {SBdontShow, SBstageClear, SBpuzzleMode}; extern stageButton stageButtonStatus; //This is the size of the blocks. They are always 50. The internal logic calculates it that way const int bsize = 50; /** * This struct defines the start conditions of the game */ struct BlockGameStartInfo { unsigned int ticks = 0; bool timeTrial = false; ///True means a stage clear game will be started. level must be set too. bool stageClear = false; ///True if puzzle mode. level must be set too. bool puzzleMode = false; ///Single puzzle is used for the editor only. bool singlePuzzle = false; int level = 0; bool AI = false; /** * True means that stats will be recorded. * If AI is true then this will be overruled to false */ bool recordStats = true; bool vsMode = false; /** * Set to true if we are fighting an AI. level should be the AI level we are fighting */ bool vsAI = false; int startBlocks = -1; int handicap = 0; int gameSpeed = 0; }; struct GarbageStruct { bool greyGarbage = false; int width = 0; int height = 0; void setGarbage(int w, int h, bool g = false) { greyGarbage = g; width = w; height = h; } }; //////////////////////////////////////////////////////////////////////////////// //The BloackGame class represents a board, score, time etc. for a single player/ //////////////////////////////////////////////////////////////////////////////// class BlockGame { private: int prevTowerHeight; bool bGarbageFallLeft; bool singlePuzzle = false; int nextGarbageNumber; int pushedPixelAt; int nrPushedPixel, nrFellDown; unsigned int nrStops; bool garbageToBeCleared[7][30]; unsigned int lastAImove; int AI_LineOffset; //how many lines have changed since command int hangTicks; //How many times have hang been decreased? //int the two following index 0 may NOT be used (what the fuck did I meen?) int chainSize[NUMBEROFCHAINS]; //Contains the chains bool chainUsed[NUMBEROFCHAINS]; //True if the chain is used unsigned int nextRandomNumber; int Level; //Only used in stageClear and puzzle (not implemented) int rand2(); int firstUnusedChain(); //public: protected: int lastCounter; std::string strHolder; bool bDraw; unsigned int ticks; unsigned int gameStartedAt; unsigned int gameEndedAfter; //How long did the game last? int linesCleared; int TowerHeight; BlockGame *garbageTarget; int board[7][30]; int stop; int speedLevel; int pixels; int MovesLeft; bool timetrial, stageClear, vsMode, puzzleMode; int stageClearLimit; //stores number of lines user must clear to win int combo; int chain; int cursorx; //stores cursor position int cursory; // -||- double speed, baseSpeed; //factor for speed. Lower value = faster gameplay int score; bool bGameOver; bool hasWonTheGame; int AI_MoveSpeed; //How often will the computer move? milliseconds bool AI_Enabled; bool recordStats = true; bool vsAI = false; //Set to true for single player vs int handicap; std::vector garbageSendQueue; int AIlineToClear; short AIstatus; //Status flags: //0: nothing, 2: clear tower, 3: clear horisontal, 4: clear vertical //1: make more lines, 5: make 2 lines, 6: make 1 line public: std::string name; public: BlockGame(); virtual ~BlockGame(); int getAIlevel() const; virtual void AddText(int x, int y, const std::string& text, int time) const {} virtual void AddBall(int x, int y, bool right, int color) const {} virtual void AddExplosion(int x, int y) const {} virtual void PlayerWonEvent() const {} virtual void DrawEvent() const {} virtual void BlockPopEvent() const {} virtual void LongChainDoneEvent() const {} virtual void TimeTrialEndEvent() const {} virtual void EndlessHighscoreEvent() const {} int GetScore() const; int GetHandicap() const; bool isGameOver() const; int GetGameStartedAt() const; int GetGameEndedAt() const; bool isTimeTrial() const; bool isStageClear() const; bool isVsMode() const; bool isPuzzleMode() const; int GetLinesCleared() const; int GetStageClearLimit() const; int GetChains() const; int GetPixels() const; int GetSpeedLevel() const; int GetTowerHeight() const; int GetCursorX() const; int GetCursorY() const; void MoveCursorTo(int x, int y); bool GetIsWinner() const; bool isSinglePuzzle() const; int getLevel() const; bool GetAIenabled() const; bool IsNearDeath() const; void NewGame(const BlockGameStartInfo &s); //Creates garbage using a given wide and height bool CreateGarbage(int wide, int height); //Creates garbage using a given wide and height bool CreateGreyGarbage(); void PopSendGarbage(std::vector& poppedData); //prints "Game Over" and ends game void SetGameOver(); //Moves the cursor, receaves N,S,E or W as a char an moves as desired void MoveCursor(char way); //switches the two blocks at the cursor position, unless game over void SwitchAtCursor(); //Generates a new line and moves the field one block up (restart puzzle mode) void PushLine(); void Update(unsigned int newtick); //Prints "winner" and ends game void setPlayerWon(); //Prints "draw" and ends the game void setDraw(); void setGarbageTarget(BlockGame* garbageTarget); BlockGame* getGarbageTarget() const; private: void NewGame(unsigned int ticks); //Test if LineNr is an empty line, returns false otherwise. bool LineEmpty(int lineNr) const; //Test if the entire board is empty (used for Puzzles) bool BoardEmpty() const; //Anything that the user can't move? In that case Game Over cannot occur bool hasStaticContent() const; void putStartBlocks(); void putStartBlocks(int n); //decreases hang for all hanging blocks and wait for waiting blocks void ReduceStuff(); void setGameSpeed(int globalSpeedLevel); void setHandicap(int globalHandicap); //Clears garbage, must take one the lower left corner! int GarbageClearer(int x, int y, int number, bool aLineToClear, int chain); //Marks garbage that must be cleared int GarbageMarker(int x, int y); int FirstGarbageMarker(int x, int y); //Clear Blocks if 3 or more is alligned (naive implemented) void ClearBlocks(); //Moves all peaces a spot down if possible int FallBlock(int x, int y, int number); //Makes all Garbage fall one spot void GarbageFall(); //Makes the blocks fall (it doesn't test time, this must be done before hand) void FallDown(); //Pushes a single pixel, so it appears to scrool void PushPixels(); //See how high the tower is, saved in integer TowerHeight void FindTowerHeight(); /////////////////////////////////////////////////////////////////////////// /////////////////////////// AI starts here! /////////////////////////////// /////////////////////////////////////////////////////////////////////////// //First the helpet functions: int nrOfType(int line, int type); int AIcolorToClear; //See if a combo can be made in this line int horiInLine(int line); bool horiClearPossible(); //the Line Has Unmoveable Objects witch might stall the AI bool lineHasGarbage(int line); //Types 0..6 in line int nrOfRealTypes(int line); //See if there is a tower bool ThereIsATower(); double firstInLine1(int line); //returns the first coordinate of the block of type double firstInLine(int line, int type); //There in the line shall we move int closestTo(int line, int place); //The AI will remove a tower void AI_ClearTower(); //The AI will try to clear block horisontally void AI_ClearHori(); //Test if vertical clear is possible bool veriClearPossible(); //There in the line shall we move int closestTo(int line, int type, int place); //The AI will try to clear blocks vertically void AI_ClearVertical(); bool firstLineCreated; void AI_Move(); ////////////////////////////////////////////////////////////////////////// ///////////////////////////// AI ends here! ////////////////////////////// //////// ////////////////////////////////////////////////////////////////// //Set the move speed of the AI based on the aiLevel parameter void setAIlevel(int aiLevel); void PushLineInternal(); //Updates evrything, if not called nothing happends void Update(); void UpdateInternal(unsigned int newtick); }; //Play the next level void nextLevel(BlockGame& g, unsigned int ticks); //Replay the current level void retryLevel(BlockGame& g, unsigned int ticks); #endif