#include #include #include #include #include "Level.h" #include "constant.h" #include "endian.h" using namespace std; extern BITMAP *tileImage; extern void generalDrawPacMan(direction headed, fixed lipBinaryAngle); int Level::getPacManStartX() { return pacManStartX; } void Level::setPacManStartX(int value) { pacManStartX = value; } int Level::getPacManStartY() { return pacManStartY; } void Level::setPacManStartY(int value) { pacManStartY = value; } int Level::getEnemyStartX() { return enemyStartX; } void Level::setEnemyStartX(int value) { enemyStartX = value; } int Level::getEnemyStartY() { return enemyStartY; } void Level::setEnemyStartY(int value) { enemyStartY = value; } direction Level::getEnemyDirection(size_t position) { return enemyRoute[position]; } void Level::pushBackEnemyDirection(direction value) { enemyRoute.push_back(value); } size_t Level::getEnemyRouteSize() { return enemyRoute.size(); } void Level::resizeEnemyRoute(size_t position) { enemyRoute.resize(position); } vector::iterator Level::enemyRouteBegin() { return enemyRoute.begin(); } vector::iterator Level::enemyRouteEnd() { return enemyRoute.end(); } vector Level::getEnemyRoute() { return enemyRoute; } void Level::setEnemyRoute(const vector &value) { enemyRoute = value; } int Level::getBonusStartX() { return bonusStartX; } void Level::setBonusStartX(int value) { bonusStartX = value; } int Level::getBonusStartY() { return bonusStartY; } void Level::setBonusStartY(int value) { bonusStartY = value; } direction Level::getBonusDirection(size_t position) { return bonusRoute[position]; } void Level::pushBackBonusDirection(direction value) { bonusRoute.push_back(value); } size_t Level::getBonusRouteSize() { return bonusRoute.size(); } void Level::resizeBonusRoute(size_t position) { bonusRoute.resize(position); } vector::iterator Level::bonusRouteBegin() { return bonusRoute.begin(); } vector::iterator Level::bonusRouteEnd() { return bonusRoute.end(); } vector Level::getBonusRoute() { return bonusRoute; } void Level::setBonusRoute (const vector &value) { bonusRoute = value; } int Level::getEnergizerLifespan() { return energizerLifespan; } void Level::setEnergizerLifespan(int value) { energizerLifespan = value; } const char* Level::getProblem() { return problem; } void Level::newLevel() { for (int y = 0; y < boardH; y++) content[0][y] = wallTile; for (int x = 1; x < boardW - 1; x++) { content[x][0] = wallTile; for (int y = 1; y < boardH - 1; y++) content[x][y] = dotTile; content[x][boardH - 1] = wallTile; } for (int y = 0; y < boardH; y++) content[boardW - 1][y] = wallTile; content[1][1] = emptyTile; pacManStartX = 1; pacManStartY = 1; enemyStartX = 0; enemyStartY = 0; enemyRoute.clear(); enemyRoute.push_back(right); enemyRoute.push_back(down); enemyRoute.push_back(left); enemyRoute.push_back(up); bonusStartX = 0; bonusStartY = 0; bonusRoute.clear(); bonusRoute.push_back(right); bonusRoute.push_back(down); bonusRoute.push_back(left); bonusRoute.push_back(up); energizerLifespan = 10000; } bool Level::saveAs(const char *fn) { const int enemyRouteLength = enemyRoute.size(); const int bonusRouteLength = bonusRoute.size(); int writeEnergizerLifespan = toLittleEndian(energizerLifespan); int writeEnemyRouteLength = toLittleEndian(enemyRouteLength); int writeBonusRouteLength = toLittleEndian(bonusRouteLength); errno = 0; FILE *out = fopen(fn, "wb"); if (!out) { problem = errno ? strerror(errno) : "Can't open file for writing."; return false; } for (int y = 0; y < boardH; y++) for (int x = 0; x < boardW; x++) if (putc(content[x][y], out) == EOF) { problem = errno ? strerror(errno) : "Error in writing to file."; fclose(out); // If that fails here, there is not much I can do. return false; } if (putc(pacManStartX, out) == EOF || putc(pacManStartY, out) == EOF || putc(enemyStartX, out) == EOF || putc(enemyStartY, out) == EOF || putc(bonusStartX, out) == EOF || putc(bonusStartY, out) == EOF || fwrite(&writeEnergizerLifespan, sizeof(int), 1, out) != 1 || fwrite(&writeEnemyRouteLength, sizeof(int), 1, out) != 1 || fwrite(&writeBonusRouteLength, sizeof(int), 1, out) != 1) { problem = errno ? strerror(errno) : "Error in writing to file."; fclose(out); // If the fails here, there is not much I can do. return false; } for (int i = 0; i < enemyRouteLength; i++) if (putc(enemyRoute[i], out) == EOF) { problem = errno ? strerror(errno) : "Error in writing to file."; fclose(out); // If that fails here, there is not much I can do. return false; } for (int i = 0; i < bonusRouteLength; i++) if (putc(bonusRoute[i], out) == EOF) { problem = errno ? strerror(errno) : "Error in writing to file."; fclose(out); // If that fails here, there is not much I can do. return false; } if (fclose(out) == EOF) { problem = errno ? strerror(errno) : "Error in closing file."; return false; } problem = NULL; return true; } bool Level::open(const char *fn) { int readBoard[boardW][boardH]; int readPacManStartX; int readPacManStartY; int readEnemyStartX; int readEnemyStartY; int readBonusStartX; int readBonusStartY; int readEnergizerLifespan; int readEnemyRouteLength; int readBonusRouteLength; errno = 0; FILE *in = fopen(fn, "rb"); if (!in) { problem = errno ? strerror(errno) : "Can't open file for reading."; return false; } for (int y = 0; y < boardH; y++) for (int x = 0; x < boardW; x++) if ((readBoard[x][y] = getc(in)) == EOF) { problem = feof(in) ? "The file is not a level." : (errno ? strerror(errno) : "Error in reading from file."); fclose(in); // If that fails here, there is not much I can do. return false; } if ((readPacManStartX = getc(in)) == EOF || (readPacManStartY = getc(in)) == EOF || (readEnemyStartX = getc(in)) == EOF || (readEnemyStartY = getc(in)) == EOF || (readBonusStartX = getc(in)) == EOF || (readBonusStartY = getc(in)) == EOF || fread(&readEnergizerLifespan, sizeof(int), 1, in) != 1 || fread(&readEnemyRouteLength, sizeof(int), 1, in) != 1 || fread(&readBonusRouteLength, sizeof(int), 1, in) != 1) { problem = feof(in) ? "The file is not a level." : (errno ? strerror(errno) : "Error in reading from file."); fclose(in); // If that fails here, there is not much I can do. return false; } readEnergizerLifespan = fromLittleEndian(readEnergizerLifespan); readEnemyRouteLength = fromLittleEndian(readEnemyRouteLength); readBonusRouteLength = fromLittleEndian(readBonusRouteLength); if (readPacManStartX < 0 || readPacManStartX >= boardW || readPacManStartY < 0 || readPacManStartY >= boardH || readEnemyStartX < 0 || readEnemyStartX >= boardW || readEnemyStartY < 0 || readEnemyStartY >= boardH || readBonusStartX < 0 || readBonusStartX >= boardW || readBonusStartY < 0 || readBonusStartY >= boardH || readEnergizerLifespan <= 0 || readEnemyRouteLength < 1 || readBonusRouteLength < 1 || readBonusStartX != 0 && readBonusStartX != boardW - 1 && readBonusStartY != 0 && readBonusStartY != boardH - 1) { problem = "The file is not a level."; fclose(in); // If that fails here, there is not much I can do. return false; } char *readEnemyRoute = (char*)malloc(readEnemyRouteLength * sizeof(char)); if (!readEnemyRoute) { problem = "Not enough memory to load it."; fclose(in); // If that fails here, there is not much I can do. return false; } char *readBonusRoute = (char*)malloc(readBonusRouteLength * sizeof(char)); if (!readBonusRoute) { problem = "Not enough memory to load it."; free(readEnemyRoute); fclose(in); // If that fails here, there is not much I can do. return false; } if (fread(readEnemyRoute, sizeof(char), readEnemyRouteLength, in) != readEnemyRouteLength || fread(readBonusRoute, sizeof(char), readBonusRouteLength, in) != readBonusRouteLength) { problem = feof(in) ? "The file is not a level." : (errno ? strerror(errno) : "Error in reading from file."); free(readEnemyRoute); free(readBonusRoute); fclose(in); // If that fails here, there is not much I can do. return false; } if (getc(in) == EOF) { if (ferror(in)) { problem = errno ? strerror(errno) : "Error in reading from file."; free(readEnemyRoute); free(readBonusRoute); fclose(in); // If that fails here, there is not much I can do. return false; } } else { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); fclose(in); // If that fails here, there is not much I can do. return false; } if (fclose(in) == EOF) { problem = errno ? strerror(errno) : "Error in closing file."; free(readEnemyRoute); free(readBonusRoute); return false; } for (int x = 0; x < boardW; x++) for (int y = 0; y < boardH; y++) if (x == readPacManStartX && y == readPacManStartY ? (readBoard[x][y] != emptyTile) : (readBoard[x][y] != wallTile && readBoard[x][y] != dotTile && readBoard[x][y] != energyTile)) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } char went = readEnemyRoute[0]; if (went != up && went != left && went != right && went != down) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } for (int i = 1; i < readEnemyRouteLength; i++) { if (readEnemyRoute[i] == otherWay[went]) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } went = readEnemyRoute[i]; if (went != up && went != left && went != right && went != down) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } } went = readBonusRoute[0]; if (went != up && went != left && went != right && went != down) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } for (int i = 1; i < readBonusRouteLength; i++) { if (readBonusRoute[i] == otherWay[went]) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } went = readBonusRoute[i]; if (went != up && went != left && went != right && went != down) { problem = "The file is not a level."; free(readEnemyRoute); free(readBonusRoute); return false; } } memcpy(content, readBoard, boardW * boardH * sizeof(int)); pacManStartX = readPacManStartX; pacManStartY = readPacManStartY; enemyStartX = readEnemyStartX; enemyStartY = readEnemyStartY; bonusStartX = readBonusStartX; bonusStartY = readBonusStartY; energizerLifespan = readEnergizerLifespan; enemyRoute.resize(readEnemyRouteLength); for (int i = 0; i < readEnemyRouteLength; i++) switch (readEnemyRoute[i]) { case up: enemyRoute[i] = up; break; case left: enemyRoute[i] = left; break; case right: enemyRoute[i] = right; break; case down: enemyRoute[i] = down; } bonusRoute.resize(readBonusRouteLength); for (int i = 0; i < readBonusRouteLength; i++) switch (readBonusRoute[i]) { case up: bonusRoute[i] = up; break; case left: bonusRoute[i] = left; break; case right: bonusRoute[i] = right; break; case down: bonusRoute[i] = down; } problem = NULL; free(readEnemyRoute); free(readBonusRoute); return true; } void Level::drawPacMan(BITMAP *canvas) { generalDrawPacMan(right, itofix(32)); draw_sprite(canvas, tileImage, pacManStartX * tileSize, pacManStartY * tileSize); } void Level::drawLevel(BITMAP *canvas) { drawBoard(canvas); drawPacMan(canvas); }