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=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 -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(LeveladdOne("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= 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-startPosition999999) 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 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; k2) + for (int k = i-combo; k-1)&&(board[j][i]%10000000<7))) { + if (board[j][i]%10000000 == previus) { + combo++; + } + else { + if (combo>2) + for (int k = j-combo; k2) + for (int k = j-combo; k2) && (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;i1)) 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;j12) ||(((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)) && (gameStartedAt0)) 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) && (gameStartedAt0;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+1AIlineToClear) + MoveCursor('S'); + else + if (cursorxxplace) + 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 (cursory2) { + 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 (leftleft"; + 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 (cursorxxplace) + 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+1closestTo(AIlineToClear, AIcolorToClear, placeToCenter)) + MoveCursor('W'); + else + if (cursorxclosestTo(AIlineToClear+1, AIcolorToClear, placeToCenter)) + MoveCursor('W'); + else + if (cursorxclosestTo(AIlineToClear+2, AIcolorToClear, placeToCenter)) + MoveCursor('W'); + else + if (cursorx5) 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(LevelgameStartedAt+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](&tempBool), sizeof(bool)); + } + for (int i=0;i(&tempUInt32), sizeof(Uint32)); + } + for (int i=0;i(&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(&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_MoveSpeedgameStartedAt+nrFellDown*140) && (!bGameOver)) FallDown(); + if ((nowTimegameStartedAt+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=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 -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(LeveladdOne("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= 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-startPosition999999) 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 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; k2) - for (int k = i-combo; k-1)&&(board[j][i]%10000000<7))) { - if (board[j][i]%10000000 == previus) { - combo++; - } - else { - if (combo>2) - for (int k = j-combo; k2) - for (int k = j-combo; k2) && (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;i1)) 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;j12) ||(((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)) && (gameStartedAt0)) 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) && (gameStartedAt0;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+1AIlineToClear) - MoveCursor('S'); - else - if (cursorxxplace) - 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 (cursory2) { - 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 (leftleft"; - 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 (cursorxxplace) - 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+1closestTo(AIlineToClear, AIcolorToClear, placeToCenter)) - MoveCursor('W'); - else - if (cursorxclosestTo(AIlineToClear+1, AIcolorToClear, placeToCenter)) - MoveCursor('W'); - else - if (cursorxclosestTo(AIlineToClear+2, AIcolorToClear, placeToCenter)) - MoveCursor('W'); - else - if (cursorx5) 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(LevelgameStartedAt+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](&tempBool), sizeof(bool)); - } - for (int i=0;i(&tempUInt32), sizeof(Uint32)); - } - for (int i=0;i(&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(&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_MoveSpeedgameStartedAt+nrFellDown*140) && (!bGameOver)) FallDown(); - if ((nowTimegameStartedAt+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