git repos / blockattack-game

commit 17916a2e

sago007 · 2010-11-07 11:26
17916a2e8cbfe9f7b0702d1835ab882d8e8dd967 patch · browse files
parent e1290bdf1707fc381f312b67f4654c3783ef1ba9

Stated to seperate BlockGame


git-svn-id: https://blockattack.svn.sourceforge.net/svnroot/blockattack/trunk@100 9d7177f8-192b-0410-8f35-a16a89829b06

Changed files

A source/code/BlockGame.cpp
M source/code/BlockGame.hpp before
M source/code/block.make before
M source/code/main.cpp before
M source/code/mainVars.hpp before
M source/code/replay.h before
diff --git a/source/code/BlockGame.cpp b/source/code/BlockGame.cpp new file mode 100644 index 0000000..62dfc00 --- /dev/null +++ b/source/code/BlockGame.cpp
@@ -0,0 +1,2361 @@
+/*
+ * BlockGame.hpp (this was cut from main.cpp for the overview)
+ * Copyright (C) 2005 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Poul Sander
+ * R�veh�jvej 36, V. 1111
+ * 2800 Kgs. Lyngby
+ * DENMARK
+ * blockattack@poulsander.com
+ */
+
+#include "BlockGame.hpp"
+
+
+////////////////////////////////////////////////////////////////////////////////
+//The BloackGame class represents a board, score, time etc. for a single player/
+////////////////////////////////////////////////////////////////////////////////
+ Uint16 BlockGame::rand2() {
+ nextRandomNumber = nextRandomNumber*1103515245 + 12345;
+ return ((Uint16)(nextRandomNumber/65536)) % 32768;
+ }
+
+ int BlockGame::firstUnusedChain() {
+ bool found=false;
+ int i = 0;
+ while (!found) {
+ if (!chainUsed[++i])
+ found=true;
+ if (i>NUMBEROFCHAINS-2)
+ found=true;
+ }
+ return i;
+ }
+
+ //Constructor
+ BlockGame::BlockGame(int tx, int ty) {
+ #if WITH_SDL
+ tmp = IMG_Load2((char*)"gfx/BackBoard.png");
+ sBoard = SDL_DisplayFormat(tmp);
+ SDL_FreeSurface(tmp);
+ #endif
+ srand((int)time(NULL));
+ nrFellDown = 0;
+ nrPushedPixel = 0;
+ garbageTarget = this;
+ nrStops=0;
+ topx = tx;
+ topy = ty;
+ cursorx = 2;
+ cursory = 3;
+ stop = 0;
+ pixels = 0;
+ score = 0;
+ bGameOver = false;
+ bDraw = false;
+ bReplaying=false; //No replay by default
+ #if NETWORK
+ bDisconnected=false;
+ bNetworkPlayer = false;
+ #endif
+ timetrial = false;
+ stageClear = false;
+ vsMode = false;
+ puzzleMode = false;
+ linesCleared = 0;
+ AI_Enabled = false;
+ AI_MoveSpeed=100;
+ hasWonTheGame = false;
+ combo=0; //counts
+ chain=0;
+ hangTicks = 0;
+ baseSpeed = 0.5; //All other speeds are relative to this
+ speed = baseSpeed;
+ speedLevel = 1;
+ gameStartedAt = ticks;
+ gameEndedAfter = 0;
+ pushedPixelAt = gameStartedAt;
+ nextGarbageNumber = 10;
+ handicap=0;
+ for (int i=0;i<7;i++)
+ for (int j=0;j<30;j++) {
+ board[i][j] = -1;
+ }
+ for (int i=0;i<NUMBEROFCHAINS;i++) {
+ chainUsed[i]=false;
+ chainSize[i] = 0;
+ }
+ theReplay = Replay();
+ showGame = true; //The game is now active
+ lastCounter = -1; //To prevent the final chunk to be played when stating the program
+ } //Constructor
+
+ //Deconstructor, never really used... game used to crash when called, cause of the way sBoard was created
+ //It should work now and can be used if we want to assign more players in network games that we need to free later
+ BlockGame::~BlockGame() {
+ #if WITH_SDL
+ SDL_FreeSurface(sBoard);
+ #endif
+ }
+
+ void BlockGame::setGameSpeed(Uint8 globalSpeedLevel) {
+ switch (globalSpeedLevel) {
+ case 0:
+ baseSpeed=0.5;
+ break;
+ case 1:
+ baseSpeed=0.4;
+ break;
+ case 2:
+ baseSpeed=0.3;
+ break;
+ case 3:
+ baseSpeed=0.25;
+ break;
+ case 4:
+ baseSpeed=0.2;
+ break;
+ default:
+ baseSpeed=0.15;
+ break;
+ };
+ }
+
+ void BlockGame::setHandicap(Uint8 globalHandicap) {
+ handicap=1000*((Uint32)globalHandicap);
+ }
+
+ //Set the move speed of the AI based on the aiLevel parameter
+ //Also enables AI
+ void BlockGame::setAIlevel(Uint8 aiLevel) {
+ AI_Enabled = true;
+ AI_MoveSpeed=120-(20*(aiLevel-3));
+ };
+
+ Uint8 BlockGame::getAIlevel() {
+ return (120-AI_MoveSpeed)/20+3;
+ }
+
+ int BlockGame::GetScore() {
+ return score;
+ }
+
+ int BlockGame::GetHandicap() {
+ return handicap;
+ }
+
+ bool BlockGame::isGameOver() {
+ return bGameOver;
+ }
+
+ int BlockGame::GetTopX() {
+ return topx;
+ }
+
+ int BlockGame::GetTopY() {
+ return topy;
+ }
+
+ unsigned int BlockGame::GetGameStartedAt() {
+ return gameStartedAt;
+ }
+
+ unsigned int BlockGame::GetGameEndedAt() {
+ return gameEndedAfter;
+ }
+
+ bool BlockGame::isTimeTrial() {
+ return timetrial;
+ }
+
+ bool BlockGame::isStageClear() {
+ return stageClear;
+ }
+
+ bool BlockGame::isVsMode() {
+ return vsMode;
+ }
+
+ bool BlockGame::isPuzzleMode() {
+ return puzzleMode;
+ }
+
+ int BlockGame::GetLinesCleared() {
+ return linesCleared;
+ }
+
+ int BlockGame::GetStageClearLimit() {
+ return stageClearLimit;
+ }
+
+ int BlockGame::GetChains() {
+ return chain;
+ }
+
+ int BlockGame::GetPixels() {
+ return pixels;
+ }
+
+ int BlockGame::GetSpeedLevel() {
+ return speedLevel;
+ }
+
+ int BlockGame::GetTowerHeight() {
+ return TowerHeight;
+ }
+
+ int BlockGame::GetCursorX() {
+ return cursorx;
+ }
+
+ int BlockGame::GetCursorY() {
+ return cursory;
+ }
+
+ void BlockGame::MoveCursorTo(int x, int y) {
+ cursorx = x;
+ cursory = y;
+ }
+
+ bool BlockGame::GetIsWinner() {
+ return hasWonTheGame;
+ }
+
+#if NETWORK
+#define garbageStackSize 10
+
+ void BlockGame::emptyGarbageStack() {
+ for (int i=0;i<10;i++)
+ for (int j=0;j<3;j++)
+ garbageStack[i][j] = 0;
+ garbageStackUsed = 0;
+ }
+
+ bool BlockGame::pushGarbage(Uint8 width, Uint8 height, Uint8 type) {
+ if (garbageStackUsed>=garbageStackSize)
+ return false;
+ garbageStack[garbageStackUsed][0]=width;
+ garbageStack[garbageStackUsed][1]=height;
+ garbageStack[garbageStackUsed][2]=type;
+ garbageStackUsed++;
+ return true;
+ }
+
+ bool BlockGame::popGarbage(Uint8 *width, Uint8 *height, Uint8 *type) {
+ if (garbageStackUsed<1)
+ return false;
+ garbageStackUsed--;
+ *width=garbageStack[garbageStackUsed][0];
+ *height=garbageStack[garbageStackUsed][1];
+ *type=garbageStack[garbageStackUsed][2];
+ return true;
+ }
+
+#endif
+
+ #if WITH_SDL
+ //Loads BackBoard again if surface format has changed
+ void BlockGame::convertSurface() {
+ SDL_FreeSurface(sBoard);
+ sBoard = SDL_DisplayFormat(backBoard);
+ }
+ #endif
+
+ //Instead of creating new object new game is called, to prevent memory leaks
+ void BlockGame::NewGame(int tx, int ty, unsigned int ticks) {
+ this->ticks = ticks;
+ stageButtonStatus = SBdontShow;
+ bReplaying = false;
+ #if NETWORK
+ bNetworkPlayer=false;
+ bDisconnected =false;
+ #endif
+ nrFellDown = 0;
+ lastNrOfPlayers = 1; //At least one player :-)
+ nrPushedPixel = 0;
+ nrStops = 0;
+ topx = tx;
+ topy = ty;
+ cursorx = 2;
+ cursory = 3;
+ stop = 0;
+ pixels = 0;
+ score = 0;
+ bGameOver = false;
+ bDraw = false;
+ timetrial = false;
+ stageClear = false;
+ linesCleared = 0;
+ hasWonTheGame = false;
+ vsMode = false;
+ puzzleMode = false;
+ combo=0;
+ chain=0;
+ AI_Enabled = false;
+ baseSpeed= 0.5;
+ speed = baseSpeed;
+ speedLevel = 1;
+ gameStartedAt = ticks+3000;
+ pushedPixelAt = gameStartedAt;
+ nextGarbageNumber = 10;
+ handicap=0;
+ for (int i=0;i<7;i++)
+ for (int j=0;j<30;j++) {
+ board[i][j] = -1;
+ }
+ for (int i=0;i<NUMBEROFCHAINS;i++) {
+ chainUsed[i]=false;
+ chainSize[i] = 0;
+ }
+ lastAImove = ticks+3000;
+ showGame = true;
+ theReplay = Replay();
+ } //NewGame
+
+ void BlockGame::NewTimeTrialGame(int x,int y, unsigned int ticks) {
+ NewGame(x,y,ticks);
+ timetrial = true;
+ putStartBlocks();
+ }
+
+ //Starts a new stage game, takes level as input!
+ void BlockGame::NewStageGame(int level, int tx, int ty,unsigned int ticks) {
+ if (level > -1) {
+ NewGame(tx, ty,ticks);
+ stageClear = true;
+ Level = level;
+ Stats::getInstance()->addOne("PlayedStageLevel"+itoa2(level));
+ stageClearLimit = 30+(Level%6)*10;
+ baseSpeed = 0.5/((double)(Level*0.5)+1.0);
+ speed = baseSpeed;
+ }
+ }
+
+ void BlockGame::NewPuzzleGame(int level, int tx, int ty, unsigned int ticks) {
+ if (level>-1) {
+ NewGame(tx, ty,ticks);
+ puzzleMode = true;
+ Level = level;
+ MovesLeft = nrOfMovesAllowed[Level];
+ for (int i=0;i<6;i++)
+ for (int j=0;j<12;j++) {
+ board[i][j+1] = puzzleLevels[Level][i][j];
+ }
+ baseSpeed = 100000;
+ speed = 100000;
+
+ //Now push the blines up
+ for (int i=19;i>0;i--)
+ for (int j=0;j<6;j++) {
+ board[j][i] = board[j][i-1];
+ }
+ for (int j=0;j<6;j++) {
+ board[j][0] = rand() % 6;
+ if (j > 0) {
+ if (board[j][0] == board[j-1][0])
+ board[j][0] = rand() % 6;
+ }
+ if (board[j][0] == board[j][1])
+ board[j][0] = 6;
+ if (board[j][0] == board[j][1])
+ board[j][0] = 6;
+
+ }
+ }
+ }
+
+ //Replay the current level
+ void BlockGame::retryLevel(unsigned int ticks)
+ {
+ if(puzzleMode)
+ NewPuzzleGame(Level,topx,topy,ticks);
+ else
+ if(stageClear)
+ NewStageGame(Level,topx,topy,ticks);
+ }
+
+ //Play the next level
+ void BlockGame::nextLevel(unsigned int ticks)
+ {
+ if(puzzleMode)
+ {
+ if(Level<nrOfPuzzles-1)
+ NewPuzzleGame(Level+1,topx,topy,ticks);
+ }
+ else
+ if(stageClear)
+ {
+ if(Level<50-1)
+ NewStageGame(Level+1,topx,topy,ticks);
+ }
+ }
+
+ //Starts new Vs Game (two Player)
+ void BlockGame::NewVsGame(int tx, int ty, BlockGame *target,unsigned int ticks) {
+ NewGame(tx, ty,ticks);
+ vsMode = true;
+ putStartBlocks();
+ garbageTarget = target;
+ Stats::getInstance()->addOne("VSgamesStarted");
+ }
+
+ //Starts new Vs Game (two Player)
+ void BlockGame::NewVsGame(int tx, int ty, BlockGame *target, bool AI,unsigned int ticks) {
+ NewGame(tx, ty,ticks);
+ vsMode = true;
+ AI_Enabled = AI;
+ if(!AI)
+ Stats::getInstance()->addOne("VSgamesStarted");
+ else
+ strcpy(name,"CPU\0");
+ putStartBlocks();
+ garbageTarget = target;
+ }
+ //Go in Demonstration mode, no movement
+ void BlockGame::Demonstration(bool toggle) {
+ speed=0;
+ baseSpeed = 0;
+ }
+ //We want to play the replay (must have been loaded beforehand)
+ void BlockGame::playReplay(int tx, int ty, unsigned int ticks) {
+ NewGame(tx, ty,ticks);
+ gameStartedAt = ticks;
+ bReplaying = true; //We are playing, no calculations
+ #if NETWORK
+ bNetworkPlayer = false; //Take input from replay file
+ #endif
+ }
+
+
+#if NETWORK
+
+ //network play
+ void BlockGame::playNetwork(int tx, int ty,unsigned int ticks) {
+ NewGame(tx, ty,ticks);
+ gameStartedAt = ticks;
+ bReplaying = false; //We are playing, no calculations
+ bNetworkPlayer = true; //Don't Take input from replay file
+ emptyGarbageStack();
+ }
+#endif
+
+ //Prints "winner" and ends game
+ void BlockGame::setPlayerWon() {
+ if (!bGameOver)
+ {
+ gameEndedAfter = ticks-gameStartedAt; //We game ends now!
+ if(!AI_Enabled && !bReplaying)
+ {
+ TimeHandler::addTime("playTime",TimeHandler::ms2ct(gameEndedAfter));
+ }
+ }
+ theReplay.setFinalFrame(getPackage(), 1);
+ bGameOver = true;
+ hasWonTheGame = true;
+ showGame = false;
+ if (SoundEnabled)Mix_PlayChannel(1, applause, 0);
+ if(!AI_Enabled && !bReplaying)
+ {
+ Stats::getInstance()->addOne("totalWins");
+ if(garbageTarget->AI_Enabled && !(garbageTarget->bReplaying))
+ {
+ //We have defeated an AI
+ Stats::getInstance()->addOne("defeatedAI"+itoa(garbageTarget->getAIlevel()));
+ }
+ }
+ if(AI_Enabled && !(garbageTarget->AI_Enabled) && garbageTarget->bReplaying==false)
+ {
+ //The AI have defeated a human player
+ Stats::getInstance()->addOne("defeatedByAI"+itoa(getAIlevel()));
+ }
+ }
+
+ //void SetGameOver();
+
+ #if NETWORK
+ //Sets disconnected:
+ void BlockGame::setDisconnect() {
+ bDisconnected = true;
+ SetGameOver();
+ }
+ #endif
+
+ //Prints "draw" and ends the game
+ void BlockGame::setDraw() {
+ bGameOver = true;
+ if(!AI_Enabled && !bReplaying)
+ {
+ TimeHandler::addTime("playTime",TimeHandler::ms2ct(gameEndedAfter));
+ }
+ theReplay.setFinalFrame(getPackage(), 3);
+ hasWonTheGame = false;
+ bDraw = true;
+ showGame = false;
+ Mix_HaltChannel(1);
+ if(!AI_Enabled && !bReplaying)
+ Stats::getInstance()->addOne("totalDraws");
+ }
+
+ //Function to get a boardpackage
+ boardPackage BlockGame::getPackage() {
+ boardPackage bp;
+ if(ticks<gameStartedAt)
+ bp.time = 0;
+ else
+ bp.time = (Uint32)(ticks-gameStartedAt);
+ for (int i=0;i<6;i++)
+ for (int j=0;j<13;j++) {
+ if (board[i][j]%10<7)
+ bp.brick[i][j]=board[i][j]%10+1;
+ if ((board[i][j]/1000000)%10==1)
+ {
+ //Ordinary garbage
+ int aInt=0; //N=1, S=2, W=4, E=8
+ if (i==0)
+ aInt+=4;
+ else
+ if ((board[i-1][j])!=(board[i][j]))
+ aInt+=4;
+ if (i==5)
+ aInt+=8;
+ else
+ if ((board[i+1][j])!=(board[i][j]))
+ aInt+=8;
+ if (j==0)
+ aInt+=2;
+ else
+ if ((board[i][j-1])!=(board[i][j]))
+ aInt+=2;
+ if ((board[i][j+1])!=(board[i][j]))
+ aInt+=1;
+ switch (aInt) {
+ case 8:
+ bp.brick[i][j]=8;
+ break;
+ case 7:
+ bp.brick[i][j]=10;
+ break;
+ case 11:
+ bp.brick[i][j]=11;
+ break;
+ case 9:
+ bp.brick[i][j]=12;
+ break;
+ case 5:
+ bp.brick[i][j]=13;
+ break;
+ case 6:
+ bp.brick[i][j]=14;
+ break;
+ case 10:
+ bp.brick[i][j]=15;
+ break;
+ case 3: //M
+ bp.brick[i][j]=16;
+ break;
+ case 0:
+ bp.brick[i][j]=17;
+ break;
+ case 1:
+ bp.brick[i][j]=18;
+ break;
+ case 2:
+ bp.brick[i][j]=19;
+ break;
+ case 4:
+ bp.brick[i][j]=20;
+ break;
+ default:
+ bp.brick[i][j]=0;
+ };
+ //cout << "garbage added to replay: " << aInt << endl;
+ }
+ if ((board[i][j]/1000000)%10==2)
+ {
+ //Gray garbage
+ bp.brick[i][j]=21;
+ }
+ if ((board[i][j]/BLOCKHANG)%10==1) //If "get ready"
+ bp.brick[i][j]+=30;
+ }
+ bp.cursorX = (Uint8)cursorx;
+ bp.cursorY = (Uint8)cursory;
+ bp.score = (Uint32)score;
+ bp.pixels = (Uint8)pixels;
+ bp.chain = (Uint8)chain;
+ bp.speed = (Uint8)speedLevel;
+ Uint8 result = 0;
+ if (bGameOver)
+ result+=1;
+ if (hasWonTheGame)
+ result+=2;
+ if (bDraw)
+ result+=4;
+ bp.result = (Uint8)result;
+ return bp;
+ }
+
+ //Takes a package and sets the board like it
+ void BlockGame::setBoard(boardPackage bp) {
+ //gameStartedAt = ticks-bp.time;
+ for (int i=0;i<6;i++)
+ for (int j=0;j<13;j++) {
+ //if(bp.brick[i][j]/8==0)
+ board[i][j]=bp.brick[i][j]-1;
+ //else
+ // board[i][j]=-1;
+ }
+ cursorx=bp.cursorX;
+ cursory=bp.cursorY;
+ score=bp.score;
+ pixels=bp.pixels;
+ chain=bp.chain;
+ speedLevel=bp.speed;
+ Uint8 result = bp.result;
+ bGameOver = false; //Make sure that it is initialized!
+ if(result%2==1) {
+ bGameOver=true;
+ result-=1;
+ }
+ if (result%4==2) {
+ hasWonTheGame = true;
+ result-=2;
+ }
+ if (result==4) {
+ bDraw = true;
+ }
+
+ }
+
+ //Test if LineNr is an empty line, returns false otherwise.
+ bool BlockGame::LineEmpty(int lineNr) {
+ bool empty = true;
+ for (int i = 0; i <7; i++)
+ if (board[i][lineNr] != -1)
+ empty = false;
+ return empty;
+ }
+
+ //Test if the entire board is empty (used for Puzzles)
+ bool BlockGame::BoardEmpty() {
+ bool empty = true;
+ for (int i=0;i<6;i++)
+ for (int j=1;j<13;j++)
+ if (board[i][j] != -1)
+ empty = false;
+ return empty;
+ }
+
+ //Anything that the user can't move? In that case Game Over cannot occur
+ bool BlockGame::hasStaticContent() {
+ for (int i=0;i<6;i++)
+ for (int j=1;j<13;j++)
+ if (board[i][j] >= 10000000) //Higher than this means combos (garbage is static, but the stack is static but nothing to do about it)
+ return true; //They are static
+ return false; //Return false if no static object found
+ }
+
+ /*
+ * Generates some blocks so the user don't see a board without blocks
+ */
+ //void putStartBlocks(Uint32);
+
+ void BlockGame::putStartBlocks() {
+ putStartBlocks(time(0));
+ }
+
+ void BlockGame::putStartBlocks(Uint32 n) {
+ for (int i=0;i<7;i++)
+ for (int j=0;j<30;j++) {
+ board[i][j] = -1;
+ }
+ nextRandomNumber = n;
+ int choice = rand2()%3; //Pick a random layout
+ switch (choice) {
+ case 0:
+ //row 0:
+ board[0][0]=1;
+ board[1][0]=0;
+ board[2][0]=4;
+ board[3][0]=3;
+ board[4][0]=3;
+ board[5][0]=5;
+ //row 1:
+ board[0][1]=1;
+ board[1][1]=4;
+ board[2][1]=2;
+ board[3][1]=0;
+ board[4][1]=4;
+ board[5][1]=5;
+ //row 2:
+ board[0][2]=2;
+ board[1][2]=3;
+ board[2][2]=0;
+ board[3][2]=4;
+ board[4][2]=1;
+ board[5][2]=1;
+ //row 3:
+ board[0][3]=3;
+ board[1][3]=2;
+ board[2][3]=3;
+ board[3][3]=1;
+ board[4][3]=0;
+ board[5][3]=4;
+ //row 4:
+ board[0][4]=2;
+ board[1][4]=3;
+ board[2][4]=3;
+ board[3][4]=1;
+ board[4][4]=4;
+ board[5][4]=0;
+ //row 5:
+ board[0][5]=-1;
+ board[1][5]=5;
+ board[2][5]=5;
+ board[3][5]=-1;
+ board[4][5]=1;
+ board[5][5]=-1;
+ break;
+ case 1:
+ //row 0:
+ board[0][0]=3;
+ board[1][0]=5;
+ board[2][0]=0;
+ board[3][0]=0;
+ board[4][0]=4;
+ board[5][0]=2;
+ //row 1:
+ board[0][1]=3;
+ board[1][1]=5;
+ board[2][1]=-1;
+ board[3][1]=5;
+ board[4][1]=4;
+ board[5][1]=2;
+ //row 2:
+ board[0][2]=2;
+ board[1][2]=-1;
+ board[2][2]=-1;
+ board[3][2]=4;
+ board[4][2]=0;
+ board[5][2]=3;
+ //row 3:
+ board[0][3]=2;
+ board[5][3]=3;
+ break;
+ default:
+ //row 0:
+ board[0][0]=4;
+ board[1][0]=5;
+ board[2][0]=2;
+ board[3][0]=0;
+ board[4][0]=1;
+ board[5][0]=5;
+ //row 1:
+ board[0][1]=4;
+ board[1][1]=5;
+ board[2][1]=2;
+ board[3][1]=1;
+ board[4][1]=0;
+ board[5][1]=2;
+ //row 2:
+ board[0][2]=2;
+ board[1][2]=4;
+ board[2][2]=-1;
+ board[3][2]=0;
+ board[4][2]=1;
+ board[5][2]=5;
+ //row 3:
+ board[0][3]=4;
+ board[1][3]=2;
+ board[2][3]=-1;
+ board[3][3]=1;
+ board[4][3]=0;
+ board[5][3]=2;
+ //row 4:
+ board[0][4]=4;
+ board[1][4]=2;
+ board[2][4]=-1;
+ board[3][4]=0;
+ board[4][4]=1;
+ board[5][4]=-1;
+ break;
+ };
+ }
+
+ //decreases hang for all hanging blocks and wait for waiting blocks
+ void BlockGame::ReduceStuff() {
+ Uint32 howMuchHang = (ticks - FRAMELENGTH*hangTicks)/FRAMELENGTH;
+ if (howMuchHang>0) {
+ for (int i=0; i<7; i++)
+ for (int j=0; j<30; j++) {
+ if ((board[i][j]/BLOCKHANG)%10==1) {
+ int hangNumber = (board[i][j]/10)%100;
+ if (hangNumber<=howMuchHang) {
+ board[i][j]-=BLOCKHANG;
+ board[i][j]-=hangNumber*10;
+ }
+ else {
+ board[i][j]-=10*howMuchHang;
+ }
+ }
+ if ((board[i][j]/BLOCKWAIT)%10==1) {
+ int hangNumber = (board[i][j]/10)%100;
+ if (hangNumber<=howMuchHang) {
+ //The blocks must be cleared
+ board[i][j]-=hangNumber*10;
+ }
+ else {
+ board[i][j]-=10*howMuchHang;
+ }
+ }
+ }
+ }
+ hangTicks+=howMuchHang;
+ }
+
+ //Creates garbage using a given wide and height
+ bool BlockGame::CreateGarbage(int wide, int height) {
+#if NETWORK
+ if (bNetworkPlayer) {
+ pushGarbage(wide, height, 0);
+ }
+ else
+#endif
+ {
+ if (wide>6) wide = 6;
+ if (height>12) height = 12;
+ int startPosition = 12;
+ while ((!(LineEmpty(startPosition))) || (startPosition == 29))
+ startPosition++;
+ if (startPosition == 29) return false; //failed to place blocks
+ if (29-startPosition<height) return false; //not enough space
+ int start, end;
+ if (bGarbageFallLeft)
+ {
+ start=0;
+ end=start+wide;
+ bGarbageFallLeft = false;
+ }
+ else
+ {
+ start=6-wide;
+ end = 6;
+ bGarbageFallLeft = true;
+ }
+ for (int i = startPosition; i <startPosition+height; i++)
+ for (int j = start; j < end; j++) {
+ board[j][i] = 1000000+nextGarbageNumber;
+ }
+ nextGarbageNumber++;
+ if (nextGarbageNumber>999999) nextGarbageNumber = 10;
+ //bGarbageFallLeft = !(bGarbageFallLeft);
+ return true;
+ }
+ }
+
+ //Creates garbage using a given wide and height
+ bool BlockGame::CreateGreyGarbage() {
+#if NETWORK
+ if (bNetworkPlayer) {
+ pushGarbage(6, 1, 1);
+ }
+ else
+#endif
+ {
+ int startPosition = 12;
+ while ((!(LineEmpty(startPosition))) || (startPosition == 29))
+ startPosition++;
+ if (startPosition == 29) return false; //failed to place blocks
+ if (29-startPosition<1) return false; //not enough space
+ int start, end;
+ {
+ start=0;
+ end=6;
+ }
+ for (int i = startPosition; i <startPosition+1; i++)
+ for (int j = start; j < end; j++) {
+ board[j][i] = 2*1000000+nextGarbageNumber;
+ }
+ nextGarbageNumber++;
+ if (nextGarbageNumber>999999) nextGarbageNumber = 10;
+ return true;
+ }
+ }
+
+
+ //Clears garbage, must take one the lower left corner!
+ int BlockGame::GarbageClearer(int x, int y, int number, bool aLineToClear, int chain) {
+ if ((board[x][y])%1000000 != number) return -1;
+ if (aLineToClear) {
+ board[x][y] = rand() % 6;
+ board[x][y] += 10*HANGTIME+BLOCKHANG+CHAINPLACE*chain;
+ }
+ garbageToBeCleared[x][y] = false;
+ GarbageClearer(x+1, y, number, aLineToClear, chain);
+ GarbageClearer(x, y+1, number, false, chain);
+ return 1;
+ }
+
+ //Marks garbage that must be cleared
+ int BlockGame::GarbageMarker(int x, int y) {
+ if ((x>6)||(x<0)||(y<0)||(y>29)) return -1;
+ if (((board[x][y])/1000000 == 1)&&(garbageToBeCleared[x][y] == false)) {
+ garbageToBeCleared[x][y] = true;
+ //Float fill
+ GarbageMarker(x-1, y);
+ GarbageMarker(x+1, y);
+ GarbageMarker(x, y-1);
+ GarbageMarker(x, y+1);
+ }
+ return 1;
+ }
+
+ int BlockGame::FirstGarbageMarker(int x, int y) {
+ if ((x>6)||(x<0)||(y<0)||(y>29)) return -1;
+ if (((board[x][y])/1000000 == 2)&&(garbageToBeCleared[x][y] == false)) {
+ for (int i=0;i<6;i++)
+ garbageToBeCleared[i][y] = true;
+ }
+ else
+ if (((board[x][y])/1000000 == 1)&&(garbageToBeCleared[x][y] == false)) {
+ garbageToBeCleared[x][y] = true;
+ //Float fill
+ GarbageMarker(x-1, y);
+ GarbageMarker(x+1, y);
+ GarbageMarker(x, y-1);
+ GarbageMarker(x, y+1);
+ }
+ return 1;
+ }
+
+ //Clear Blocks if 3 or more is alligned (naive implemented)
+ void BlockGame::ClearBlocks() {
+
+ bool toBeCleared[7][30]; //true if blok must be removed
+
+ int previus=-1; //the last block checked
+ int combo=0;
+ for (int i=0;i<30;i++)
+ for (int j=0;j<7;j++) {
+ toBeCleared[j][i] = false;
+ garbageToBeCleared[j][i] = false;
+ }
+ for (int i=0;i<7;i++) {
+ bool faaling = false;
+ for (int j=0;j<30;j++) {
+ if ((faaling)&&(board[i][j]>-1)&&(board[i][j]%10000000<7)) {
+ board[i][j]+=BLOCKFALL;
+ }
+ if ((!faaling)&&((board[i][j]/BLOCKFALL)%10==1))
+ board[i][j]-=BLOCKFALL;
+ if (!((board[i][j]>-1)&&(board[i][j]%10000000<7)))
+ faaling=true;
+ if (((board[i][j]/1000000)%10==1)||((board[i][j]/1000000)%10==2)||((board[i][j]/BLOCKHANG)%10==1)||((board[i][j]/BLOCKWAIT)%10==1))
+ faaling = false;
+ }
+ }
+
+
+ for (int j=0;j<7;j++) {
+ previus = -1;
+ combo=0;
+
+ for (int i=1;i<30;i++) {
+ if ((board[j][i]>-1)&&(board[j][i]%10000000<7)) {
+ if (board[j][i]%10000000 == previus) {
+ combo++;
+ }
+ else {
+ if (combo>2)
+ for (int k = i-combo; k<i;k++) {
+ toBeCleared[j][k] = true;
+ }
+ combo=1;
+ previus = board[j][i]%10000000;
+ }
+ } //if board
+ else {
+ if (combo>2)
+ for (int k = i-combo; k<i;k++) {
+ toBeCleared[j][k] = true;
+ }
+ combo = 0;
+ previus = -1;
+ }
+
+ } //for i
+ } //for j
+
+
+ combo = 0;
+ chain = 0;
+ for (int i=0; i<6;i++)
+ for (int j=0; j<30;j++) {
+ //Clears blocks marked for clearing
+ Sint32 temp=board[i][j];
+ if (1==((temp/BLOCKWAIT)%10))
+ if (((temp/10)%100)==0) {
+ if (chainSize[chain]<chainSize[board[i][j]/10000000])
+ chain = board[i][j]/10000000;
+
+ theBallManeger.addBall(topx+40+i*bsize, topy+bsize*12-j*bsize, true, board[i][j]%10);
+ theBallManeger.addBall(topx+i*bsize, topy+bsize*12-j*bsize, false, board[i][j]%10);
+ theExplosionManeger.addExplosion(topx-10+i*bsize, topy+bsize*12-10-j*bsize);
+ board[i][j]=-2;
+ }
+ }
+ for (int i=0; i<7;i++) {
+ bool setChain=false;
+ for (int j=0; j<30;j++) {
+ if (board[i][j]==-1)
+ setChain=false;
+ if (board[i][j]==-2) {
+ board[i][j]=-1;
+ setChain=true;
+ if (SoundEnabled)Mix_PlayChannel(0, boing, 0);
+ }
+ if (board[i][j]!=-1)
+ if ((setChain)&&((board[i][j]/GARBAGE)%10!=1)&&((board[i][j]/GARBAGE)%10!=2)) {
+ board[i][j]=((board[i][j]%CHAINPLACE)+CHAINPLACE*chain);
+ //somethingsGottaFall = true;
+ }
+
+ }
+ }
+ combo=0;
+ int startvalue;
+ if (pixels == 0)
+ startvalue=1;
+ else
+ startvalue=0;
+ for (int i=startvalue;i<30;i++) {
+ previus=-1;
+ combo=0;
+ for (int j=0;j<7;j++) {
+ if (((board[j][i]>-1)&&(board[j][i]%10000000<7))) {
+ if (board[j][i]%10000000 == previus) {
+ combo++;
+ }
+ else {
+ if (combo>2)
+ for (int k = j-combo; k<j;k++) {
+ toBeCleared[k][i] = true;
+ }
+ combo=1;
+ previus = board[j][i]%10000000;
+ }
+ } //if board
+ else {
+ if (combo>2)
+ for (int k = j-combo; k<j;k++) {
+ toBeCleared[k][i] = true;
+ }
+ combo = 0;
+ previus = -1;
+ }
+
+ } //for j
+ } //for i
+ bool blockIsFalling[6][30]; //See that is falling
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++)
+ blockIsFalling[j][i] = false;
+
+
+
+ combo = 0;
+ chain = 0;
+ int grey = 0;
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++)
+ if (toBeCleared[j][i]) {
+ //see if any garbage is around:
+ FirstGarbageMarker(j-1, i);
+ FirstGarbageMarker(j+1, i);
+ FirstGarbageMarker(j, i-1);
+ FirstGarbageMarker(j, i+1);
+ //that is checked now :-)
+ if (board[j][i]%10000000==6)
+ grey++;
+ if ((vsMode) && (grey>2) && (board[j][i]%10000000==6))
+ garbageTarget->CreateGreyGarbage();
+ if ((board[j][i]>-1)&&(board[j][i]%10000000<7))
+ board[j][i]+=BLOCKWAIT+10*FALLTIME;
+
+ if (chainSize[board[j][i]/10000000]>chainSize[chain])
+ chain=board[j][i]/10000000;
+ combo++;
+ stop+=140*combo;
+ score +=10;
+ if (combo>3)
+ score+=3*combo; //More points if more cleared simontanously
+ }
+ score+=chainSize[chain]*100;
+ if (chain==0) {
+ chain=firstUnusedChain();
+ chainSize[chain]=0;
+ chainUsed[chain]=true;
+ }
+ chainSize[chain]++;
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++) {
+ //if(board[j][i]/10==(BLOCKWAIT+10*FALLTIME)/10)
+ if (toBeCleared[j][i]) {
+ board[j][i]=(board[j][i]%10000000)+chain*10000000;
+ }
+ }
+
+ { //This is here we add text to screen!
+ bool dead = false;
+ for (int i=29;i>=0;i--)
+ for (int j=0;j<6;j++)
+ if (toBeCleared[j][i]) {
+ if (!dead) {
+ dead=true;
+ string tempS = itoa(chainSize[chain]);
+ if (chainSize[chain]>1)
+ theTextManeger.addText(topx-10+j*bsize, topy+12*bsize-i*bsize, tempS, 1000);
+ }
+ }
+ } //This was there text was added
+
+ if (vsMode)
+ switch (combo) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ case 4:
+ garbageTarget->CreateGarbage(3, 1);
+ break;
+ case 5:
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ case 6:
+ garbageTarget->CreateGarbage(5, 1);
+ break;
+ case 7:
+ garbageTarget->CreateGarbage(6, 1);
+ break;
+ case 8:
+ garbageTarget->CreateGarbage(4, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ case 9:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ case 10:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ break;
+ case 11:
+ garbageTarget->CreateGarbage(6, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ break;
+ case 12:
+ garbageTarget->CreateGarbage(6, 1);
+ garbageTarget->CreateGarbage(6, 1);
+ break;
+ case 13:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ default:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ }
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++)
+ if (garbageToBeCleared[j][i]) {
+ GarbageClearer(j, i, board[j][i]%1000000, true, chain); //Clears the blocks and all blocks connected to it.
+ }
+
+ chain=0;
+
+ //Break chains (if a block is stable it is resetted to (chain == 0)):
+ for (int i=0;i<7;i++) {
+ bool faaling = false; //In the beginning we are NOT falling
+ for (int j=0;j<30;j++) {
+ if ((faaling)&&(board[i][j]>-1)&&(board[i][j]<7)) {
+ board[i][j]+=BLOCKFALL;
+ }
+ if ((!faaling)&&((board[i][j]/BLOCKFALL)%10==1))
+ board[i][j]-=BLOCKFALL;
+ if ((!faaling)&&(board[i][j]>0)&&(board[i][j]/10000000!=0)&&((board[i][j]/BLOCKWAIT)%10!=1)&&((board[i][j]/BLOCKHANG)%10!=1)) {
+ if (chainSize[board[i][j]/10000000]>chainSize[chain])
+ chain=board[i][j]/10000000;
+ board[i][j]=board[i][j]%10000000;
+ }
+ if (!((board[i][j]>-1)&&(board[i][j]<7)))
+ faaling=true;
+ if (((board[i][j]/1000000)%10==1)||((board[i][j]/BLOCKHANG)%10==1)||((board[i][j]/BLOCKWAIT)%10==1))
+ faaling = false;
+ }
+ }
+
+ //Create garbage as a result
+ //if((vsMode)&&(chainSize[chain]>1)) garbageTarget->CreateGarbage(6,chainSize[chain]-1);
+
+ //Calculate chain
+ chain=0;
+ for (int i=0; i<6;i++)
+ for (int j=0; j<30;j++) {
+ if (chainSize[board[i][j]/10000000]>chain)
+ chain=chainSize[board[i][j]/10000000];
+ }
+
+ //Make space in table for more things
+ if (chain==0)
+ for (int i=0;i<NUMBEROFCHAINS;i++)
+ if (chainUsed[i]==true) {
+ if ((vsMode)&&(chainSize[i]>1)) garbageTarget->CreateGarbage(6, chainSize[i]-1);
+ if ((SoundEnabled)&&(chainSize[i]>4))Mix_PlayChannel(1, applause, 0);
+ if(chainSize[i]>1 && !puzzleMode && !AI_Enabled)
+ Stats::getInstance()->addOne((string)"chainX"+itoa(chainSize[i]));
+ chainUsed[i]=false;
+ }
+ } //ClearBlocks
+
+ //prints "Game Over" and ends game
+ void BlockGame::SetGameOver() {
+ if (!bGameOver) {
+ gameEndedAfter = ticks-gameStartedAt; //We game ends now!
+ if(!AI_Enabled && !bReplaying)
+ {
+ TimeHandler::addTime("playTime",TimeHandler::ms2ct(gameEndedAfter));
+ }
+ }
+ if(bReplaying)
+ {
+ bReplaying = false;
+ }
+ else
+ {
+ strncpy(theReplay.name,name,30);
+ }
+ theReplay.setFinalFrame(getPackage(), 0);
+ bGameOver = true;
+ showGame = false;
+ if(stageClear)
+ stageButtonStatus = SBstageClear;
+ }
+
+ bool BlockGame::GetAIenabled() {
+ return AI_Enabled;
+ }
+
+
+ //Moves all peaces a spot down if possible
+ int BlockGame::FallBlock(int x, int y, int number) {
+ if (y == 0) return -1;
+ if (x>0)
+ if (board[x-1][y] == number)
+ return -1;
+ int i=x;
+ bool canFall = true;
+ //checks a line of a garbage block and see if something is under it
+ while ((board[i][y] == number)&&(canFall)&&(i<6)) {
+ if (board[i][y-1] != -1) canFall = false;
+ i++;
+ }
+ if (canFall) {
+ //cout << "Now falling" << endl;
+ for (int j = x;j<i;j++) {
+ board[j][y-1] = board[j][y];
+ board[j][y] = -1;
+ }
+ }
+ return 0;
+ } //FallBlock
+
+
+ //Makes all Garbage fall one spot
+ void BlockGame::GarbageFall() {
+ for (int i=0;i<30;i++)
+ for (int j=0;j<7; j++) {
+ if ((((board[j][i]/1000000)%10) == 1)||(((board[j][i]/1000000)%10) == 2))
+ FallBlock(j, i, board[j][i]);
+ }
+ }
+
+ //Makes the blocks fall (it doesn't test time, this must be done before hand)
+ void BlockGame::FallDown() {
+ bool falling =false; //nothing is moving unless proven otherwise
+ for (int i=0;i<29;i++)
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]==-1) && (board[j][i+1]!=-1) && (board[j][i+1]%BLOCKFALL<7)) {
+ board[j][i] = board[j][i+1];
+ board[j][i+1] = -1;
+ falling = true; //something is moving!
+ }
+ if ((board[j][i]/BLOCKWAIT)%10==1)
+ falling=true;
+ }
+ if (!falling) //If nothing is falling
+ {
+ if ((puzzleMode)&&(!bGameOver)&&(MovesLeft==0)&&(!(BoardEmpty()))) {
+ //Puzzle not won
+ SetGameOver();
+ stageButtonStatus = SBpuzzleMode;
+ }
+ }
+ GarbageFall(); //Makes the garbage fall
+ nrFellDown++; //Sets number of this fall, so we know then the next will occur
+ }
+
+ //Moves the cursor, receaves N,S,E or W as a char an moves as desired
+ void BlockGame::MoveCursor(char way) {
+ if (!bGameOver) //If game over nothing happends
+ {
+ if ((way == 'N') && ((cursory<10)||(TowerHeight>12) ||(((pixels==bsize)||(pixels==0)) && (cursory<11))))
+ cursory++;
+ if ((way == 'S') && (cursory>0))
+ cursory--;
+ if ((way == 'W') && (cursorx>0))
+ cursorx--;
+ if ((way == 'E') && (cursorx<4))
+ cursorx++;
+ }
+ }
+
+ //switches the two blocks at the cursor position, unless game over
+ void BlockGame::SwitchAtCursor() {
+ if ((board[cursorx][cursory+1]<7) && (board[cursorx+1][cursory+1]<7) && (!bGameOver) && ((!puzzleMode)||(MovesLeft>0)) && (gameStartedAt<ticks)) {
+ int temp = board[cursorx][cursory+1];
+ board[cursorx][cursory+1] = board[cursorx+1][cursory+1];
+ board[cursorx+1][cursory+1] = temp;
+ }
+ if ((puzzleMode)&&(gameStartedAt<ticks)&&(MovesLeft>0)) MovesLeft--;
+ }
+
+ //Generates a new line and moves the field one block up (restart puzzle mode)
+ void BlockGame::PushLine() {
+ //If not game over, not high tower and not puzzle mode
+ if ((!bGameOver) && TowerHeight<13 && (!puzzleMode) && (gameStartedAt<ticks)&&(chain==0)) {
+ for (int i=19;i>0;i--)
+ for (int j=0;j<6;j++) {
+ board[j][i] = board[j][i-1];
+ }
+ for (int j=0;j<6;j++) {
+ board[j][0] = rand2() % 4;
+ if (j > 0) {
+ if (board[j][0] == board[j-1][0])
+ board[j][0] = rand2() % 6;
+ }
+ if (board[j][0] == board[j][1])
+ board[j][0] = rand2() % 6;
+ if (board[j][0] == board[j][1])
+ board[j][0] = rand2() % 6;
+ while ((j>0)&&(board[j][0]==board[j-1][0]))
+ board[j][0] = rand2() % 6;
+ }
+ score+=1;
+ MoveCursor('N');
+ if (vsMode) {
+ if (rand2()%6==1)
+ board[rand2()%6][0]=6;
+ }
+ pixels = 0;
+ stop=0;
+ pushedPixelAt = ticks;
+ linesCleared++;
+ AI_LineOffset++;
+ nrPushedPixel=(int)((double)(pushedPixelAt-gameStartedAt)/(1000.0*speed));
+
+ if(!AI_Enabled && !bReplaying)
+ {
+ Stats::getInstance()->addOne("linesPushed");
+ }
+ } //if !bGameOver
+
+ //Restart Puzzle mode
+ if (puzzleMode && !bGameOver) {
+ //Reloads level
+ MovesLeft = nrOfMovesAllowed[Level];
+ for (int i=0;i<6;i++)
+ for (int j=0;j<12;j++) {
+ board[i][j+1] = puzzleLevels[Level][i][j];
+ }
+ score=0;
+ bGameOver=false;
+ showGame = true;
+ }
+
+ if ((TowerHeight>12) && (!puzzleMode)&&(!bGameOver)&&(chain==0)) {
+ if ((!vsMode)&&(theTopScoresEndless.isHighScore(score))&&(!AI_Enabled)) {
+ if (SoundEnabled)Mix_PlayChannel(1, applause, 0);
+ theTopScoresEndless.addScore(name, score);
+ cout << "New high score!" << endl;
+ }
+ SetGameOver();
+ }
+
+
+ }//PushLine
+
+ //Pushes a single pixel, so it appears to scrool
+ void BlockGame::PushPixels() {
+ nrPushedPixel++;
+ if ((pixels < bsize) && TowerHeight<13) {
+ pixels++;
+ }
+ else
+ PushLine();
+ if (pixels>bsize)
+ pixels=0;
+ }
+
+
+ //See how high the tower is, saved in integer TowerHeight
+ void BlockGame::FindTowerHeight() {
+ /*
+ * Old implementation, used until I find the bug in the other.
+ * This function has a bug in stage clear! if an empty line appears.
+ */
+ prevTowerHeight = TowerHeight;
+ bool found = false;
+ TowerHeight = 0;
+ while (!found) {
+ found = true;
+ for (int j=0;j<6;j++)
+ if (board[j][TowerHeight] != -1)
+ found = false;
+ TowerHeight++;
+ }
+ TowerHeight--;
+ }
+
+///////////////////////////////////////////////////////////////////////////
+/////////////////////////// AI starts here! ///////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+ //First the helpet functions:
+ int BlockGame::nrOfType(int line, int type) {
+ // cout << "Start_ nrOfType" << endl;
+ int counter = 0;
+ for (int i=0; i<6; i++)
+ if (board[i][line]==type)counter++;
+ return counter;
+ }
+
+
+ //See if a combo can be made in this line
+ int BlockGame::horiInLine(int line) {
+ //cout << "Start_ hori in line" << endl;
+ int nrOfType[7] = {0, 0, 0, 0, 0, 0, 0};
+ int iTemp;
+ int max = 0;
+ for (int i=0; i<6; i++) {
+ iTemp = board[i][line];
+ if ((iTemp>-1)&&(iTemp<7))
+ nrOfType[iTemp]++;
+ }
+ for (int j=0; j<7; j++) {
+ if (nrOfType[j]>max) {
+ max = nrOfType[j];
+ AIcolorToClear = j;
+ }
+ }
+ return max;
+ }
+
+ bool BlockGame::horiClearPossible() {
+ //cout << "Start_ horiclear possible" << endl;
+ int i=13;
+ bool solutionFound = false;
+ do{
+ if (horiInLine(i)>2) {
+ AI_LineOffset = 0;
+ AIlineToClear = i;
+ solutionFound = true;
+ }
+ i--;
+ }while ((!solutionFound)&&(i>0));
+ return solutionFound;
+ }
+
+ //the Line Has Unmoveable Objects witch might stall the AI
+ bool BlockGame::lineHasGarbage(int line) {
+ for (int i=0;i<6;i++)
+ if (board[i][line]>1000000)
+ return true;
+ return false;
+ }
+
+ //Types 0..6 in line
+ int BlockGame::nrOfRealTypes(int line) {
+ //cout << "Start_ nrOfReal" << endl;
+ int counter = 0;
+ for (int i=0; i<6; i++)
+ if ((board[i][line]>-1)&&(board[i][line]<7))counter++;
+ return counter;
+ }
+
+ //See if there is a tower
+ bool BlockGame::ThereIsATower() {
+ //cout << "Start_ there is a tower" << endl;
+ bool bThereIsATower = false; //Unless proven otherwise!
+ bool topReached = false; //If we have reached the top
+ int lineNumber = 0;
+ bool emptySpacesFound = false;
+ do {
+ if ((emptySpacesFound) && (nrOfRealTypes(lineNumber)>0)&&(nrOfType(lineNumber, -1)>0)) {
+ AIlineToClear = lineNumber;
+ if (lineHasGarbage(lineNumber))
+ return false;
+ else
+ bThereIsATower = true;
+ }
+ else
+ emptySpacesFound=false;
+ if ((!emptySpacesFound)&&(nrOfType(lineNumber, -1)>0))
+ emptySpacesFound = true;
+ if (lineNumber<12)
+ lineNumber++;
+ else
+ topReached = true;
+ }while ((!bThereIsATower)&&(!topReached));
+ //if(bThereIsATower)
+ //cout << "There is actually a tower" << endl;
+ return bThereIsATower;
+ }
+
+ double BlockGame::firstInLine1(int line) {
+ for (int i=0;i<6;i++)
+ if ((board[i][line]>-1)&&(board[i][line]<7))
+ return (double)i;
+ return 3.0;
+ }
+
+ //returns the first coordinate of the block of type
+ double BlockGame::firstInLine(int line, int type) {
+ for (int i=0;i<6;i++)
+ if (board[i][line]==type)
+ return (double)i;
+ return 3.0;
+ }
+
+ //There in the line shall we move
+ int BlockGame::closestTo(int line, int place) {
+ if ((int)firstInLine1(line)>place)
+ return (int)firstInLine1(line)-1;
+ for (int i=place;i>=0;i--) {
+ if ((board[i][line]>-1)&&(board[i][line]<7))
+ return i;
+ }
+ AIstatus=0;
+ return place;
+ }
+
+ //The AI will remove a tower
+ void BlockGame::AI_ClearTower() {
+ // cout << "AI: ClearTower, line: " << AIlineToClear << endl;
+ int place = (int)firstInLine(AIlineToClear-1, -1); //Find an empty field to frop a brick into
+ int xplace = closestTo(AIlineToClear, place); //Find the brick to drop in it
+ if (cursory+1<AIlineToClear)
+ MoveCursor('N');
+ else
+ if (cursory+1>AIlineToClear)
+ MoveCursor('S');
+ else
+ if (cursorx<xplace)
+ MoveCursor('E');
+ else
+ if (cursorx>xplace)
+ MoveCursor('W');
+ else
+ SwitchAtCursor();
+ if (!ThereIsATower())
+ AIstatus = 0;
+ }
+
+ //The AI will try to clear block horisontally
+ void BlockGame::AI_ClearHori() {
+ // cout << "AI: ClearHori";
+ int lowestLine = AIlineToClear;
+ //AIcolorToClear
+ bool found =true;
+ /*for(int i; (i<12)&&(!found);i++)
+ * {
+ * if(horiInLine(i)>2)
+ * {
+ * int lowestLine = i;
+ * found = true;
+ * }
+ * }*/
+ for (int i=0;i<7;i++) {
+ if (nrOfType(lowestLine, i)>2)
+ AIcolorToClear = i;
+ }
+ if (found) {
+ if (cursory>lowestLine-1)
+ MoveCursor('S');
+ else if (cursory<lowestLine-1)
+ MoveCursor('N');
+ else if (nrOfType(lowestLine, AIcolorToClear)>2) {
+ int left=0, right=0;
+ if (board[0][lowestLine]==AIcolorToClear) left++;
+ if (board[1][lowestLine]==AIcolorToClear) left++;
+ if (board[2][lowestLine]==AIcolorToClear) left++;
+ if (board[3][lowestLine]==AIcolorToClear) right++;
+ if (board[4][lowestLine]==AIcolorToClear) right++;
+ if (board[5][lowestLine]==AIcolorToClear) right++;
+ int xplace = 0;
+ if (left<right) {
+ // cout << ", right>left";
+ int count=0;
+ for (int i=0;(i<4)&&(count<1);i++)
+ if ((board[i][lowestLine]==AIcolorToClear)&&((i==0)||(board[i+1][lowestLine]!=AIcolorToClear))) {
+ count++;
+ xplace = i;
+ }
+ }
+ else {
+ // cout << ", left>=right";
+ int count=0;
+ for (int i=3;(i<=5)&&(count<1);i++)
+ if ((board[i][lowestLine]==AIcolorToClear)&&(board[i-1][lowestLine]!=AIcolorToClear)) {
+ count++;
+ xplace = --i;
+ }
+ }
+ //cout << ", xplace: " << xplace;
+ if (cursorx<xplace)
+ MoveCursor('E');
+ else
+ if (cursorx>xplace)
+ MoveCursor('W');
+ else
+ if (cursorx==xplace)
+ SwitchAtCursor();
+ else
+ AIstatus = 0;
+ }
+ else
+ AIstatus = 0;
+ }
+ else
+ AIstatus = 0;
+ //cout << endl; //for debugging
+ }
+
+ //Test if vertical clear is possible
+ bool BlockGame::veriClearPossible() {
+ bool found=false;
+ int colors[7] = {0, 0, 0, 0, 0, 0, 0};
+ for (int i=12;(i>0)&&(!found);i--) {
+ for (int j=0;j<7;j++) {
+ if (nrOfType(i, j)==0)
+ colors[j]=0;
+ else
+ if (++colors[j]>2) {
+ AIcolorToClear = j;
+ AIlineToClear = i;
+ found=true;
+ }
+
+ }
+ }
+ return found;
+ }
+
+
+
+ //There in the line shall we move
+ int BlockGame::closestTo(int line, int type, int place) {
+ if ((int)firstInLine(line, type)>place)
+ return (int)firstInLine(line, type)-1;
+ for (int i=place;i>=0;i--) {
+ if (board[i][line]==type)
+ return i;
+ }
+ AIstatus=0;
+ return place;
+ }
+
+ //The AI will try to clear blocks vertically
+ void BlockGame::AI_ClearVertical() {
+ // cout << "AI: ClearVeri";
+ //First we find the place there we will align the bricks
+ int placeToCenter = (int)(firstInLine(AIlineToClear, AIcolorToClear)/3.0+firstInLine(AIlineToClear+1, AIcolorToClear)/3.0+firstInLine(AIlineToClear+2, AIcolorToClear)/3.0);
+ int unlimitedLoop=0;
+ while (((board[placeToCenter][AIlineToClear]>1000000)||(board[placeToCenter][AIlineToClear+1]>1000000)||(board[placeToCenter][AIlineToClear+2]>1000000))&&(unlimitedLoop<10)) {
+ unlimitedLoop++;
+ placeToCenter++;
+ if (placeToCenter>5)
+ placeToCenter=0;
+ }
+ if(unlimitedLoop>9) {
+ AIstatus = 0;
+ }
+ //cout << ", ptc: " << placeToCenter << ", line: " << AIlineToClear << ", cy: " << cursory;
+ if (cursory+1>AIlineToClear+2) {
+ // cout << ", cursory>line+2";
+ MoveCursor('S');
+ }
+ if (cursory+1<AIlineToClear)
+ MoveCursor('N');
+ bool toAlign[3]={true, true, true};
+ if (board[placeToCenter][AIlineToClear+0]==AIcolorToClear)
+ toAlign[0]=false;
+ if (board[placeToCenter][AIlineToClear+1]==AIcolorToClear)
+ toAlign[1]=false;
+ if (board[placeToCenter][AIlineToClear+2]==AIcolorToClear)
+ toAlign[2]=false;
+ //cout << "status: " << toAlign[0] << " " << toAlign[1] << " " << toAlign[2];
+ if (cursory+1==AIlineToClear) {
+ if (toAlign[0]==false)
+ MoveCursor('N');
+ else {
+ if (cursorx>closestTo(AIlineToClear, AIcolorToClear, placeToCenter))
+ MoveCursor('W');
+ else
+ if (cursorx<closestTo(AIlineToClear, AIcolorToClear, placeToCenter))
+ MoveCursor('E');
+ else
+ SwitchAtCursor();
+ }
+ }
+ else
+ if (cursory+1==AIlineToClear+1) {
+ if (toAlign[1]==false) {
+ if (toAlign[2])
+ MoveCursor('N');
+ else
+ MoveCursor('S');
+ }
+ else {
+ if (cursorx>closestTo(AIlineToClear+1, AIcolorToClear, placeToCenter))
+ MoveCursor('W');
+ else
+ if (cursorx<closestTo(AIlineToClear+1, AIcolorToClear, placeToCenter))
+ MoveCursor('E');
+ else
+ SwitchAtCursor();
+ }
+ }
+ else
+ if (cursory+1==AIlineToClear+2) {
+ if (toAlign[2]==false)
+ MoveCursor('S');
+ else {
+ if (cursorx>closestTo(AIlineToClear+2, AIcolorToClear, placeToCenter))
+ MoveCursor('W');
+ else
+ if (cursorx<closestTo(AIlineToClear+2, AIcolorToClear, placeToCenter))
+ MoveCursor('E');
+ else
+ SwitchAtCursor();
+ }
+ }
+
+ if ((!toAlign[0])&&(!toAlign[1])&&(!toAlign[2]))
+ AIstatus = 0;
+ if ((nrOfType(AIlineToClear, AIcolorToClear)==0)||(nrOfType(AIlineToClear+1, AIcolorToClear)==0)||(nrOfType(AIlineToClear+2, AIcolorToClear)==0))
+ AIstatus = 0;
+ //cout << endl;
+ }
+
+
+ void BlockGame::AI_Move() {
+ switch (AIstatus) {
+ case 1:
+ if (TowerHeight<8)PushLine();
+ else AIstatus = 0;
+ break;
+ case 2:
+ AI_ClearTower();
+ break;
+ case 3:
+ AI_ClearHori();
+ break;
+ case 4:
+ AI_ClearVertical();
+ break;
+ case 5:
+ if (!firstLineCreated){
+ PushLine();
+ firstLineCreated = true;
+ }
+ else {
+ PushLine();
+ AIstatus = 0;
+ }
+ break;
+ case 6:
+ PushLine();
+ AIstatus = 0;
+ break;
+ default:
+ if (TowerHeight<6) AIstatus = 1;
+ else
+ if (horiClearPossible()) AIstatus = 3;
+ else
+ if (veriClearPossible()) AIstatus = 4;
+ else
+ if (ThereIsATower()) AIstatus = 2;
+ else
+ AIstatus = 5;
+ break;
+ }
+ }
+
+//////////////////////////////////////////////////////////////////////////
+///////////////////////////// AI ends here! //////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+#if WITH_SDL
+ //Draws all the bricks to the board (including garbage)
+ void BlockGame::PaintBricks() {
+ for (int i=0;((i<13)&&(i<30));i++)
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]%10 != -1) && (board[j][i]%10 < 7) && ((board[j][i]/1000000)%10==0)) {
+ DrawIMG(bricks[board[j][i]%10], sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((board[j][i]/BLOCKWAIT)%10==1)
+ DrawIMG(bomb[(ticks/BOMBTIME)%2], sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((board[j][i]/BLOCKHANG)%10==1)
+ DrawIMG(ready[(ticks/READYTIME)%2], sBoard, j*bsize, bsize*12-i*bsize-pixels);
+
+ }
+ if ((board[j][i]/1000000)%10==1) {
+ int left, right, over, under;
+ int number = board[j][i];
+ if (j<1) left = -1;
+ else left = board[j-1][i];
+ if (j>5) right = -1;
+ else right = board[j+1][i];
+ if (i>28) over = -1;
+ else over = board[j][i+1];
+ if (i<1) under = -1;
+ else under = board[j][i-1];
+ if ((left == number)&&(right == number)&&(over == number)&&(under == number))
+ DrawIMG(garbageFill, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left != number)&&(right == number)&&(over == number)&&(under == number))
+ DrawIMG(garbageL, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right != number)&&(over == number)&&(under == number))
+ DrawIMG(garbageR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right == number)&&(over != number)&&(under == number))
+ DrawIMG(garbageT, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right == number)&&(over == number)&&(under != number))
+ DrawIMG(garbageB, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left != number)&&(right == number)&&(over != number)&&(under == number))
+ DrawIMG(garbageTL, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left != number)&&(right == number)&&(over == number)&&(under != number))
+ DrawIMG(garbageBL, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right != number)&&(over != number)&&(under == number))
+ DrawIMG(garbageTR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right != number)&&(over == number)&&(under != number))
+ DrawIMG(garbageBR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right != number)&&(over != number)&&(under != number))
+ DrawIMG(garbageMR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left == number)&&(right == number)&&(over != number)&&(under != number))
+ DrawIMG(garbageM, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ if ((left != number)&&(right == number)&&(over != number)&&(under != number))
+ DrawIMG(garbageML, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ }
+ if ((board[j][i]/1000000)%10==2) {
+ if (j==0)
+ DrawIMG(garbageGML, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ else
+ if (j==5)
+ DrawIMG(garbageGMR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ else
+ DrawIMG(garbageGM, sBoard, j*bsize, bsize*12-i*bsize-pixels);
+ }
+ }
+ const int j = 0;
+
+ int garbageSize=0;
+ for (int i=0;i<20;i++) {
+ if ((board[j][i]/1000000)%10==1) {
+ int left, right, over, under;
+ int number = board[j][i];
+ if (j<1) left = -1;
+ else left = board[j-1][i];
+ if (j>5) right = -1;
+ else right = board[j+1][i];
+ if (i>28) over = -1;
+ else over = board[j][i+1];
+ if (i<1) under = -1;
+ else under = board[j][i-1];
+ if (((left != number)&&(right == number)&&(over != number)&&(under == number))&&(garbageSize>0)) {
+ DrawIMG(smiley[board[j][i]%4], sBoard, 2*bsize, 12*bsize-i*bsize-pixels+(bsize/2)*garbageSize);
+ }
+ if (!((left != number)&&(right == number)&&(over == number)&&(under == number))) //not in garbage
+ {
+ garbageSize=0;
+ }
+ else {
+ //cout << "In garbage" << endl;
+ garbageSize++;
+ }
+
+ }
+ }
+ for (int i=0;i<6;i++)
+ if (board[i][0]!=-1)
+ DrawIMG(transCover, sBoard, i*bsize, 12*bsize-pixels); //Make the appering blocks transperant
+
+ }
+
+ //Paints the bricks gotten from a replay/net package
+ void BlockGame::SimplePaintBricks() {
+ /*
+ * We will need to mark the blocks that must have a bomb, we will here need to see, what is falling
+ */
+ bool bbomb[6][13]; //has a bomb on it!
+ bool falling[6][13]; //this is falling
+ bool getReady[6][13]; //getReady
+ for (int i=0;i<6;i++)
+ for (int j=0;j<13;j++) {
+ bbomb[i][j]=false; //All false by default
+ falling[i][j]=false;
+ if (board[i][j]>29)
+ getReady[i][j]=true;
+ else
+ getReady[i][j]=false;
+ }
+ //See that is falling
+ for (int i=0;i<6;i++) {
+ bool rowFalling = false;
+ for (int j=0;j<13;j++) {
+ if (rowFalling)
+ falling[i][j]=true;
+ if ((!rowFalling)&&(board[i][j]%30==-1))
+ rowFalling = true;
+ if ((rowFalling)&&(board[i][j]%30>6))
+ rowFalling = false;
+ if (getReady[i][j]) {
+ falling[i][j]=true; //getReady is the same as falling
+ rowFalling = false;
+ }
+ }
+ }
+ //Now looking at rows:
+ for (int i=0;i<6;i++) {
+ int count = 0;
+ int color = -1;
+ for (int j=1;j<13;j++) {
+ if ((board[i][j]%30==color)&&(!falling[i][j]))
+ count++;
+ else
+ if (falling[i][j]) {
+ count = 0;
+ }
+ else {
+ color=board[i][j]%30;
+ count=1;
+ }
+ if ((count>2)&&(color>-1)&&(color)<7) {
+ bbomb[i][j]=true;
+ bbomb[i][j-1]=true;
+ bbomb[i][j-2]=true;
+ }
+ }
+ }
+ //now looking for lines
+ for (int i=1;i<13;i++) {
+ int count = 0;
+ int color = -1;
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]%30==color)&&(!falling[j][i]))
+ count++;
+ else
+ if (falling[j][i]) {
+ count = 0;
+ }
+ else {
+ color=board[j][i]%30;
+ count=1;
+ }
+ if ((count>2)&&(color>-1)&&(color<7)) {
+ bbomb[j][i]=true;
+ bbomb[j-1][i]=true;
+ bbomb[j-2][i]=true;
+ }
+ }
+ }
+ for (int i=0;((i<13)&&(i<30));i++)
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]%10 != -1) && (board[j][i]%30 < 7)) {
+ DrawIMG(bricks[board[j][i]%10], sBoard, j*bsize, 12*bsize-i*bsize-pixels);
+ if (bbomb[j][i])
+ DrawIMG(bomb[(ticks/BOMBTIME)%2], sBoard, j*bsize, 12*bsize-i*bsize-pixels);
+ if (getReady[j][i])
+ DrawIMG(ready[(ticks/READYTIME)%2], sBoard, j*bsize, 12*bsize-i*bsize-pixels);
+ }
+ if (board[j][i]%30>6) {
+ if (board[j][i]%30==7)
+ DrawIMG(garbageR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==9)
+ DrawIMG(garbageML, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==10)
+ DrawIMG(garbageMR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==11)
+ DrawIMG(garbageTR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==12)
+ DrawIMG(garbageTL, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==13)
+ DrawIMG(garbageBL, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==14)
+ DrawIMG(garbageBR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==15)
+ DrawIMG(garbageM, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==16)
+ DrawIMG(garbageFill, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==17)
+ DrawIMG(garbageT, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==18)
+ DrawIMG(garbageB, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==19)
+ DrawIMG(garbageL, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
+ if (board[j][i]%30==20)
+ switch(j) {
+ case 0:
+ DrawIMG(garbageGML, sBoard,j*bsize, 12*bsize-i*bsize-pixels);
+ break;
+ case 5:
+ DrawIMG(garbageGMR, sBoard,j*bsize, 12*bsize-i*bsize-pixels);
+ break;
+ default:
+ DrawIMG(garbageGM, sBoard,j*bsize, 12*bsize-i*bsize-pixels);
+ }
+ //cout << "IS: " << board[j][i] << endl;
+ }
+
+
+ }
+
+ int garbageSize=0;
+ for (int i=0;i<20;i++) {
+ if ((board[0][i]%30==12)&&(garbageSize>0)) {
+ DrawIMG(smiley[0], sBoard, 2*bsize, bsize-i*bsize-pixels+(bsize/2)*garbageSize);
+ }
+ if (board[0][i]%30!=19) //not in garbage
+ {
+ garbageSize=0;
+ }
+ else {
+ //cout << "In garbage" << endl;
+ garbageSize++;
+ }
+
+ }
+ }
+
+ //Draws everything
+ void BlockGame::DoPaintJob() {
+ DrawIMG(backBoard, sBoard, 0, 0);
+ #if NETWORK
+ if ((!bReplaying)&&(!bNetworkPlayer))
+ #else
+ if (!bReplaying)
+ #endif
+ PaintBricks();
+ else
+ SimplePaintBricks();
+ if (stageClear) DrawIMG(blackLine, sBoard, 0, bsize*(12+2)+bsize*(stageClearLimit-linesCleared)-pixels-1);
+ if (puzzleMode&&(!bGameOver)) {
+ //We need to write nr. of moves left!
+ strHolder = "Moves left: " + itoa(MovesLeft);
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+ if(puzzleMode && stageButtonStatus == SBpuzzleMode)
+ {
+ DrawIMG(bRetry,sBoard, cordRetryButton.x, cordRetryButton.y);
+ if(Level<nrOfPuzzles-1)
+ {
+ if(hasWonTheGame)
+ DrawIMG(bNext,sBoard,cordNextButton.x, cordNextButton.y);
+ else
+ DrawIMG(bSkip,sBoard,cordNextButton.x, cordNextButton.y);
+ }
+ else
+ {
+ strHolder = "Last puzzle";
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+ }
+ if(stageClear && stageButtonStatus == SBstageClear)
+ {
+ DrawIMG(bRetry,sBoard, cordRetryButton.x, cordRetryButton.y);
+ if(Level<50-1)
+ {
+ if(hasWonTheGame)
+ DrawIMG(bNext,sBoard,cordNextButton.x, cordNextButton.y);
+ else
+ DrawIMG(bSkip,sBoard,cordNextButton.x, cordNextButton.y);
+ }
+ else
+ {
+ strHolder = "Last stage";
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+ }
+
+#if DEBUG
+ if (AI_Enabled&&(!bGameOver)) {
+ strHolder = "AI_status: " + itoa(AIstatus)+ ", "+ itoa(AIlineToClear);
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+#endif
+ if (!bGameOver)DrawIMG(cursor[(ticks/600)%2],sBoard,cursorx*bsize-4,11*bsize-cursory*bsize-pixels-4);
+ if (ticks<gameStartedAt)
+ {
+ int currentCounter = abs((int)ticks-(int)gameStartedAt)/1000;
+ if( (currentCounter!=lastCounter) && (SoundEnabled)&&(!NoSound))
+ Mix_PlayChannel(1,counterChunk,0);
+ lastCounter = currentCounter;
+ switch (currentCounter) {
+ case 2:
+ DrawIMG(counter[2], sBoard, 2*bsize, 5*bsize);
+ break;
+ case 1:
+ DrawIMG(counter[1], sBoard, 2*bsize, 5*bsize);
+ break;
+ case 0:
+ DrawIMG(counter[0], sBoard, 2*bsize, 5*bsize);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if(SoundEnabled&&(!NoSound)&&(timetrial)&&(ticks>gameStartedAt+10000)&&(!bGameOver))
+ {
+ int currentCounter = (ticks-(int)gameStartedAt)/1000;
+ if(currentCounter!=lastCounter)
+ {
+ if(currentCounter>115 && currentCounter<120)
+ Mix_PlayChannel(1,counterChunk,0);
+ }
+ lastCounter = currentCounter;
+ }
+ else
+ {
+ if( (0==lastCounter) && (SoundEnabled)&&(!NoSound))
+ {
+ Mix_PlayChannel(1,counterFinalChunk,0);
+ }
+ lastCounter = -1;
+ }
+ }
+
+ if ((bGameOver)&&(!editorMode))
+ if (hasWonTheGame)DrawIMG(iWinner, sBoard, 0, 5*bsize);
+ else if (bDraw) DrawIMG(iDraw, sBoard, 0, 5*bsize);
+ else
+ DrawIMG(iGameOver, sBoard, 0, 5*bsize);
+ }
+
+ #endif
+
+ //Updates evrything, if not called nothing happends
+ void BlockGame::Update() {
+ Uint32 tempUInt32;
+ Uint32 nowTime = ticks; //We remember the time, so it doesn't change during this call
+ if (bReplaying) {
+ setBoard(theReplay.getFrameSec((Uint32)(nowTime-gameStartedAt)));
+ strncpy(name,theReplay.name,30);
+ if (theReplay.isFinnished((Uint32)(nowTime-gameStartedAt)))
+ switch (theReplay.getFinalStatus()) {
+ case 1: //Winner
+ bGameOver = true;
+ hasWonTheGame = true;
+ break;
+ case 2: //Looser
+ case 4: //GameOver
+ bGameOver = true;
+ break;
+ case 3: //draw
+ bGameOver =true;
+ bDraw = true;
+ break;
+ default:
+ bGameOver = true;
+ //Nothing
+ break;
+ };
+ }
+ #if NETWORK
+ if ((!bReplaying)&&(!bNetworkPlayer)) {
+ #else
+ if (!bReplaying) {
+ #endif
+ FindTowerHeight();
+ if ((linesCleared-TowerHeight>stageClearLimit) && (stageClear) && (!bGameOver)) {
+ stageCleared[Level] = true;
+ if(stageScores[Level]<score)
+ {
+ gameEndedAfter = nowTime-gameStartedAt;
+ stageScores[Level] = score;
+ stageTimes[Level] = gameEndedAfter;
+ }
+
+ ofstream outfile;
+ outfile.open(stageClearSavePath.c_str(), ios::binary |ios::trunc);
+ if (!outfile) {
+ cout << "Error writing to file: " << stageClearSavePath << endl;
+ }
+ else {
+ for (int i=0;i<nrOfStageLevels;i++) {
+ bool tempBool = stageCleared[i];
+ outfile.write(reinterpret_cast<char*>(&tempBool), sizeof(bool));
+ }
+ for (int i=0;i<nrOfStageLevels;i++) {
+ tempUInt32 = stageScores[i];
+ outfile.write(reinterpret_cast<char*>(&tempUInt32), sizeof(Uint32));
+ }
+ for (int i=0;i<nrOfStageLevels;i++) {
+ tempUInt32 = stageTimes[i];
+ outfile.write(reinterpret_cast<char*>(&tempUInt32), sizeof(Uint32));
+ }
+ outfile.close();
+ }
+ setPlayerWon();
+ stageButtonStatus = SBstageClear;
+ }
+ if ((TowerHeight>12)&&(prevTowerHeight<13)&&(!puzzleMode)) {
+ //if (SoundEnabled) Mix_PlayChannel(1, heartBeat, 0);
+ stop+=1000;
+ }
+
+ if ((TowerHeight>12)&&(!puzzleMode)&&(!bGameOver)) {
+ bNearDeath = true;
+ }
+
+ while (nowTime>nrStops*40+gameStartedAt) //Increase stops, till we reach nowTime
+ {
+ if (stop>0) {
+ stop = stop-20;
+ if (stop<=0) nrPushedPixel=(int)((nowTime-gameStartedAt)/(1000.0*speed));
+ }
+ if (stop<0)
+ stop = 0;
+ nrStops++;
+ }
+ //If we have static content, we don't raise at all!
+ if (hasStaticContent())
+ stop++;
+ if ((puzzleMode)&&(!bGameOver)&&BoardEmpty()) {
+ if (!singlePuzzle) {
+ if(puzzleCleared[Level]==false)
+ Stats::getInstance()->addOne("puzzlesSolved");
+ puzzleCleared[Level] = true;
+ ofstream outfile;
+ stageButtonStatus = SBpuzzleMode;
+ outfile.open(puzzleSavePath.c_str(), ios::binary |ios::trunc);
+ if (!outfile) {
+ cout << "Error writing to file: " << puzzleSavePath << endl;
+ }
+ else {
+ for (int i=0;i<nrOfPuzzles;i++) {
+ bool tempBool = puzzleCleared[i];
+ outfile.write(reinterpret_cast<char*>(&tempBool), sizeof(bool));
+ }
+ outfile.close();
+ }
+ }
+ setPlayerWon();
+ }
+
+ //increse speed:
+ if ((nowTime>gameStartedAt+20000*speedLevel)&&(speedLevel <99)&&(!bGameOver))
+ {
+ speed = (baseSpeed*0.9)/((double)speedLevel*0.5);
+ speedLevel++;
+ nrPushedPixel=(int)((double)(nowTime-gameStartedAt)/(1000.0*speed));
+ }
+
+
+ //To prevent the stack from raising a lot then we stop a chain (doesn't work anymore)
+ if (chain>0)
+ stop+=1;
+ //Raises the stack
+ if ((nowTime>gameStartedAt+nrPushedPixel*1000*speed) && (!bGameOver)&&(!stop))
+ while ((nowTime>gameStartedAt+nrPushedPixel*1000*speed)&&(!(puzzleMode)))
+ PushPixels();
+ if (!bGameOver)ClearBlocks();
+
+ /*************************************************************
+ Ai stuff
+ **************************************************************/
+ if (bGameOver) {
+ AIstatus = 0; //Enusres that AI is resetted
+ }
+ else
+ if (AI_Enabled)
+ if (lastAImove+AI_MoveSpeed<ticks) {
+ AI_Move();
+ lastAImove=ticks;
+ }
+
+ /*************************************************************
+ Ai stuff ended
+ **************************************************************/
+ if ((nowTime>gameStartedAt+nrFellDown*140) && (!bGameOver)) FallDown();
+ if ((nowTime<gameStartedAt)&&(puzzleMode)) {
+ FallDown();
+ nrFellDown--;
+ }
+ ReduceStuff();
+ if ((timetrial) && (!bGameOver) && (nowTime>gameStartedAt+2*60*1000)) {
+ SetGameOver();
+ if(!NoSound && SoundEnabled)Mix_PlayChannel(1,counterFinalChunk,0);
+ if ((theTopScoresTimeTrial.isHighScore(score))&&(!AI_Enabled)) {
+ theTopScoresTimeTrial.addScore(name, score);
+ //new highscore
+ //Also check if it is better than the best result so far.
+ string checkFilename = getPathToSaveFiles() + "/bestTTresult";
+ ifstream inFile(checkFilename.c_str());
+ Uint32 bestResult = 3000; //Never accept a best result under 3000
+ if(inFile)
+ {
+ inFile >> bestResult;
+ inFile.close();
+ }
+ if(score>bestResult)
+ {
+ string bestFile = getPathToSaveFiles() + "/bestTT";
+ theReplay.saveReplay(bestFile);
+ ofstream outFile(checkFilename.c_str(),ios::trunc);
+ if(outFile)
+ outFile << score;
+ }
+ }
+ }
+ }
+ if ((!bGameOver)&&(!bReplaying)&&(nowTime>gameStartedAt))
+ {
+ //cout << nowTime << " bigger than " << gameStartedAt << endl;
+ theReplay.setFrameSecTo(nowTime-gameStartedAt, getPackage());
+ }
+ DoPaintJob();
+ }
+
+ void BlockGame::Update(int newtick) {
+ ticks = newtick;
+ Update();
+ }
+////////////////////////////////////////////////////////////////////////////////
+///////////////////////// BlockAttack class end ////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
diff --git a/source/code/BlockGame.hpp b/source/code/BlockGame.hpp index 7187c71..b60c9cb 100644 --- a/source/code/BlockGame.hpp +++ b/source/code/BlockGame.hpp
@@ -23,10 +23,28 @@
* blockattack@poulsander.com
*/
+#ifndef BLOCKGAME_HPP
+#define BLOCKGAME_HPP 1
+
#include "stats.h"
#include "common.h"
-#include "mainVars.hpp"
-
+#include "SDL.h"
+#include "replay.h"
+
+#define WITH_SDL 1
+
+//Some definitions
+//The game is divided in frames. FALLTIME means the blocks will fall one block every FRAMELENGTH*FALLTIME millisecond
+#define FRAMELENGTH 50
+#define HANGTIME 40
+#define FALLTIME 20
+//Don't change the following, they are fundamental and later some functions are hardcoded
+#define BLOCKFALL 10000
+#define BLOCKWAIT 100000
+#define BLOCKHANG 1000
+#define GARBAGE 1000000
+#define CHAINPLACE 10000000
+#define NUMBEROFCHAINS 100
////////////////////////////////////////////////////////////////////////////////
//The BloackGame class represents a board, score, time etc. for a single player/
@@ -58,22 +76,8 @@ private:
Uint32 nextRandomNumber;
- Uint16 rand2() {
- nextRandomNumber = nextRandomNumber*1103515245 + 12345;
- return ((Uint16)(nextRandomNumber/65536)) % 32768;
- }
-
- int firstUnusedChain() {
- bool found=false;
- int i = 0;
- while (!found) {
- if (!chainUsed[++i])
- found=true;
- if (i>NUMBEROFCHAINS-2)
- found=true;
- }
- return i;
- }
+ Uint16 rand2();
+ int firstUnusedChain();
//public:
Uint32 gameStartedAt;
@@ -112,2376 +116,206 @@ public:
#endif
//Constructor
- BlockGame(int tx, int ty) {
- #if WITH_SDL
- tmp = IMG_Load2((char*)"gfx/BackBoard.png");
- sBoard = SDL_DisplayFormat(tmp);
- SDL_FreeSurface(tmp);
- #endif
- srand((int)time(NULL));
- nrFellDown = 0;
- nrPushedPixel = 0;
- garbageTarget = this;
- nrStops=0;
- topx = tx;
- topy = ty;
- cursorx = 2;
- cursory = 3;
- stop = 0;
- pixels = 0;
- score = 0;
- bGameOver = false;
- bDraw = false;
- bReplaying=false; //No replay by default
- #if NETWORK
- bDisconnected=false;
- bNetworkPlayer = false;
- #endif
- timetrial = false;
- stageClear = false;
- vsMode = false;
- puzzleMode = false;
- linesCleared = 0;
- AI_Enabled = false;
- AI_MoveSpeed=100;
- hasWonTheGame = false;
- combo=0; //counts
- chain=0;
- hangTicks = 0;
- baseSpeed = 0.5; //All other speeds are relative to this
- speed = baseSpeed;
- speedLevel = 1;
- gameStartedAt = ticks;
- gameEndedAfter = 0;
- pushedPixelAt = gameStartedAt;
- nextGarbageNumber = 10;
- handicap=0;
- for (int i=0;i<7;i++)
- for (int j=0;j<30;j++) {
- board[i][j] = -1;
- }
- for (int i=0;i<NUMBEROFCHAINS;i++) {
- chainUsed[i]=false;
- chainSize[i] = 0;
- }
- theReplay = Replay();
- showGame = true; //The game is now active
- lastCounter = -1; //To prevent the final chunk to be played when stating the program
- } //Constructor
+ BlockGame(int tx, int ty);
//Deconstructor, never really used... game used to crash when called, cause of the way sBoard was created
//It should work now and can be used if we want to assign more players in network games that we need to free later
- ~BlockGame() {
- #if WITH_SDL
- SDL_FreeSurface(sBoard);
- #endif
- }
-
- void setGameSpeed(Uint8 globalSpeedLevel) {
- switch (globalSpeedLevel) {
- case 0:
- baseSpeed=0.5;
- break;
- case 1:
- baseSpeed=0.4;
- break;
- case 2:
- baseSpeed=0.3;
- break;
- case 3:
- baseSpeed=0.25;
- break;
- case 4:
- baseSpeed=0.2;
- break;
- default:
- baseSpeed=0.15;
- break;
- };
- }
-
- void setHandicap(Uint8 globalHandicap) {
- handicap=1000*((Uint32)globalHandicap);
- }
+ ~BlockGame();
+ void setGameSpeed(Uint8 globalSpeedLevel);
+ void setHandicap(Uint8 globalHandicap);
//Set the move speed of the AI based on the aiLevel parameter
//Also enables AI
- void setAIlevel(Uint8 aiLevel) {
- AI_Enabled = true;
- AI_MoveSpeed=120-(20*(aiLevel-3));
- };
-
- Uint8 getAIlevel() {
- return (120-AI_MoveSpeed)/20+3;
- }
-
- int GetScore() {
- return score;
- }
-
- int GetHandicap() {
- return handicap;
- }
-
- bool isGameOver() {
- return bGameOver;
- }
-
- int GetTopX() {
- return topx;
- }
-
- int GetTopY() {
- return topy;
- }
-
- unsigned int GetGameStartedAt() {
- return gameStartedAt;
- }
-
- unsigned int GetGameEndedAt() {
- return gameEndedAfter;
- }
-
- bool isTimeTrial() {
- return timetrial;
- }
-
- bool isStageClear() {
- return stageClear;
- }
-
- bool isVsMode() {
- return vsMode;
- }
-
- bool isPuzzleMode() {
- return puzzleMode;
- }
-
- int GetLinesCleared() {
- return linesCleared;
- }
-
- int GetStageClearLimit() {
- return stageClearLimit;
- }
-
- int GetChains() {
- return chain;
- }
-
- int GetPixels() {
- return pixels;
- }
-
- int GetSpeedLevel() {
- return speedLevel;
- }
-
- int GetTowerHeight() {
- return TowerHeight;
- }
-
- int GetCursorX() {
- return cursorx;
- }
-
- int GetCursorY() {
- return cursory;
- }
-
- void MoveCursorTo(int x, int y) {
- cursorx = x;
- cursory = y;
- }
-
- bool GetIsWinner() {
- return hasWonTheGame;
- }
-
+ void setAIlevel(Uint8 aiLevel);
+ Uint8 getAIlevel();
+
+ int GetScore();
+ int GetHandicap();
+ bool isGameOver();
+ int GetTopX();
+ int GetTopY();
+ unsigned int GetGameStartedAt();
+ unsigned int GetGameEndedAt();
+ bool isTimeTrial();
+ bool isStageClear();
+ bool isVsMode();
+ bool isPuzzleMode();
+ int GetLinesCleared();
+ int GetStageClearLimit();
+ int GetChains();
+ int GetPixels();
+ int GetSpeedLevel();
+ int GetTowerHeight();
+ int GetCursorX();
+ int GetCursorY();
+ void MoveCursorTo(int x, int y);
+ bool GetIsWinner();
private:
#if NETWORK
#define garbageStackSize 10
Uint8 garbageStack[garbageStackSize][3]; //A garbage stack with space for 10 garbage blocks. 0=x,1=y,2=type
int garbageStackUsed;
- void emptyGarbageStack() {
- for (int i=0;i<10;i++)
- for (int j=0;j<3;j++)
- garbageStack[i][j] = 0;
- garbageStackUsed = 0;
- }
-
- bool pushGarbage(Uint8 width, Uint8 height, Uint8 type) {
- if (garbageStackUsed>=garbageStackSize)
- return false;
- garbageStack[garbageStackUsed][0]=width;
- garbageStack[garbageStackUsed][1]=height;
- garbageStack[garbageStackUsed][2]=type;
- garbageStackUsed++;
- return true;
- }
+ void emptyGarbageStack();
+ bool pushGarbage(Uint8 width, Uint8 height, Uint8 type);
public:
- bool popGarbage(Uint8 *width, Uint8 *height, Uint8 *type) {
- if (garbageStackUsed<1)
- return false;
- garbageStackUsed--;
- *width=garbageStack[garbageStackUsed][0];
- *height=garbageStack[garbageStackUsed][1];
- *type=garbageStack[garbageStackUsed][2];
- return true;
- }
+ bool popGarbage(Uint8 *width, Uint8 *height, Uint8 *type);
private:
#endif
#if WITH_SDL
//Loads BackBoard again if surface format has changed
- void convertSurface() {
- SDL_FreeSurface(sBoard);
- sBoard = SDL_DisplayFormat(backBoard);
- }
+ void convertSurface();
#endif
public:
//Instead of creating new object new game is called, to prevent memory leaks
- void NewGame(int tx, int ty, unsigned int ticks) {
- this->ticks = ticks;
- stageButtonStatus = SBdontShow;
- bReplaying = false;
- #if NETWORK
- bNetworkPlayer=false;
- bDisconnected =false;
- #endif
- nrFellDown = 0;
- lastNrOfPlayers = 1; //At least one player :-)
- nrPushedPixel = 0;
- nrStops = 0;
- topx = tx;
- topy = ty;
- cursorx = 2;
- cursory = 3;
- stop = 0;
- pixels = 0;
- score = 0;
- bGameOver = false;
- bDraw = false;
- timetrial = false;
- stageClear = false;
- linesCleared = 0;
- hasWonTheGame = false;
- vsMode = false;
- puzzleMode = false;
- combo=0;
- chain=0;
- AI_Enabled = false;
- baseSpeed= 0.5;
- speed = baseSpeed;
- speedLevel = 1;
- gameStartedAt = ticks+3000;
- pushedPixelAt = gameStartedAt;
- nextGarbageNumber = 10;
- handicap=0;
- for (int i=0;i<7;i++)
- for (int j=0;j<30;j++) {
- board[i][j] = -1;
- }
- for (int i=0;i<NUMBEROFCHAINS;i++) {
- chainUsed[i]=false;
- chainSize[i] = 0;
- }
- lastAImove = ticks+3000;
- showGame = true;
- theReplay = Replay();
- } //NewGame
-
- void NewTimeTrialGame(int x,int y, unsigned int ticks) {
- NewGame(x,y,ticks);
- timetrial = true;
- putStartBlocks();
- }
-
+ void NewGame(int tx, int ty, unsigned int ticks);
+ void NewTimeTrialGame(int x,int y, unsigned int ticks);
//Starts a new stage game, takes level as input!
- void NewStageGame(int level, int tx, int ty,unsigned int ticks) {
- if (level > -1) {
- NewGame(tx, ty,ticks);
- stageClear = true;
- Level = level;
- Stats::getInstance()->addOne("PlayedStageLevel"+itoa2(level));
- stageClearLimit = 30+(Level%6)*10;
- baseSpeed = 0.5/((double)(Level*0.5)+1.0);
- speed = baseSpeed;
- }
- }
-
- void NewPuzzleGame(int level, int tx, int ty, unsigned int ticks) {
- if (level>-1) {
- NewGame(tx, ty,ticks);
- puzzleMode = true;
- Level = level;
- MovesLeft = nrOfMovesAllowed[Level];
- for (int i=0;i<6;i++)
- for (int j=0;j<12;j++) {
- board[i][j+1] = puzzleLevels[Level][i][j];
- }
- baseSpeed = 100000;
- speed = 100000;
-
- //Now push the blines up
- for (int i=19;i>0;i--)
- for (int j=0;j<6;j++) {
- board[j][i] = board[j][i-1];
- }
- for (int j=0;j<6;j++) {
- board[j][0] = rand() % 6;
- if (j > 0) {
- if (board[j][0] == board[j-1][0])
- board[j][0] = rand() % 6;
- }
- if (board[j][0] == board[j][1])
- board[j][0] = 6;
- if (board[j][0] == board[j][1])
- board[j][0] = 6;
-
- }
- }
- }
-
+ void NewStageGame(int level, int tx, int ty,unsigned int ticks);
+ void NewPuzzleGame(int level, int tx, int ty, unsigned int ticks);
//Replay the current level
- void retryLevel(unsigned int ticks)
- {
- if(puzzleMode)
- NewPuzzleGame(Level,topx,topy,ticks);
- else
- if(stageClear)
- NewStageGame(Level,topx,topy,ticks);
- }
-
+ void retryLevel(unsigned int ticks);
//Play the next level
- void nextLevel(unsigned int ticks)
- {
- if(puzzleMode)
- {
- if(Level<nrOfPuzzles-1)
- NewPuzzleGame(Level+1,topx,topy,ticks);
- }
- else
- if(stageClear)
- {
- if(Level<50-1)
- NewStageGame(Level+1,topx,topy,ticks);
- }
- }
-
+ void nextLevel(unsigned int ticks);
//Starts new Vs Game (two Player)
- void NewVsGame(int tx, int ty, BlockGame *target,unsigned int ticks) {
- NewGame(tx, ty,ticks);
- vsMode = true;
- putStartBlocks();
- garbageTarget = target;
- Stats::getInstance()->addOne("VSgamesStarted");
- }
-
+ void NewVsGame(int tx, int ty, BlockGame *target,unsigned int ticks);
//Starts new Vs Game (two Player)
- void NewVsGame(int tx, int ty, BlockGame *target, bool AI,unsigned int ticks) {
- NewGame(tx, ty,ticks);
- vsMode = true;
- AI_Enabled = AI;
- if(!AI)
- Stats::getInstance()->addOne("VSgamesStarted");
- else
- strcpy(name,"CPU\0");
- putStartBlocks();
- garbageTarget = target;
- }
+ void NewVsGame(int tx, int ty, BlockGame *target, bool AI,unsigned int ticks);
private:
-
//Go in Demonstration mode, no movement
- void Demonstration(bool toggle) {
- speed=0;
- baseSpeed = 0;
- }
+ void Demonstration(bool toggle);
public:
//We want to play the replay (must have been loaded beforehand)
- void playReplay(int tx, int ty, unsigned int ticks) {
- NewGame(tx, ty,ticks);
- gameStartedAt = ticks;
- bReplaying = true; //We are playing, no calculations
- #if NETWORK
- bNetworkPlayer = false; //Take input from replay file
- #endif
- }
-
-
+ void playReplay(int tx, int ty, unsigned int ticks);
#if NETWORK
-
//network play
- void playNetwork(int tx, int ty,unsigned int ticks) {
- NewGame(tx, ty,ticks);
- gameStartedAt = ticks;
- bReplaying = false; //We are playing, no calculations
- bNetworkPlayer = true; //Don't Take input from replay file
- emptyGarbageStack();
- }
+ void playNetwork(int tx, int ty,unsigned int ticks);
#endif
-
//Prints "winner" and ends game
- void setPlayerWon() {
- if (!bGameOver)
- {
- gameEndedAfter = ticks-gameStartedAt; //We game ends now!
- if(!AI_Enabled && !bReplaying)
- {
- TimeHandler::addTime("playTime",TimeHandler::ms2ct(gameEndedAfter));
- }
- }
- theReplay.setFinalFrame(getPackage(), 1);
- bGameOver = true;
- hasWonTheGame = true;
- showGame = false;
- if (SoundEnabled)Mix_PlayChannel(1, applause, 0);
- if(!AI_Enabled && !bReplaying)
- {
- Stats::getInstance()->addOne("totalWins");
- if(garbageTarget->AI_Enabled && !(garbageTarget->bReplaying))
- {
- //We have defeated an AI
- Stats::getInstance()->addOne("defeatedAI"+itoa(garbageTarget->getAIlevel()));
- }
- }
- if(AI_Enabled && !(garbageTarget->AI_Enabled) && garbageTarget->bReplaying==false)
- {
- //The AI have defeated a human player
- Stats::getInstance()->addOne("defeatedByAI"+itoa(getAIlevel()));
- }
- }
-
+ void setPlayerWon();
//void SetGameOver();
#if NETWORK
//Sets disconnected:
- void setDisconnect() {
- bDisconnected = true;
- SetGameOver();
- }
+ void setDisconnect();
#endif
-
//Prints "draw" and ends the game
- void setDraw() {
- bGameOver = true;
- if(!AI_Enabled && !bReplaying)
- {
- TimeHandler::addTime("playTime",TimeHandler::ms2ct(gameEndedAfter));
- }
- theReplay.setFinalFrame(getPackage(), 3);
- hasWonTheGame = false;
- bDraw = true;
- showGame = false;
- Mix_HaltChannel(1);
- if(!AI_Enabled && !bReplaying)
- Stats::getInstance()->addOne("totalDraws");
- }
-
+ void setDraw();
//Function to get a boardpackage
- boardPackage getPackage() {
- boardPackage bp;
- if(ticks<gameStartedAt)
- bp.time = 0;
- else
- bp.time = (Uint32)(ticks-gameStartedAt);
- for (int i=0;i<6;i++)
- for (int j=0;j<13;j++) {
- if (board[i][j]%10<7)
- bp.brick[i][j]=board[i][j]%10+1;
- if ((board[i][j]/1000000)%10==1)
- {
- //Ordinary garbage
- int aInt=0; //N=1, S=2, W=4, E=8
- if (i==0)
- aInt+=4;
- else
- if ((board[i-1][j])!=(board[i][j]))
- aInt+=4;
- if (i==5)
- aInt+=8;
- else
- if ((board[i+1][j])!=(board[i][j]))
- aInt+=8;
- if (j==0)
- aInt+=2;
- else
- if ((board[i][j-1])!=(board[i][j]))
- aInt+=2;
- if ((board[i][j+1])!=(board[i][j]))
- aInt+=1;
- switch (aInt) {
- case 8:
- bp.brick[i][j]=8;
- break;
- case 7:
- bp.brick[i][j]=10;
- break;
- case 11:
- bp.brick[i][j]=11;
- break;
- case 9:
- bp.brick[i][j]=12;
- break;
- case 5:
- bp.brick[i][j]=13;
- break;
- case 6:
- bp.brick[i][j]=14;
- break;
- case 10:
- bp.brick[i][j]=15;
- break;
- case 3: //M
- bp.brick[i][j]=16;
- break;
- case 0:
- bp.brick[i][j]=17;
- break;
- case 1:
- bp.brick[i][j]=18;
- break;
- case 2:
- bp.brick[i][j]=19;
- break;
- case 4:
- bp.brick[i][j]=20;
- break;
- default:
- bp.brick[i][j]=0;
- };
- //cout << "garbage added to replay: " << aInt << endl;
- }
- if ((board[i][j]/1000000)%10==2)
- {
- //Gray garbage
- bp.brick[i][j]=21;
- }
- if ((board[i][j]/BLOCKHANG)%10==1) //If "get ready"
- bp.brick[i][j]+=30;
- }
- bp.cursorX = (Uint8)cursorx;
- bp.cursorY = (Uint8)cursory;
- bp.score = (Uint32)score;
- bp.pixels = (Uint8)pixels;
- bp.chain = (Uint8)chain;
- bp.speed = (Uint8)speedLevel;
- Uint8 result = 0;
- if (bGameOver)
- result+=1;
- if (hasWonTheGame)
- result+=2;
- if (bDraw)
- result+=4;
- bp.result = (Uint8)result;
- return bp;
- }
-
+ boardPackage getPackage();
//Takes a package and sets the board like it
- void setBoard(boardPackage bp) {
- //gameStartedAt = ticks-bp.time;
- for (int i=0;i<6;i++)
- for (int j=0;j<13;j++) {
- //if(bp.brick[i][j]/8==0)
- board[i][j]=bp.brick[i][j]-1;
- //else
- // board[i][j]=-1;
- }
- cursorx=bp.cursorX;
- cursory=bp.cursorY;
- score=bp.score;
- pixels=bp.pixels;
- chain=bp.chain;
- speedLevel=bp.speed;
- Uint8 result = bp.result;
- bGameOver = false; //Make sure that it is initialized!
- if(result%2==1) {
- bGameOver=true;
- result-=1;
- }
- if (result%4==2) {
- hasWonTheGame = true;
- result-=2;
- }
- if (result==4) {
- bDraw = true;
- }
-
- }
-
+ void setBoard(boardPackage bp);
private:
-
//Test if LineNr is an empty line, returns false otherwise.
- bool LineEmpty(int lineNr) {
- bool empty = true;
- for (int i = 0; i <7; i++)
- if (board[i][lineNr] != -1)
- empty = false;
- return empty;
- }
-
+ bool LineEmpty(int lineNr);
//Test if the entire board is empty (used for Puzzles)
- bool BoardEmpty() {
- bool empty = true;
- for (int i=0;i<6;i++)
- for (int j=1;j<13;j++)
- if (board[i][j] != -1)
- empty = false;
- return empty;
- }
-
+ bool BoardEmpty();
//Anything that the user can't move? In that case Game Over cannot occur
- bool hasStaticContent() {
- for (int i=0;i<6;i++)
- for (int j=1;j<13;j++)
- if (board[i][j] >= 10000000) //Higher than this means combos (garbage is static, but the stack is static but nothing to do about it)
- return true; //They are static
- return false; //Return false if no static object found
- }
-
- /*
- * Generates some blocks so the user don't see a board without blocks
- */
- //void putStartBlocks(Uint32);
-
- void putStartBlocks() {
- putStartBlocks(time(0));
- }
-
+ bool hasStaticContent();
+ void putStartBlocks();
public:
- void putStartBlocks(Uint32 n) {
- for (int i=0;i<7;i++)
- for (int j=0;j<30;j++) {
- board[i][j] = -1;
- }
- nextRandomNumber = n;
- int choice = rand2()%3; //Pick a random layout
- switch (choice) {
- case 0:
- //row 0:
- board[0][0]=1;
- board[1][0]=0;
- board[2][0]=4;
- board[3][0]=3;
- board[4][0]=3;
- board[5][0]=5;
- //row 1:
- board[0][1]=1;
- board[1][1]=4;
- board[2][1]=2;
- board[3][1]=0;
- board[4][1]=4;
- board[5][1]=5;
- //row 2:
- board[0][2]=2;
- board[1][2]=3;
- board[2][2]=0;
- board[3][2]=4;
- board[4][2]=1;
- board[5][2]=1;
- //row 3:
- board[0][3]=3;
- board[1][3]=2;
- board[2][3]=3;
- board[3][3]=1;
- board[4][3]=0;
- board[5][3]=4;
- //row 4:
- board[0][4]=2;
- board[1][4]=3;
- board[2][4]=3;
- board[3][4]=1;
- board[4][4]=4;
- board[5][4]=0;
- //row 5:
- board[0][5]=-1;
- board[1][5]=5;
- board[2][5]=5;
- board[3][5]=-1;
- board[4][5]=1;
- board[5][5]=-1;
- break;
- case 1:
- //row 0:
- board[0][0]=3;
- board[1][0]=5;
- board[2][0]=0;
- board[3][0]=0;
- board[4][0]=4;
- board[5][0]=2;
- //row 1:
- board[0][1]=3;
- board[1][1]=5;
- board[2][1]=-1;
- board[3][1]=5;
- board[4][1]=4;
- board[5][1]=2;
- //row 2:
- board[0][2]=2;
- board[1][2]=-1;
- board[2][2]=-1;
- board[3][2]=4;
- board[4][2]=0;
- board[5][2]=3;
- //row 3:
- board[0][3]=2;
- board[5][3]=3;
- break;
- default:
- //row 0:
- board[0][0]=4;
- board[1][0]=5;
- board[2][0]=2;
- board[3][0]=0;
- board[4][0]=1;
- board[5][0]=5;
- //row 1:
- board[0][1]=4;
- board[1][1]=5;
- board[2][1]=2;
- board[3][1]=1;
- board[4][1]=0;
- board[5][1]=2;
- //row 2:
- board[0][2]=2;
- board[1][2]=4;
- board[2][2]=-1;
- board[3][2]=0;
- board[4][2]=1;
- board[5][2]=5;
- //row 3:
- board[0][3]=4;
- board[1][3]=2;
- board[2][3]=-1;
- board[3][3]=1;
- board[4][3]=0;
- board[5][3]=2;
- //row 4:
- board[0][4]=4;
- board[1][4]=2;
- board[2][4]=-1;
- board[3][4]=0;
- board[4][4]=1;
- board[5][4]=-1;
- break;
- };
- }
-
+ void putStartBlocks(Uint32 n);
private:
-
//decreases hang for all hanging blocks and wait for waiting blocks
- void ReduceStuff() {
- Uint32 howMuchHang = (ticks - FRAMELENGTH*hangTicks)/FRAMELENGTH;
- if (howMuchHang>0) {
- for (int i=0; i<7; i++)
- for (int j=0; j<30; j++) {
- if ((board[i][j]/BLOCKHANG)%10==1) {
- int hangNumber = (board[i][j]/10)%100;
- if (hangNumber<=howMuchHang) {
- board[i][j]-=BLOCKHANG;
- board[i][j]-=hangNumber*10;
- }
- else {
- board[i][j]-=10*howMuchHang;
- }
- }
- if ((board[i][j]/BLOCKWAIT)%10==1) {
- int hangNumber = (board[i][j]/10)%100;
- if (hangNumber<=howMuchHang) {
- //The blocks must be cleared
- board[i][j]-=hangNumber*10;
- }
- else {
- board[i][j]-=10*howMuchHang;
- }
- }
- }
- }
- hangTicks+=howMuchHang;
- }
-
+ void ReduceStuff();
public:
-
//Creates garbage using a given wide and height
- bool CreateGarbage(int wide, int height) {
-#if NETWORK
- if (bNetworkPlayer) {
- pushGarbage(wide, height, 0);
- }
- else
-#endif
- {
- if (wide>6) wide = 6;
- if (height>12) height = 12;
- int startPosition = 12;
- while ((!(LineEmpty(startPosition))) || (startPosition == 29))
- startPosition++;
- if (startPosition == 29) return false; //failed to place blocks
- if (29-startPosition<height) return false; //not enough space
- int start, end;
- if (bGarbageFallLeft)
- {
- start=0;
- end=start+wide;
- bGarbageFallLeft = false;
- }
- else
- {
- start=6-wide;
- end = 6;
- bGarbageFallLeft = true;
- }
- for (int i = startPosition; i <startPosition+height; i++)
- for (int j = start; j < end; j++) {
- board[j][i] = 1000000+nextGarbageNumber;
- }
- nextGarbageNumber++;
- if (nextGarbageNumber>999999) nextGarbageNumber = 10;
- //bGarbageFallLeft = !(bGarbageFallLeft);
- return true;
- }
- }
-
+ bool CreateGarbage(int wide, int height);
//Creates garbage using a given wide and height
- bool CreateGreyGarbage() {
-#if NETWORK
- if (bNetworkPlayer) {
- pushGarbage(6, 1, 1);
- }
- else
-#endif
- {
- int startPosition = 12;
- while ((!(LineEmpty(startPosition))) || (startPosition == 29))
- startPosition++;
- if (startPosition == 29) return false; //failed to place blocks
- if (29-startPosition<1) return false; //not enough space
- int start, end;
- {
- start=0;
- end=6;
- }
- for (int i = startPosition; i <startPosition+1; i++)
- for (int j = start; j < end; j++) {
- board[j][i] = 2*1000000+nextGarbageNumber;
- }
- nextGarbageNumber++;
- if (nextGarbageNumber>999999) nextGarbageNumber = 10;
- return true;
- }
- }
-
+ bool CreateGreyGarbage();
private:
-
//Clears garbage, must take one the lower left corner!
- int GarbageClearer(int x, int y, int number, bool aLineToClear, int chain) {
- if ((board[x][y])%1000000 != number) return -1;
- if (aLineToClear) {
- board[x][y] = rand() % 6;
- board[x][y] += 10*HANGTIME+BLOCKHANG+CHAINPLACE*chain;
- }
- garbageToBeCleared[x][y] = false;
- GarbageClearer(x+1, y, number, aLineToClear, chain);
- GarbageClearer(x, y+1, number, false, chain);
- return 1;
- }
-
+ int GarbageClearer(int x, int y, int number, bool aLineToClear, int chain);
//Marks garbage that must be cleared
- int GarbageMarker(int x, int y) {
- if ((x>6)||(x<0)||(y<0)||(y>29)) return -1;
- if (((board[x][y])/1000000 == 1)&&(garbageToBeCleared[x][y] == false)) {
- garbageToBeCleared[x][y] = true;
- //Float fill
- GarbageMarker(x-1, y);
- GarbageMarker(x+1, y);
- GarbageMarker(x, y-1);
- GarbageMarker(x, y+1);
- }
- return 1;
- }
-
- int FirstGarbageMarker(int x, int y) {
- if ((x>6)||(x<0)||(y<0)||(y>29)) return -1;
- if (((board[x][y])/1000000 == 2)&&(garbageToBeCleared[x][y] == false)) {
- for (int i=0;i<6;i++)
- garbageToBeCleared[i][y] = true;
- }
- else
- if (((board[x][y])/1000000 == 1)&&(garbageToBeCleared[x][y] == false)) {
- garbageToBeCleared[x][y] = true;
- //Float fill
- GarbageMarker(x-1, y);
- GarbageMarker(x+1, y);
- GarbageMarker(x, y-1);
- GarbageMarker(x, y+1);
- }
- return 1;
- }
-
+ int GarbageMarker(int x, int y);
+ int FirstGarbageMarker(int x, int y);
//Clear Blocks if 3 or more is alligned (naive implemented)
- void ClearBlocks() {
-
- bool toBeCleared[7][30]; //true if blok must be removed
-
- int previus=-1; //the last block checked
- int combo=0;
- for (int i=0;i<30;i++)
- for (int j=0;j<7;j++) {
- toBeCleared[j][i] = false;
- garbageToBeCleared[j][i] = false;
- }
- for (int i=0;i<7;i++) {
- bool faaling = false;
- for (int j=0;j<30;j++) {
- if ((faaling)&&(board[i][j]>-1)&&(board[i][j]%10000000<7)) {
- board[i][j]+=BLOCKFALL;
- }
- if ((!faaling)&&((board[i][j]/BLOCKFALL)%10==1))
- board[i][j]-=BLOCKFALL;
- if (!((board[i][j]>-1)&&(board[i][j]%10000000<7)))
- faaling=true;
- if (((board[i][j]/1000000)%10==1)||((board[i][j]/1000000)%10==2)||((board[i][j]/BLOCKHANG)%10==1)||((board[i][j]/BLOCKWAIT)%10==1))
- faaling = false;
- }
- }
-
-
- for (int j=0;j<7;j++) {
- previus = -1;
- combo=0;
-
- for (int i=1;i<30;i++) {
- if ((board[j][i]>-1)&&(board[j][i]%10000000<7)) {
- if (board[j][i]%10000000 == previus) {
- combo++;
- }
- else {
- if (combo>2)
- for (int k = i-combo; k<i;k++) {
- toBeCleared[j][k] = true;
- }
- combo=1;
- previus = board[j][i]%10000000;
- }
- } //if board
- else {
- if (combo>2)
- for (int k = i-combo; k<i;k++) {
- toBeCleared[j][k] = true;
- }
- combo = 0;
- previus = -1;
- }
-
- } //for i
- } //for j
-
-
- combo = 0;
- chain = 0;
- for (int i=0; i<6;i++)
- for (int j=0; j<30;j++) {
- //Clears blocks marked for clearing
- Sint32 temp=board[i][j];
- if (1==((temp/BLOCKWAIT)%10))
- if (((temp/10)%100)==0) {
- if (chainSize[chain]<chainSize[board[i][j]/10000000])
- chain = board[i][j]/10000000;
-
- theBallManeger.addBall(topx+40+i*bsize, topy+bsize*12-j*bsize, true, board[i][j]%10);
- theBallManeger.addBall(topx+i*bsize, topy+bsize*12-j*bsize, false, board[i][j]%10);
- theExplosionManeger.addExplosion(topx-10+i*bsize, topy+bsize*12-10-j*bsize);
- board[i][j]=-2;
- }
- }
- for (int i=0; i<7;i++) {
- bool setChain=false;
- for (int j=0; j<30;j++) {
- if (board[i][j]==-1)
- setChain=false;
- if (board[i][j]==-2) {
- board[i][j]=-1;
- setChain=true;
- if (SoundEnabled)Mix_PlayChannel(0, boing, 0);
- }
- if (board[i][j]!=-1)
- if ((setChain)&&((board[i][j]/GARBAGE)%10!=1)&&((board[i][j]/GARBAGE)%10!=2)) {
- board[i][j]=((board[i][j]%CHAINPLACE)+CHAINPLACE*chain);
- //somethingsGottaFall = true;
- }
-
- }
- }
- combo=0;
- int startvalue;
- if (pixels == 0)
- startvalue=1;
- else
- startvalue=0;
- for (int i=startvalue;i<30;i++) {
- previus=-1;
- combo=0;
- for (int j=0;j<7;j++) {
- if (((board[j][i]>-1)&&(board[j][i]%10000000<7))) {
- if (board[j][i]%10000000 == previus) {
- combo++;
- }
- else {
- if (combo>2)
- for (int k = j-combo; k<j;k++) {
- toBeCleared[k][i] = true;
- }
- combo=1;
- previus = board[j][i]%10000000;
- }
- } //if board
- else {
- if (combo>2)
- for (int k = j-combo; k<j;k++) {
- toBeCleared[k][i] = true;
- }
- combo = 0;
- previus = -1;
- }
-
- } //for j
- } //for i
- bool blockIsFalling[6][30]; //See that is falling
- for (int i=0;i<30;i++)
- for (int j=0;j<6;j++)
- blockIsFalling[j][i] = false;
-
-
-
- combo = 0;
- chain = 0;
- int grey = 0;
- for (int i=0;i<30;i++)
- for (int j=0;j<6;j++)
- if (toBeCleared[j][i]) {
- //see if any garbage is around:
- FirstGarbageMarker(j-1, i);
- FirstGarbageMarker(j+1, i);
- FirstGarbageMarker(j, i-1);
- FirstGarbageMarker(j, i+1);
- //that is checked now :-)
- if (board[j][i]%10000000==6)
- grey++;
- if ((vsMode) && (grey>2) && (board[j][i]%10000000==6))
- garbageTarget->CreateGreyGarbage();
- if ((board[j][i]>-1)&&(board[j][i]%10000000<7))
- board[j][i]+=BLOCKWAIT+10*FALLTIME;
-
- if (chainSize[board[j][i]/10000000]>chainSize[chain])
- chain=board[j][i]/10000000;
- combo++;
- stop+=140*combo;
- score +=10;
- if (combo>3)
- score+=3*combo; //More points if more cleared simontanously
- }
- score+=chainSize[chain]*100;
- if (chain==0) {
- chain=firstUnusedChain();
- chainSize[chain]=0;
- chainUsed[chain]=true;
- }
- chainSize[chain]++;
- for (int i=0;i<30;i++)
- for (int j=0;j<6;j++) {
- //if(board[j][i]/10==(BLOCKWAIT+10*FALLTIME)/10)
- if (toBeCleared[j][i]) {
- board[j][i]=(board[j][i]%10000000)+chain*10000000;
- }
- }
-
- { //This is here we add text to screen!
- bool dead = false;
- for (int i=29;i>=0;i--)
- for (int j=0;j<6;j++)
- if (toBeCleared[j][i]) {
- if (!dead) {
- dead=true;
- string tempS = itoa(chainSize[chain]);
- if (chainSize[chain]>1)
- theTextManeger.addText(topx-10+j*bsize, topy+12*bsize-i*bsize, tempS, 1000);
- }
- }
- } //This was there text was added
-
- if (vsMode)
- switch (combo) {
- case 0:
- case 1:
- case 2:
- case 3:
- break;
- case 4:
- garbageTarget->CreateGarbage(3, 1);
- break;
- case 5:
- garbageTarget->CreateGarbage(4, 1);
- break;
- case 6:
- garbageTarget->CreateGarbage(5, 1);
- break;
- case 7:
- garbageTarget->CreateGarbage(6, 1);
- break;
- case 8:
- garbageTarget->CreateGarbage(4, 1);
- garbageTarget->CreateGarbage(4, 1);
- break;
- case 9:
- garbageTarget->CreateGarbage(5, 1);
- garbageTarget->CreateGarbage(4, 1);
- break;
- case 10:
- garbageTarget->CreateGarbage(5, 1);
- garbageTarget->CreateGarbage(5, 1);
- break;
- case 11:
- garbageTarget->CreateGarbage(6, 1);
- garbageTarget->CreateGarbage(5, 1);
- break;
- case 12:
- garbageTarget->CreateGarbage(6, 1);
- garbageTarget->CreateGarbage(6, 1);
- break;
- case 13:
- garbageTarget->CreateGarbage(5, 1);
- garbageTarget->CreateGarbage(5, 1);
- garbageTarget->CreateGarbage(4, 1);
- break;
- default:
- garbageTarget->CreateGarbage(5, 1);
- garbageTarget->CreateGarbage(5, 1);
- garbageTarget->CreateGarbage(4, 1);
- break;
- }
- for (int i=0;i<30;i++)
- for (int j=0;j<6;j++)
- if (garbageToBeCleared[j][i]) {
- GarbageClearer(j, i, board[j][i]%1000000, true, chain); //Clears the blocks and all blocks connected to it.
- }
-
- chain=0;
-
- //Break chains (if a block is stable it is resetted to (chain == 0)):
- for (int i=0;i<7;i++) {
- bool faaling = false; //In the beginning we are NOT falling
- for (int j=0;j<30;j++) {
- if ((faaling)&&(board[i][j]>-1)&&(board[i][j]<7)) {
- board[i][j]+=BLOCKFALL;
- }
- if ((!faaling)&&((board[i][j]/BLOCKFALL)%10==1))
- board[i][j]-=BLOCKFALL;
- if ((!faaling)&&(board[i][j]>0)&&(board[i][j]/10000000!=0)&&((board[i][j]/BLOCKWAIT)%10!=1)&&((board[i][j]/BLOCKHANG)%10!=1)) {
- if (chainSize[board[i][j]/10000000]>chainSize[chain])
- chain=board[i][j]/10000000;
- board[i][j]=board[i][j]%10000000;
- }
- if (!((board[i][j]>-1)&&(board[i][j]<7)))
- faaling=true;
- if (((board[i][j]/1000000)%10==1)||((board[i][j]/BLOCKHANG)%10==1)||((board[i][j]/BLOCKWAIT)%10==1))
- faaling = false;
- }
- }
-
- //Create garbage as a result
- //if((vsMode)&&(chainSize[chain]>1)) garbageTarget->CreateGarbage(6,chainSize[chain]-1);
-
- //Calculate chain
- chain=0;
- for (int i=0; i<6;i++)
- for (int j=0; j<30;j++) {
- if (chainSize[board[i][j]/10000000]>chain)
- chain=chainSize[board[i][j]/10000000];
- }
-
- //Make space in table for more things
- if (chain==0)
- for (int i=0;i<NUMBEROFCHAINS;i++)
- if (chainUsed[i]==true) {
- if ((vsMode)&&(chainSize[i]>1)) garbageTarget->CreateGarbage(6, chainSize[i]-1);
- if ((SoundEnabled)&&(chainSize[i]>4))Mix_PlayChannel(1, applause, 0);
- if(chainSize[i]>1 && !puzzleMode && !AI_Enabled)
- Stats::getInstance()->addOne((string)"chainX"+itoa(chainSize[i]));
- chainUsed[i]=false;
- }
- } //ClearBlocks
-
+ void ClearBlocks();
public:
//prints "Game Over" and ends game
- void SetGameOver() {
- if (!bGameOver) {
- gameEndedAfter = ticks-gameStartedAt; //We game ends now!
- if(!AI_Enabled && !bReplaying)
- {
- TimeHandler::addTime("playTime",TimeHandler::ms2ct(gameEndedAfter));
- }
- }
- if(bReplaying)
- {
- bReplaying = false;
- }
- else
- {
- strncpy(theReplay.name,name,30);
- }
- theReplay.setFinalFrame(getPackage(), 0);
- bGameOver = true;
- showGame = false;
- if(stageClear)
- stageButtonStatus = SBstageClear;
- }
-
- bool GetAIenabled() {
- return AI_Enabled;
- }
-
+ void SetGameOver();
+ bool GetAIenabled();
private:
-
//Moves all peaces a spot down if possible
- int FallBlock(int x, int y, int number) {
- if (y == 0) return -1;
- if (x>0)
- if (board[x-1][y] == number)
- return -1;
- int i=x;
- bool canFall = true;
- //checks a line of a garbage block and see if something is under it
- while ((board[i][y] == number)&&(canFall)&&(i<6)) {
- if (board[i][y-1] != -1) canFall = false;
- i++;
- }
- if (canFall) {
- //cout << "Now falling" << endl;
- for (int j = x;j<i;j++) {
- board[j][y-1] = board[j][y];
- board[j][y] = -1;
- }
- }
- return 0;
- } //FallBlock
-
-
+ int FallBlock(int x, int y, int number);
//Makes all Garbage fall one spot
- void GarbageFall() {
- for (int i=0;i<30;i++)
- for (int j=0;j<7; j++) {
- if ((((board[j][i]/1000000)%10) == 1)||(((board[j][i]/1000000)%10) == 2))
- FallBlock(j, i, board[j][i]);
- }
- }
-
+ void GarbageFall();
//Makes the blocks fall (it doesn't test time, this must be done before hand)
- void FallDown() {
- bool falling =false; //nothing is moving unless proven otherwise
- for (int i=0;i<29;i++)
- for (int j=0;j<6;j++) {
- if ((board[j][i]==-1) && (board[j][i+1]!=-1) && (board[j][i+1]%BLOCKFALL<7)) {
- board[j][i] = board[j][i+1];
- board[j][i+1] = -1;
- falling = true; //something is moving!
- }
- if ((board[j][i]/BLOCKWAIT)%10==1)
- falling=true;
- }
- if (!falling) //If nothing is falling
- {
- if ((puzzleMode)&&(!bGameOver)&&(MovesLeft==0)&&(!(BoardEmpty()))) {
- //Puzzle not won
- SetGameOver();
- stageButtonStatus = SBpuzzleMode;
- }
- }
- GarbageFall(); //Makes the garbage fall
- nrFellDown++; //Sets number of this fall, so we know then the next will occur
- }
-
+ void FallDown();
public:
//Moves the cursor, receaves N,S,E or W as a char an moves as desired
- void MoveCursor(char way) {
- if (!bGameOver) //If game over nothing happends
- {
- if ((way == 'N') && ((cursory<10)||(TowerHeight>12) ||(((pixels==bsize)||(pixels==0)) && (cursory<11))))
- cursory++;
- if ((way == 'S') && (cursory>0))
- cursory--;
- if ((way == 'W') && (cursorx>0))
- cursorx--;
- if ((way == 'E') && (cursorx<4))
- cursorx++;
- }
- }
-
+ void MoveCursor(char way);
//switches the two blocks at the cursor position, unless game over
- void SwitchAtCursor() {
- if ((board[cursorx][cursory+1]<7) && (board[cursorx+1][cursory+1]<7) && (!bGameOver) && ((!puzzleMode)||(MovesLeft>0)) && (gameStartedAt<ticks)) {
- int temp = board[cursorx][cursory+1];
- board[cursorx][cursory+1] = board[cursorx+1][cursory+1];
- board[cursorx+1][cursory+1] = temp;
- }
- if ((puzzleMode)&&(gameStartedAt<ticks)&&(MovesLeft>0)) MovesLeft--;
- }
-
+ void SwitchAtCursor();
//Generates a new line and moves the field one block up (restart puzzle mode)
- void PushLine() {
- //If not game over, not high tower and not puzzle mode
- if ((!bGameOver) && TowerHeight<13 && (!puzzleMode) && (gameStartedAt<ticks)&&(chain==0)) {
- for (int i=19;i>0;i--)
- for (int j=0;j<6;j++) {
- board[j][i] = board[j][i-1];
- }
- for (int j=0;j<6;j++) {
- board[j][0] = rand2() % 4;
- if (j > 0) {
- if (board[j][0] == board[j-1][0])
- board[j][0] = rand2() % 6;
- }
- if (board[j][0] == board[j][1])
- board[j][0] = rand2() % 6;
- if (board[j][0] == board[j][1])
- board[j][0] = rand2() % 6;
- while ((j>0)&&(board[j][0]==board[j-1][0]))
- board[j][0] = rand2() % 6;
- }
- score+=1;
- MoveCursor('N');
- if (vsMode) {
- if (rand2()%6==1)
- board[rand2()%6][0]=6;
- }
- pixels = 0;
- stop=0;
- pushedPixelAt = ticks;
- linesCleared++;
- AI_LineOffset++;
- nrPushedPixel=(int)((double)(pushedPixelAt-gameStartedAt)/(1000.0*speed));
-
- if(!AI_Enabled && !bReplaying)
- {
- Stats::getInstance()->addOne("linesPushed");
- }
- } //if !bGameOver
-
- //Restart Puzzle mode
- if (puzzleMode && !bGameOver) {
- //Reloads level
- MovesLeft = nrOfMovesAllowed[Level];
- for (int i=0;i<6;i++)
- for (int j=0;j<12;j++) {
- board[i][j+1] = puzzleLevels[Level][i][j];
- }
- score=0;
- bGameOver=false;
- showGame = true;
- }
-
- if ((TowerHeight>12) && (!puzzleMode)&&(!bGameOver)&&(chain==0)) {
- if ((!vsMode)&&(theTopScoresEndless.isHighScore(score))&&(!AI_Enabled)) {
- if (SoundEnabled)Mix_PlayChannel(1, applause, 0);
- theTopScoresEndless.addScore(name, score);
- cout << "New high score!" << endl;
- }
- SetGameOver();
- }
-
-
- }//PushLine
-
+ void PushLine();
private:
-
//Pushes a single pixel, so it appears to scrool
- void PushPixels() {
- nrPushedPixel++;
- if ((pixels < bsize) && TowerHeight<13) {
- pixels++;
- }
- else
- PushLine();
- if (pixels>bsize)
- pixels=0;
- }
-
- //See how high the tower is, saved in integer TowerHeight
- /*void FindTowerHeight()
- * {
- * /*
- * This function needs to be corrected, if an empty line appears towerheight become to low!
- * /
- * bool found = false;
- * bool notNew = false;
- * TowerHeight = 0;
- * for(int i=0; i<19;i++)
- * //while(!found)
- * {
- * found = true;
- * for(int j=0;j<6;j++)
- * if(board[j][i] != -1)
- * found = false;
- * if((!found) && (notNew))
- * notNew =false;
- * if((found)&&(!notNew))
- * {
- * TowerHeight=i;
- * notNew = true;
- * }
- * }
- * TowerHeight--;
- * }*/
-
+ void PushPixels();
//See how high the tower is, saved in integer TowerHeight
- void FindTowerHeight() {
- /*
- * Old implementation, used until I find the bug in the other.
- * This function has a bug in stage clear! if an empty line appears.
- */
- prevTowerHeight = TowerHeight;
- bool found = false;
- TowerHeight = 0;
- while (!found) {
- found = true;
- for (int j=0;j<6;j++)
- if (board[j][TowerHeight] != -1)
- found = false;
- TowerHeight++;
- }
- TowerHeight--;
- }
-
+ void FindTowerHeight();
///////////////////////////////////////////////////////////////////////////
/////////////////////////// AI starts here! ///////////////////////////////
///////////////////////////////////////////////////////////////////////////
//First the helpet functions:
- int nrOfType(int line, int type) {
- // cout << "Start_ nrOfType" << endl;
- int counter = 0;
- for (int i=0; i<6; i++)
- if (board[i][line]==type)counter++;
- return counter;
- }
-
+ int nrOfType(int line, int type);
int AIcolorToClear;
int AIlineToClear;
-
//See if a combo can be made in this line
- int horiInLine(int line) {
- //cout << "Start_ hori in line" << endl;
- int nrOfType[7] = {0, 0, 0, 0, 0, 0, 0};
- int iTemp;
- int max = 0;
- for (int i=0; i<6; i++) {
- iTemp = board[i][line];
- if ((iTemp>-1)&&(iTemp<7))
- nrOfType[iTemp]++;
- }
- for (int j=0; j<7; j++) {
- if (nrOfType[j]>max) {
- max = nrOfType[j];
- AIcolorToClear = j;
- }
- }
- return max;
- }
-
- bool horiClearPossible() {
- //cout << "Start_ horiclear possible" << endl;
- int i=13;
- bool solutionFound = false;
- do{
- if (horiInLine(i)>2) {
- AI_LineOffset = 0;
- AIlineToClear = i;
- solutionFound = true;
- }
- i--;
- }while ((!solutionFound)&&(i>0));
- return solutionFound;
- }
-
+ int horiInLine(int line);
+ bool horiClearPossible();
//the Line Has Unmoveable Objects witch might stall the AI
- bool lineHasGarbage(int line) {
- for (int i=0;i<6;i++)
- if (board[i][line]>1000000)
- return true;
- return false;
- }
-
+ bool lineHasGarbage(int line);
//Types 0..6 in line
- int nrOfRealTypes(int line) {
- //cout << "Start_ nrOfReal" << endl;
- int counter = 0;
- for (int i=0; i<6; i++)
- if ((board[i][line]>-1)&&(board[i][line]<7))counter++;
- return counter;
- }
-
+ int nrOfRealTypes(int line);
//See if there is a tower
- bool ThereIsATower() {
- //cout << "Start_ there is a tower" << endl;
- bool bThereIsATower = false; //Unless proven otherwise!
- bool topReached = false; //If we have reached the top
- int lineNumber = 0;
- bool emptySpacesFound = false;
- do {
- if ((emptySpacesFound) && (nrOfRealTypes(lineNumber)>0)&&(nrOfType(lineNumber, -1)>0)) {
- AIlineToClear = lineNumber;
- if (lineHasGarbage(lineNumber))
- return false;
- else
- bThereIsATower = true;
- }
- else
- emptySpacesFound=false;
- if ((!emptySpacesFound)&&(nrOfType(lineNumber, -1)>0))
- emptySpacesFound = true;
- if (lineNumber<12)
- lineNumber++;
- else
- topReached = true;
- }while ((!bThereIsATower)&&(!topReached));
- //if(bThereIsATower)
- //cout << "There is actually a tower" << endl;
- return bThereIsATower;
- }
-
- double firstInLine1(int line) {
- for (int i=0;i<6;i++)
- if ((board[i][line]>-1)&&(board[i][line]<7))
- return (double)i;
- return 3.0;
- }
-
+ bool ThereIsATower();
+ double firstInLine1(int line);
//returns the first coordinate of the block of type
- double firstInLine(int line, int type) {
- for (int i=0;i<6;i++)
- if (board[i][line]==type)
- return (double)i;
- return 3.0;
- }
-
+ double firstInLine(int line, int type);
//There in the line shall we move
- int closestTo(int line, int place) {
- if ((int)firstInLine1(line)>place)
- return (int)firstInLine1(line)-1;
- for (int i=place;i>=0;i--) {
- if ((board[i][line]>-1)&&(board[i][line]<7))
- return i;
- }
- AIstatus=0;
- return place;
- }
-
+ int closestTo(int line, int place);
//The AI will remove a tower
- void AI_ClearTower() {
- // cout << "AI: ClearTower, line: " << AIlineToClear << endl;
- int place = (int)firstInLine(AIlineToClear-1, -1); //Find an empty field to frop a brick into
- int xplace = closestTo(AIlineToClear, place); //Find the brick to drop in it
- if (cursory+1<AIlineToClear)
- MoveCursor('N');
- else
- if (cursory+1>AIlineToClear)
- MoveCursor('S');
- else
- if (cursorx<xplace)
- MoveCursor('E');
- else
- if (cursorx>xplace)
- MoveCursor('W');
- else
- SwitchAtCursor();
- if (!ThereIsATower())
- AIstatus = 0;
- }
-
+ void AI_ClearTower();
//The AI will try to clear block horisontally
- void AI_ClearHori() {
- // cout << "AI: ClearHori";
- int lowestLine = AIlineToClear;
- //AIcolorToClear
- bool found =true;
- /*for(int i; (i<12)&&(!found);i++)
- * {
- * if(horiInLine(i)>2)
- * {
- * int lowestLine = i;
- * found = true;
- * }
- * }*/
- for (int i=0;i<7;i++) {
- if (nrOfType(lowestLine, i)>2)
- AIcolorToClear = i;
- }
- if (found) {
- if (cursory>lowestLine-1)
- MoveCursor('S');
- else if (cursory<lowestLine-1)
- MoveCursor('N');
- else if (nrOfType(lowestLine, AIcolorToClear)>2) {
- int left=0, right=0;
- if (board[0][lowestLine]==AIcolorToClear) left++;
- if (board[1][lowestLine]==AIcolorToClear) left++;
- if (board[2][lowestLine]==AIcolorToClear) left++;
- if (board[3][lowestLine]==AIcolorToClear) right++;
- if (board[4][lowestLine]==AIcolorToClear) right++;
- if (board[5][lowestLine]==AIcolorToClear) right++;
- int xplace = 0;
- if (left<right) {
- // cout << ", right>left";
- int count=0;
- for (int i=0;(i<4)&&(count<1);i++)
- if ((board[i][lowestLine]==AIcolorToClear)&&((i==0)||(board[i+1][lowestLine]!=AIcolorToClear))) {
- count++;
- xplace = i;
- }
- }
- else {
- // cout << ", left>=right";
- int count=0;
- for (int i=3;(i<=5)&&(count<1);i++)
- if ((board[i][lowestLine]==AIcolorToClear)&&(board[i-1][lowestLine]!=AIcolorToClear)) {
- count++;
- xplace = --i;
- }
- }
- //cout << ", xplace: " << xplace;
- if (cursorx<xplace)
- MoveCursor('E');
- else
- if (cursorx>xplace)
- MoveCursor('W');
- else
- if (cursorx==xplace)
- SwitchAtCursor();
- else
- AIstatus = 0;
- }
- else
- AIstatus = 0;
- }
- else
- AIstatus = 0;
- //cout << endl; //for debugging
- }
-
+ void AI_ClearHori();
//Test if vertical clear is possible
- bool veriClearPossible() {
- bool found=false;
- int colors[7] = {0, 0, 0, 0, 0, 0, 0};
- for (int i=12;(i>0)&&(!found);i--) {
- for (int j=0;j<7;j++) {
- if (nrOfType(i, j)==0)
- colors[j]=0;
- else
- if (++colors[j]>2) {
- AIcolorToClear = j;
- AIlineToClear = i;
- found=true;
- }
-
- }
- }
- return found;
- }
-
-
-
+ bool veriClearPossible();
//There in the line shall we move
- int closestTo(int line, int type, int place) {
- if ((int)firstInLine(line, type)>place)
- return (int)firstInLine(line, type)-1;
- for (int i=place;i>=0;i--) {
- if (board[i][line]==type)
- return i;
- }
- AIstatus=0;
- return place;
- }
-
+ int closestTo(int line, int type, int place);
//The AI will try to clear blocks vertically
- void AI_ClearVertical() {
- // cout << "AI: ClearVeri";
- //First we find the place there we will align the bricks
- int placeToCenter = (int)(firstInLine(AIlineToClear, AIcolorToClear)/3.0+firstInLine(AIlineToClear+1, AIcolorToClear)/3.0+firstInLine(AIlineToClear+2, AIcolorToClear)/3.0);
- int unlimitedLoop=0;
- while (((board[placeToCenter][AIlineToClear]>1000000)||(board[placeToCenter][AIlineToClear+1]>1000000)||(board[placeToCenter][AIlineToClear+2]>1000000))&&(unlimitedLoop<10)) {
- unlimitedLoop++;
- placeToCenter++;
- if (placeToCenter>5)
- placeToCenter=0;
- }
- if(unlimitedLoop>9) {
- AIstatus = 0;
- }
- //cout << ", ptc: " << placeToCenter << ", line: " << AIlineToClear << ", cy: " << cursory;
- if (cursory+1>AIlineToClear+2) {
- // cout << ", cursory>line+2";
- MoveCursor('S');
- }
- if (cursory+1<AIlineToClear)
- MoveCursor('N');
- bool toAlign[3]={true, true, true};
- if (board[placeToCenter][AIlineToClear+0]==AIcolorToClear)
- toAlign[0]=false;
- if (board[placeToCenter][AIlineToClear+1]==AIcolorToClear)
- toAlign[1]=false;
- if (board[placeToCenter][AIlineToClear+2]==AIcolorToClear)
- toAlign[2]=false;
- //cout << "status: " << toAlign[0] << " " << toAlign[1] << " " << toAlign[2];
- if (cursory+1==AIlineToClear) {
- if (toAlign[0]==false)
- MoveCursor('N');
- else {
- if (cursorx>closestTo(AIlineToClear, AIcolorToClear, placeToCenter))
- MoveCursor('W');
- else
- if (cursorx<closestTo(AIlineToClear, AIcolorToClear, placeToCenter))
- MoveCursor('E');
- else
- SwitchAtCursor();
- }
- }
- else
- if (cursory+1==AIlineToClear+1) {
- if (toAlign[1]==false) {
- if (toAlign[2])
- MoveCursor('N');
- else
- MoveCursor('S');
- }
- else {
- if (cursorx>closestTo(AIlineToClear+1, AIcolorToClear, placeToCenter))
- MoveCursor('W');
- else
- if (cursorx<closestTo(AIlineToClear+1, AIcolorToClear, placeToCenter))
- MoveCursor('E');
- else
- SwitchAtCursor();
- }
- }
- else
- if (cursory+1==AIlineToClear+2) {
- if (toAlign[2]==false)
- MoveCursor('S');
- else {
- if (cursorx>closestTo(AIlineToClear+2, AIcolorToClear, placeToCenter))
- MoveCursor('W');
- else
- if (cursorx<closestTo(AIlineToClear+2, AIcolorToClear, placeToCenter))
- MoveCursor('E');
- else
- SwitchAtCursor();
- }
- }
-
- if ((!toAlign[0])&&(!toAlign[1])&&(!toAlign[2]))
- AIstatus = 0;
- if ((nrOfType(AIlineToClear, AIcolorToClear)==0)||(nrOfType(AIlineToClear+1, AIcolorToClear)==0)||(nrOfType(AIlineToClear+2, AIcolorToClear)==0))
- AIstatus = 0;
- //cout << endl;
- }
-
-
-
+ void AI_ClearVertical();
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
bool firstLineCreated;
-
- void AI_Move() {
- switch (AIstatus) {
- case 1:
- if (TowerHeight<8)PushLine();
- else AIstatus = 0;
- break;
- case 2:
- AI_ClearTower();
- break;
- case 3:
- AI_ClearHori();
- break;
- case 4:
- AI_ClearVertical();
- break;
- case 5:
- if (!firstLineCreated){
- PushLine();
- firstLineCreated = true;
- }
- else {
- PushLine();
- AIstatus = 0;
- }
- break;
- case 6:
- PushLine();
- AIstatus = 0;
- break;
- default:
- if (TowerHeight<6) AIstatus = 1;
- else
- if (horiClearPossible()) AIstatus = 3;
- else
- if (veriClearPossible()) AIstatus = 4;
- else
- if (ThereIsATower()) AIstatus = 2;
- else
- AIstatus = 5;
- break;
- }
- }
-
+ void AI_Move();
//////////////////////////////////////////////////////////////////////////
///////////////////////////// AI ends here! //////////////////////////////
//////////////////////////////////////////////////////////////////////////
#if WITH_SDL
//Draws all the bricks to the board (including garbage)
- void PaintBricks() {
- for (int i=0;((i<13)&&(i<30));i++)
- for (int j=0;j<6;j++) {
- if ((board[j][i]%10 != -1) && (board[j][i]%10 < 7) && ((board[j][i]/1000000)%10==0)) {
- DrawIMG(bricks[board[j][i]%10], sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((board[j][i]/BLOCKWAIT)%10==1)
- DrawIMG(bomb[(ticks/BOMBTIME)%2], sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((board[j][i]/BLOCKHANG)%10==1)
- DrawIMG(ready[(ticks/READYTIME)%2], sBoard, j*bsize, bsize*12-i*bsize-pixels);
-
- }
- if ((board[j][i]/1000000)%10==1) {
- int left, right, over, under;
- int number = board[j][i];
- if (j<1) left = -1;
- else left = board[j-1][i];
- if (j>5) right = -1;
- else right = board[j+1][i];
- if (i>28) over = -1;
- else over = board[j][i+1];
- if (i<1) under = -1;
- else under = board[j][i-1];
- if ((left == number)&&(right == number)&&(over == number)&&(under == number))
- DrawIMG(garbageFill, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left != number)&&(right == number)&&(over == number)&&(under == number))
- DrawIMG(garbageL, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right != number)&&(over == number)&&(under == number))
- DrawIMG(garbageR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right == number)&&(over != number)&&(under == number))
- DrawIMG(garbageT, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right == number)&&(over == number)&&(under != number))
- DrawIMG(garbageB, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left != number)&&(right == number)&&(over != number)&&(under == number))
- DrawIMG(garbageTL, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left != number)&&(right == number)&&(over == number)&&(under != number))
- DrawIMG(garbageBL, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right != number)&&(over != number)&&(under == number))
- DrawIMG(garbageTR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right != number)&&(over == number)&&(under != number))
- DrawIMG(garbageBR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right != number)&&(over != number)&&(under != number))
- DrawIMG(garbageMR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left == number)&&(right == number)&&(over != number)&&(under != number))
- DrawIMG(garbageM, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- if ((left != number)&&(right == number)&&(over != number)&&(under != number))
- DrawIMG(garbageML, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- }
- if ((board[j][i]/1000000)%10==2) {
- if (j==0)
- DrawIMG(garbageGML, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- else
- if (j==5)
- DrawIMG(garbageGMR, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- else
- DrawIMG(garbageGM, sBoard, j*bsize, bsize*12-i*bsize-pixels);
- }
- }
- const int j = 0;
-
- int garbageSize=0;
- for (int i=0;i<20;i++) {
- if ((board[j][i]/1000000)%10==1) {
- int left, right, over, under;
- int number = board[j][i];
- if (j<1) left = -1;
- else left = board[j-1][i];
- if (j>5) right = -1;
- else right = board[j+1][i];
- if (i>28) over = -1;
- else over = board[j][i+1];
- if (i<1) under = -1;
- else under = board[j][i-1];
- if (((left != number)&&(right == number)&&(over != number)&&(under == number))&&(garbageSize>0)) {
- DrawIMG(smiley[board[j][i]%4], sBoard, 2*bsize, 12*bsize-i*bsize-pixels+(bsize/2)*garbageSize);
- }
- if (!((left != number)&&(right == number)&&(over == number)&&(under == number))) //not in garbage
- {
- garbageSize=0;
- }
- else {
- //cout << "In garbage" << endl;
- garbageSize++;
- }
-
- }
- }
- for (int i=0;i<6;i++)
- if (board[i][0]!=-1)
- DrawIMG(transCover, sBoard, i*bsize, 12*bsize-pixels); //Make the appering blocks transperant
-
- }
-
+ void PaintBricks();
//Paints the bricks gotten from a replay/net package
- void SimplePaintBricks() {
- /*
- * We will need to mark the blocks that must have a bomb, we will here need to see, what is falling
- */
- bool bbomb[6][13]; //has a bomb on it!
- bool falling[6][13]; //this is falling
- bool getReady[6][13]; //getReady
- for (int i=0;i<6;i++)
- for (int j=0;j<13;j++) {
- bbomb[i][j]=false; //All false by default
- falling[i][j]=false;
- if (board[i][j]>29)
- getReady[i][j]=true;
- else
- getReady[i][j]=false;
- }
- //See that is falling
- for (int i=0;i<6;i++) {
- bool rowFalling = false;
- for (int j=0;j<13;j++) {
- if (rowFalling)
- falling[i][j]=true;
- if ((!rowFalling)&&(board[i][j]%30==-1))
- rowFalling = true;
- if ((rowFalling)&&(board[i][j]%30>6))
- rowFalling = false;
- if (getReady[i][j]) {
- falling[i][j]=true; //getReady is the same as falling
- rowFalling = false;
- }
- }
- }
- //Now looking at rows:
- for (int i=0;i<6;i++) {
- int count = 0;
- int color = -1;
- for (int j=1;j<13;j++) {
- if ((board[i][j]%30==color)&&(!falling[i][j]))
- count++;
- else
- if (falling[i][j]) {
- count = 0;
- }
- else {
- color=board[i][j]%30;
- count=1;
- }
- if ((count>2)&&(color>-1)&&(color)<7) {
- bbomb[i][j]=true;
- bbomb[i][j-1]=true;
- bbomb[i][j-2]=true;
- }
- }
- }
- //now looking for lines
- for (int i=1;i<13;i++) {
- int count = 0;
- int color = -1;
- for (int j=0;j<6;j++) {
- if ((board[j][i]%30==color)&&(!falling[j][i]))
- count++;
- else
- if (falling[j][i]) {
- count = 0;
- }
- else {
- color=board[j][i]%30;
- count=1;
- }
- if ((count>2)&&(color>-1)&&(color<7)) {
- bbomb[j][i]=true;
- bbomb[j-1][i]=true;
- bbomb[j-2][i]=true;
- }
- }
- }
- for (int i=0;((i<13)&&(i<30));i++)
- for (int j=0;j<6;j++) {
- if ((board[j][i]%10 != -1) && (board[j][i]%30 < 7)) {
- DrawIMG(bricks[board[j][i]%10], sBoard, j*bsize, 12*bsize-i*bsize-pixels);
- if (bbomb[j][i])
- DrawIMG(bomb[(ticks/BOMBTIME)%2], sBoard, j*bsize, 12*bsize-i*bsize-pixels);
- if (getReady[j][i])
- DrawIMG(ready[(ticks/READYTIME)%2], sBoard, j*bsize, 12*bsize-i*bsize-pixels);
- }
- if (board[j][i]%30>6) {
- if (board[j][i]%30==7)
- DrawIMG(garbageR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==9)
- DrawIMG(garbageML, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==10)
- DrawIMG(garbageMR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==11)
- DrawIMG(garbageTR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==12)
- DrawIMG(garbageTL, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==13)
- DrawIMG(garbageBL, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==14)
- DrawIMG(garbageBR, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==15)
- DrawIMG(garbageM, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==16)
- DrawIMG(garbageFill, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==17)
- DrawIMG(garbageT, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==18)
- DrawIMG(garbageB, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==19)
- DrawIMG(garbageL, sBoard, j*bsize, 12*bsize-i*bsize-pixels); //good
- if (board[j][i]%30==20)
- switch(j) {
- case 0:
- DrawIMG(garbageGML, sBoard,j*bsize, 12*bsize-i*bsize-pixels);
- break;
- case 5:
- DrawIMG(garbageGMR, sBoard,j*bsize, 12*bsize-i*bsize-pixels);
- break;
- default:
- DrawIMG(garbageGM, sBoard,j*bsize, 12*bsize-i*bsize-pixels);
- }
- //cout << "IS: " << board[j][i] << endl;
- }
-
-
- }
-
- int garbageSize=0;
- for (int i=0;i<20;i++) {
- if ((board[0][i]%30==12)&&(garbageSize>0)) {
- DrawIMG(smiley[0], sBoard, 2*bsize, bsize-i*bsize-pixels+(bsize/2)*garbageSize);
- }
- if (board[0][i]%30!=19) //not in garbage
- {
- garbageSize=0;
- }
- else {
- //cout << "In garbage" << endl;
- garbageSize++;
- }
-
- }
- }
-
+ void SimplePaintBricks();
int lastCounter;
public:
//Draws everything
- void DoPaintJob() {
- DrawIMG(backBoard, sBoard, 0, 0);
- #if NETWORK
- if ((!bReplaying)&&(!bNetworkPlayer))
- #else
- if (!bReplaying)
- #endif
- PaintBricks();
- else
- SimplePaintBricks();
- if (stageClear) DrawIMG(blackLine, sBoard, 0, bsize*(12+2)+bsize*(stageClearLimit-linesCleared)-pixels-1);
- if (puzzleMode&&(!bGameOver)) {
- //We need to write nr. of moves left!
- strHolder = "Moves left: " + itoa(MovesLeft);
- SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
- }
- if(puzzleMode && stageButtonStatus == SBpuzzleMode)
- {
- DrawIMG(bRetry,sBoard, cordRetryButton.x, cordRetryButton.y);
- if(Level<nrOfPuzzles-1)
- {
- if(hasWonTheGame)
- DrawIMG(bNext,sBoard,cordNextButton.x, cordNextButton.y);
- else
- DrawIMG(bSkip,sBoard,cordNextButton.x, cordNextButton.y);
- }
- else
- {
- strHolder = "Last puzzle";
- SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
- }
- }
- if(stageClear && stageButtonStatus == SBstageClear)
- {
- DrawIMG(bRetry,sBoard, cordRetryButton.x, cordRetryButton.y);
- if(Level<50-1)
- {
- if(hasWonTheGame)
- DrawIMG(bNext,sBoard,cordNextButton.x, cordNextButton.y);
- else
- DrawIMG(bSkip,sBoard,cordNextButton.x, cordNextButton.y);
- }
- else
- {
- strHolder = "Last stage";
- SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
- }
- }
-
-#if DEBUG
- if (AI_Enabled&&(!bGameOver)) {
- strHolder = "AI_status: " + itoa(AIstatus)+ ", "+ itoa(AIlineToClear);
- SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
- }
-#endif
- if (!bGameOver)DrawIMG(cursor[(ticks/600)%2],sBoard,cursorx*bsize-4,11*bsize-cursory*bsize-pixels-4);
- if (ticks<gameStartedAt)
- {
- int currentCounter = abs((int)ticks-(int)gameStartedAt)/1000;
- if( (currentCounter!=lastCounter) && (SoundEnabled)&&(!NoSound))
- Mix_PlayChannel(1,counterChunk,0);
- lastCounter = currentCounter;
- switch (currentCounter) {
- case 2:
- DrawIMG(counter[2], sBoard, 2*bsize, 5*bsize);
- break;
- case 1:
- DrawIMG(counter[1], sBoard, 2*bsize, 5*bsize);
- break;
- case 0:
- DrawIMG(counter[0], sBoard, 2*bsize, 5*bsize);
- break;
- default:
- break;
- }
- }
- else
- {
- if(SoundEnabled&&(!NoSound)&&(timetrial)&&(ticks>gameStartedAt+10000)&&(!bGameOver))
- {
- int currentCounter = (ticks-(int)gameStartedAt)/1000;
- if(currentCounter!=lastCounter)
- {
- if(currentCounter>115 && currentCounter<120)
- Mix_PlayChannel(1,counterChunk,0);
- }
- lastCounter = currentCounter;
- }
- else
- {
- if( (0==lastCounter) && (SoundEnabled)&&(!NoSound))
- {
- Mix_PlayChannel(1,counterFinalChunk,0);
- }
- lastCounter = -1;
- }
- }
-
- if ((bGameOver)&&(!editorMode))
- if (hasWonTheGame)DrawIMG(iWinner, sBoard, 0, 5*bsize);
- else if (bDraw) DrawIMG(iDraw, sBoard, 0, 5*bsize);
- else
- DrawIMG(iGameOver, sBoard, 0, 5*bsize);
- }
-
+ void DoPaintJob();
#endif
-
private:
//Updates evrything, if not called nothing happends
- void Update() {
- Uint32 tempUInt32;
- Uint32 nowTime = ticks; //We remember the time, so it doesn't change during this call
- if (bReplaying) {
- setBoard(theReplay.getFrameSec((Uint32)(nowTime-gameStartedAt)));
- strncpy(name,theReplay.name,30);
- if (theReplay.isFinnished((Uint32)(nowTime-gameStartedAt)))
- switch (theReplay.getFinalStatus()) {
- case 1: //Winner
- bGameOver = true;
- hasWonTheGame = true;
- break;
- case 2: //Looser
- case 4: //GameOver
- bGameOver = true;
- break;
- case 3: //draw
- bGameOver =true;
- bDraw = true;
- break;
- default:
- bGameOver = true;
- //Nothing
- break;
- };
- }
- #if NETWORK
- if ((!bReplaying)&&(!bNetworkPlayer)) {
- #else
- if (!bReplaying) {
- #endif
- FindTowerHeight();
- if ((linesCleared-TowerHeight>stageClearLimit) && (stageClear) && (!bGameOver)) {
- stageCleared[Level] = true;
- if(stageScores[Level]<score)
- {
- gameEndedAfter = nowTime-gameStartedAt;
- stageScores[Level] = score;
- stageTimes[Level] = gameEndedAfter;
- }
-
- ofstream outfile;
- outfile.open(stageClearSavePath.c_str(), ios::binary |ios::trunc);
- if (!outfile) {
- cout << "Error writing to file: " << stageClearSavePath << endl;
- }
- else {
- for (int i=0;i<nrOfStageLevels;i++) {
- bool tempBool = stageCleared[i];
- outfile.write(reinterpret_cast<char*>(&tempBool), sizeof(bool));
- }
- for (int i=0;i<nrOfStageLevels;i++) {
- tempUInt32 = stageScores[i];
- outfile.write(reinterpret_cast<char*>(&tempUInt32), sizeof(Uint32));
- }
- for (int i=0;i<nrOfStageLevels;i++) {
- tempUInt32 = stageTimes[i];
- outfile.write(reinterpret_cast<char*>(&tempUInt32), sizeof(Uint32));
- }
- outfile.close();
- }
- setPlayerWon();
- stageButtonStatus = SBstageClear;
- }
- if ((TowerHeight>12)&&(prevTowerHeight<13)&&(!puzzleMode)) {
- //if (SoundEnabled) Mix_PlayChannel(1, heartBeat, 0);
- stop+=1000;
- }
-
- if ((TowerHeight>12)&&(!puzzleMode)&&(!bGameOver)) {
- bNearDeath = true;
- }
-
- while (nowTime>nrStops*40+gameStartedAt) //Increase stops, till we reach nowTime
- {
- if (stop>0) {
- stop = stop-20;
- if (stop<=0) nrPushedPixel=(int)((nowTime-gameStartedAt)/(1000.0*speed));
- }
- if (stop<0)
- stop = 0;
- nrStops++;
- }
- //If we have static content, we don't raise at all!
- if (hasStaticContent())
- stop++;
- if ((puzzleMode)&&(!bGameOver)&&BoardEmpty()) {
- if (!singlePuzzle) {
- if(puzzleCleared[Level]==false)
- Stats::getInstance()->addOne("puzzlesSolved");
- puzzleCleared[Level] = true;
- ofstream outfile;
- stageButtonStatus = SBpuzzleMode;
- outfile.open(puzzleSavePath.c_str(), ios::binary |ios::trunc);
- if (!outfile) {
- cout << "Error writing to file: " << puzzleSavePath << endl;
- }
- else {
- for (int i=0;i<nrOfPuzzles;i++) {
- bool tempBool = puzzleCleared[i];
- outfile.write(reinterpret_cast<char*>(&tempBool), sizeof(bool));
- }
- outfile.close();
- }
- }
- setPlayerWon();
- }
-
- //increse speed:
- if ((nowTime>gameStartedAt+20000*speedLevel)&&(speedLevel <99)&&(!bGameOver))
- {
- speed = (baseSpeed*0.9)/((double)speedLevel*0.5);
- speedLevel++;
- nrPushedPixel=(int)((double)(nowTime-gameStartedAt)/(1000.0*speed));
- }
-
-
- //To prevent the stack from raising a lot then we stop a chain (doesn't work anymore)
- if (chain>0)
- stop+=1;
- //Raises the stack
- if ((nowTime>gameStartedAt+nrPushedPixel*1000*speed) && (!bGameOver)&&(!stop))
- while ((nowTime>gameStartedAt+nrPushedPixel*1000*speed)&&(!(puzzleMode)))
- PushPixels();
- if (!bGameOver)ClearBlocks();
-
- /*************************************************************
- Ai stuff
- **************************************************************/
- if (bGameOver) {
- AIstatus = 0; //Enusres that AI is resetted
- }
- else
- if (AI_Enabled)
- if (lastAImove+AI_MoveSpeed<ticks) {
- AI_Move();
- lastAImove=ticks;
- }
-
- /*************************************************************
- Ai stuff ended
- **************************************************************/
- if ((nowTime>gameStartedAt+nrFellDown*140) && (!bGameOver)) FallDown();
- if ((nowTime<gameStartedAt)&&(puzzleMode)) {
- FallDown();
- nrFellDown--;
- }
- ReduceStuff();
- if ((timetrial) && (!bGameOver) && (nowTime>gameStartedAt+2*60*1000)) {
- SetGameOver();
- if(!NoSound && SoundEnabled)Mix_PlayChannel(1,counterFinalChunk,0);
- if ((theTopScoresTimeTrial.isHighScore(score))&&(!AI_Enabled)) {
- theTopScoresTimeTrial.addScore(name, score);
- //new highscore
- //Also check if it is better than the best result so far.
- string checkFilename = getPathToSaveFiles() + "/bestTTresult";
- ifstream inFile(checkFilename.c_str());
- Uint32 bestResult = 3000; //Never accept a best result under 3000
- if(inFile)
- {
- inFile >> bestResult;
- inFile.close();
- }
- if(score>bestResult)
- {
- string bestFile = getPathToSaveFiles() + "/bestTT";
- theReplay.saveReplay(bestFile);
- ofstream outFile(checkFilename.c_str(),ios::trunc);
- if(outFile)
- outFile << score;
- }
- }
- }
- }
- if ((!bGameOver)&&(!bReplaying)&&(nowTime>gameStartedAt))
- {
- //cout << nowTime << " bigger than " << gameStartedAt << endl;
- theReplay.setFrameSecTo(nowTime-gameStartedAt, getPackage());
- }
- DoPaintJob();
- }
-
+ void Update();
public:
- void Update(int newtick) {
- ticks = newtick;
- Update();
- }
-}; //class BlockGame
+ void Update(int newtick);
+};
////////////////////////////////////////////////////////////////////////////////
///////////////////////// BlockAttack class end ////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/source/code/block.make b/source/code/block.make index 7cff0ef..02c2f9f 100644 --- a/source/code/block.make +++ b/source/code/block.make
@@ -38,12 +38,15 @@ endif
BASE_LIBS += -lphysfs
$(BINARY): build/main.o build/highscore.o build/SFont.o build/ReadKeyboard.o build/joypad.o build/listFiles.o build/replay.o build/common.o build/stats.o
- $(CPP) -O -o $(BINARY) build/main.o build/highscore.o build/SFont.o build/ReadKeyboard.o build/joypad.o build/listFiles.o build/replay.o build/common.o build/stats.o $(BASE_LIBS)
+ $(CPP) -O -o $(BINARY) build/main.o build/highscore.o build/SFont.o build/ReadKeyboard.o build/joypad.o build/listFiles.o build/replay.o build/common.o build/stats.o $(BASE_LIBS)
#-lphysfs
-build/main.o: main.cpp BlockGame.hpp mainVars.hpp common.h
+build/main.o: main.cpp mainVars.hpp common.h
$(CPP) $(BASE_CFLAGS) main.cpp -o build/main.o
+#build/blockgame.o: BlockGame.hpp BlockGame.cpp
+# $(CPP) $(BASE_CFLAGS) BlockGame.cpp -o build/blockgame.o
+
build/highscore.o: highscore.h highscore.cpp
$(CPP) $(BASE_CFLAGS) highscore.cpp -o build/highscore.o
diff --git a/source/code/main.cpp b/source/code/main.cpp index 334d838..f093aac 100644 --- a/source/code/main.cpp +++ b/source/code/main.cpp
@@ -1166,6 +1166,7 @@ textManeger theTextManeger;
//Here comes the Block Game object
#include "BlockGame.hpp"
+#include "BlockGame.cpp"
#include "SFont.h"
//writeScreenShot saves the screen as a bmp file, it uses the time to get a unique filename
diff --git a/source/code/mainVars.hpp b/source/code/mainVars.hpp index 5045b80..93b4c11 100644 --- a/source/code/mainVars.hpp +++ b/source/code/mainVars.hpp
@@ -29,18 +29,6 @@ Copyright (C) 2007 Poul Sander
//main variables and constants
-//Some definitions
-//The game is divided in frames. FALLTIME means the blocks will fall one block every FRAMELENGTH*FALLTIME millisecond
-#define FRAMELENGTH 50
-#define HANGTIME 40
-#define FALLTIME 20
-//Don't change the following, they are fundamental and later some functions are hardcoded
-#define BLOCKFALL 10000
-#define BLOCKWAIT 100000
-#define BLOCKHANG 1000
-#define GARBAGE 1000000
-#define CHAINPLACE 10000000
-#define NUMBEROFCHAINS 100
//Animation lengths:
#define READYTIME 500
diff --git a/source/code/replay.h b/source/code/replay.h index 1b7fdcb..23b9daa 100644 --- a/source/code/replay.h +++ b/source/code/replay.h
@@ -29,6 +29,9 @@ replay is used to save a replay, there is saved 10 moves per second, should be
able to give a realistic replay
*/
+#ifndef REPLAY_H
+#define REPLAY_H 1
+
//constants - 3000 is 5 minutes
#define FRAMESPERSEC 10
@@ -92,3 +95,5 @@ public:
};
+
+#endif