diff --git a/AI/KBlocksAITypeDefine.h b/AI/KBlocksAITypeDefine.h index b1ad7fd..1bd1465 100644 --- a/AI/KBlocksAITypeDefine.h +++ b/AI/KBlocksAITypeDefine.h @@ -1,32 +1,30 @@ /*************************************************************************** * KBlocks, a falling blocks game by KDE * * Copyright (C) 2010 University Freiburg * * * * 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. * ***************************************************************************/ #ifndef KBLOCKSAITYPEDEFINE_H #define KBLOCKSAITYPEDEFINE_H #include #include #define KSIRTET #define INITLIST #ifndef DEBUG #define DEBUG #endif #ifndef LOG #define LOG #endif #define UNIX -#include - #endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ff8d4d..9129234 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,141 +1,142 @@ cmake_minimum_required (VERSION 3.5 FATAL_ERROR) # KDE Application Version, managed by release script set(KDE_APPLICATIONS_VERSION_MAJOR "19") set(KDE_APPLICATIONS_VERSION_MINOR "11") set(KDE_APPLICATIONS_VERSION_MICRO "70") set(KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}") project(kblocks VERSION ${KDE_APPLICATIONS_VERSION}) set (QT_MIN_VERSION "5.7.0") set (KF5_MIN_VERSION "5.30.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED CONFIG) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Widgets Svg Network) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Config ConfigWidgets CoreAddons Crash DocTools DBusAddons I18n WidgetsAddons XmlGui ) find_package(KF5KDEGames 7.1.0 REQUIRED) include(FeatureSummary) include(ECMInstallIcons) include(KDEInstallDirs) include(KDECompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(ECMAddAppIcon) include(ECMQtDeclareLoggingCategory) include(ECMSetupVersion) add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) if (${KF5Config_VERSION} STRGREATER "5.56.0") add_definitions(-DQT_NO_FOREACH) MESSAGE(STATUS "compile without foreach") endif() add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_subdirectory(themes) add_subdirectory(sounds) add_subdirectory(doc) ########### next target ############### set(kblocks_SRCS main.cpp KBlocksDefine.cpp KBlocksNetServer.cpp KBlocksNetClient.cpp KBlocksConfigManager.cpp KBlocksWin.cpp KBlocksDisplay.cpp KBlocksRepWin.cpp KBlocksAppThread.cpp KBlocksScene.cpp KBlocksView.cpp KBlocksScore.cpp KBlocksGraphics.cpp KBlocksSound.cpp KBlocksItemGroup.cpp KBlocksSvgItem.cpp KBlocksAnimator.cpp KBlocksAnimFade.cpp KBlocksAnimDrop.cpp KBlocksPlayManager.cpp KBlocksPlayNetwork.cpp KBlocksSinglePlayer.cpp KBlocksNetPlayer.cpp KBlocksKeyboardPlayer.cpp KBlocksDummyAI.cpp KBlocksLayout.cpp KBlocksGameLogic.cpp KBlocksSingleGame.cpp KBlocksField.cpp KBlocksPiece.cpp KBlocksPieceGenerator.cpp KBlocksGameMessage.cpp KBlocksGameRecorder.cpp KBlocksGameReplayer.cpp AI/KBlocksAIPlayer.cpp AI/KBlocksAIPlanner.cpp AI/KBlocksAIPlannerExtend.cpp AI/KBlocksAIEvaluation.cpp AI/KBlocksAIFeature.cpp AI/KBlocksAILog.cpp + utils.cpp ) ecm_setup_version(${KDE_APPLICATIONS_VERSION} VARIABLE_PREFIX KBLOCKS VERSION_HEADER kblocks_version.h) ecm_qt_declare_logging_category(kblocks_SRCS HEADER kblocks_ai_debug.h IDENTIFIER KBlocksAI CATEGORY_NAME KBlocks.AI) ecm_qt_declare_logging_category(kblocks_SRCS HEADER kblocks_sound_debug.h IDENTIFIER KBSound CATEGORY_NAME KBlocks.Sound) ecm_qt_declare_logging_category(kblocks_SRCS HEADER kblocks_replay_debug.h IDENTIFIER KBReplay CATEGORY_NAME KBlocks.Replay) ecm_qt_declare_logging_category(kblocks_SRCS HEADER kblocks_graphics_debug.h IDENTIFIER KBGraphics CATEGORY_NAME KBlocks.Graphics) kconfig_add_kcfg_files(kblocks_SRCS settings.kcfgc ) file(GLOB ICONS_SRCS "*-apps-kblocks.png") ecm_add_app_icon(kblocks_SRCS ICONS ${ICONS_SRCS}) add_executable(kblocks ${kblocks_SRCS}) target_link_libraries(kblocks KF5KDEGames KF5KDEGamesPrivate Qt5::Network KF5::Crash KF5::DBusAddons KF5::XmlGui KF5::I18n Qt5::Svg ) install(TARGETS kblocks ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) ########### install files ############### install(PROGRAMS org.kde.kblocks.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES org.kde.kblocks.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install(FILES kblocks.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) install(FILES kblocksui.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/kblocks) install(FILES kblocks.knsrc DESTINATION ${KDE_INSTALL_CONFDIR}) ecm_install_icons(ICONS 128-apps-kblocks.png 16-apps-kblocks.png 22-apps-kblocks.png 32-apps-kblocks.png 48-apps-kblocks.png 64-apps-kblocks.png DESTINATION ${KDE_INSTALL_ICONDIR} THEME hicolor) if (${ECM_VERSION} STRGREATER "5.58.0") install(FILES kblocks.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) else() install(FILES kblocks.categories DESTINATION ${KDE_INSTALL_CONFDIR}) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/KBlocksConfigManager.cpp b/KBlocksConfigManager.cpp index 075c138..07650ce 100644 --- a/KBlocksConfigManager.cpp +++ b/KBlocksConfigManager.cpp @@ -1,400 +1,399 @@ /*************************************************************************** * KBlocks, a falling blocks game by KDE * * Copyright (C) 2010 Zhongjie Cai * * * * 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. * ***************************************************************************/ #include "KBlocksConfigManager.h" #include #include #include -#include #include #include #include KBlocksConfigManager::KBlocksConfigManager() { stConfigSectionList.clear(); stConfigKeyNameList.clear(); stConfigDataTable.clear(); isDebug = false; } KBlocksConfigManager::~KBlocksConfigManager() { stConfigSectionList.clear(); stConfigKeyNameList.clear(); stConfigDataTable.clear(); } int KBlocksConfigManager::SetDebugOutput(bool flag) { isDebug = flag; return 0; } int KBlocksConfigManager::LoadConfigFile(const string &filename) { FILE *fp; int result; fp = fopen(filename.c_str(), "r"); if (fp == NULL) { return -1; } result = ParseConfigFile(fp); fclose(fp); return result; } int KBlocksConfigManager::SaveConfigFile(const string &filename) { FILE *fp; int result; fp = fopen(filename.c_str(), "w+"); if (fp == NULL) { return -1; } result = ConstructConfigFile(fp); fclose(fp); return result; } int KBlocksConfigManager::GetSectionCount() { return stConfigSectionList.size(); } int KBlocksConfigManager::GetKeyCount(const string &SectionName) { map< string, map >::iterator it; it = stConfigDataTable.find(SectionName); if (it == stConfigDataTable.end()) { return -1; } map tmpMap = it->second; return tmpMap.size(); } int KBlocksConfigManager::GetKeyString(const string &SectionName, const string &KeyName, string *KeyString, const string &Default) { map< string, map >::iterator it; it = stConfigDataTable.find(SectionName); if (it == stConfigDataTable.end()) { *KeyString = Default; return -1; } map tmpMap = it->second; if (tmpMap.find(KeyName) == tmpMap.end()) { *KeyString = Default; return -1; } *KeyString = tmpMap[KeyName]; return 0; } int KBlocksConfigManager::GetKeyInt(const string &SectionName, const string &KeyName, int *KeyInt, const int Default) { map< string, map >::iterator it; it = stConfigDataTable.find(SectionName); if (it == stConfigDataTable.end()) { *KeyInt = Default; return -1; } map tmpMap = it->second; if (tmpMap.find(KeyName) == tmpMap.end()) { *KeyInt = Default; return -1; } string tmpString = tmpMap[KeyName]; char *endptr; if (tmpString.find("0x") == tmpString.npos) { *KeyInt = strtol(tmpString.c_str(), &endptr, 10); } else { *KeyInt = strtol(tmpString.c_str(), &endptr, 16); } return 0; } int KBlocksConfigManager::GetKeyBool(const string &SectionName, const string &KeyName, bool *KeyBool, const bool Default) { string tmpValue; if (GetKeyString(SectionName, KeyName, &tmpValue, "") == -1) { *KeyBool = Default; return -1; } transform(tmpValue.begin(), tmpValue.end(), tmpValue.begin(), (int(*)(int))tolower); if (tmpValue.find("true") != tmpValue.npos) { *KeyBool = true; } else if (tmpValue.find("false") != tmpValue.npos) { *KeyBool = false; } return 0; } int KBlocksConfigManager::SetKeyString(string SectionName, string KeyName, string KeyString) { map tmpKeyName; map< string, map< int, string > >::iterator it_keyname; map tmpKeyMap; map< string, map >::iterator it_data; it_data = stConfigDataTable.find(SectionName); if (it_data == stConfigDataTable.end()) { stConfigDataTable.insert(pair< string, map >(SectionName, tmpKeyMap)); stConfigSectionList.insert(pair(stConfigSectionList.size() + 1, SectionName)); stConfigKeyNameList.insert(pair< string, map >(SectionName, tmpKeyName)); } it_data = stConfigDataTable.find(SectionName); tmpKeyMap = it_data->second; if (tmpKeyMap.find(KeyName) == tmpKeyMap.end()) { it_keyname = stConfigKeyNameList.find(SectionName); tmpKeyName = it_keyname->second; tmpKeyName.insert(pair(tmpKeyName.size() + 1, KeyName)); stConfigKeyNameList[SectionName] = tmpKeyName; tmpKeyMap.insert(pair(KeyName, KeyString)); } else { tmpKeyMap[KeyName] = KeyString; } stConfigDataTable[SectionName] = tmpKeyMap; return 0; } int KBlocksConfigManager::SetKeyInt(string SectionName, string KeyName, int KeyInt) { map tmpKeyName; map< string, map< int, string > >::iterator it_keyname; map tmpKeyMap; map< string, map >::iterator it_data; it_data = stConfigDataTable.find(SectionName); if (it_data == stConfigDataTable.end()) { stConfigDataTable.insert(pair< string, map >(SectionName, tmpKeyMap)); stConfigSectionList.insert(pair(stConfigSectionList.size() + 1, SectionName)); stConfigKeyNameList.insert(pair< string, map >(SectionName, tmpKeyName)); } it_data = stConfigDataTable.find(SectionName); tmpKeyMap = it_data->second; string tmpString = int16tostring(KeyInt); if (tmpKeyMap.find(KeyName) == tmpKeyMap.end()) { it_keyname = stConfigKeyNameList.find(SectionName); tmpKeyName = it_keyname->second; tmpKeyName.insert(pair(tmpKeyName.size() + 1, KeyName)); stConfigKeyNameList[SectionName] = tmpKeyName; tmpKeyMap.insert(pair(KeyName, tmpString)); } else { tmpKeyMap[KeyName] = tmpString; } stConfigDataTable[SectionName] = tmpKeyMap; return 0; } int KBlocksConfigManager::SetKeyBool(const string &SectionName, const string &KeyName, bool KeyBool) { if (KeyBool) { return SetKeyString(SectionName, KeyName, "true"); } else { return SetKeyString(SectionName, KeyName, "false"); } } int KBlocksConfigManager::ParseConfigFile(FILE *fp) { map< string, map< string, string > >::iterator it_section; map tmpKeyName; map< string, map< int, string > >::iterator it_keyname; map tmpKeyMap; map< string, map< string, string > >::iterator it_data; stConfigSectionList.clear(); stConfigKeyNameList.clear(); stConfigDataTable.clear(); string curSection = "DefaultSection"; string curKey = "DefaultKey"; string curValue = "DefaultValue"; int lenth; string tmpString; char tmpBuff[1024]; while (fgets(tmpBuff, 1024, fp)) { switch (tmpBuff[0]) { case '[': tmpString = string(tmpBuff); lenth = tmpString.find(']'); curSection = tmpString.substr(1, lenth - 1); it_section = stConfigDataTable.find(curSection); if (it_section == stConfigDataTable.end()) { map tmpKeyMap; stConfigDataTable.insert(pair< string, map >(curSection, tmpKeyMap)); map tmpKeyName; stConfigKeyNameList.insert(pair< string, map >(curSection, tmpKeyName)); stConfigSectionList.insert(pair(stConfigSectionList.size() + 1, curSection)); if (isDebug) { printf("New section loaded <%s>\n", curSection.c_str()); } } else { if (isDebug) { printf("Existing section updated <%s>\n", curSection.c_str()); } } break; case '#': // skip this line break; case '\n': // skip this line break; case '\0': // skip this line break; default: tmpString = string(tmpBuff); lenth = tmpString.find('='); curKey = tmpString.substr(0, lenth); if (tmpString[tmpString.size() - 1] == '\n') { tmpString[tmpString.size() - 1] = '\0'; } curValue = tmpString.substr(lenth + 1); transform(curValue.begin(), curValue.end(), curValue.begin(), (int(*)(int))tolower); it_data = stConfigDataTable.find(curSection); if (it_data == stConfigDataTable.end()) { stConfigDataTable.insert(pair< string, map >(curSection, tmpKeyMap)); stConfigSectionList.insert(pair(stConfigSectionList.size() + 1, curSection)); stConfigKeyNameList.insert(pair< string, map >(curSection, tmpKeyName)); if (isDebug) { printf("New section added <%s>\n", curSection.c_str()); } } else { tmpKeyMap = it_data->second; } if (tmpKeyMap.find(curKey) == tmpKeyMap.end()) { it_keyname = stConfigKeyNameList.find(curSection); tmpKeyName = it_keyname->second; tmpKeyName.insert(pair(tmpKeyName.size() + 1, curKey)); stConfigKeyNameList[curSection] = tmpKeyName; if (isDebug) { printf("New Key & Value loaded <%s=%s> for section <%s>\n", curKey.c_str(), curValue.c_str(), curSection.c_str()); } tmpKeyMap.insert(pair(curKey, curValue)); } else { if (isDebug) { printf("Existing Key & Value updated <%s=%s> for section <%s>\n", curKey.c_str(), curValue.c_str(), curSection.c_str()); } tmpKeyMap[curKey] = curValue; } stConfigDataTable[curSection] = tmpKeyMap; break; } } return 0; } int KBlocksConfigManager::ConstructConfigFile(FILE *fp) { for (unsigned int i = 1; i < stConfigSectionList.size() + 1; i++) { string tmpSectionName = stConfigSectionList[i]; fprintf(fp, "[%s]\n", tmpSectionName.c_str()); map tmpKeyName = stConfigKeyNameList[tmpSectionName]; map tmpKeyMap = stConfigDataTable[tmpSectionName]; for (unsigned int j = 1; j < tmpKeyName.size() + 1; j++) { string tmpKeyNameStr = tmpKeyName[j]; string tmpKeyValueStr = tmpKeyMap[tmpKeyName[j]]; fprintf(fp, "%s=%s\n", tmpKeyNameStr.c_str(), tmpKeyValueStr.c_str()); } } return 0; } string KBlocksConfigManager::int16tostring(int input) { string tmpString = ""; char tmpChar[2] = {0, 0}; do { tmpChar[0] = input & 0x0F; input >>= 4; if (tmpChar[0] < 10) { tmpChar[0] += '0'; } else { tmpChar[0] += 'a' - 10; } tmpString = string(tmpChar) + tmpString; } while (input != 0); tmpString = "0x" + tmpString; return tmpString; } diff --git a/KBlocksGameRecorder.cpp b/KBlocksGameRecorder.cpp index 6dfe8b7..69b2b9c 100644 --- a/KBlocksGameRecorder.cpp +++ b/KBlocksGameRecorder.cpp @@ -1,97 +1,85 @@ /*************************************************************************** * KBlocks, a falling blocks game by KDE * * Copyright (C) 2010 Zhongjie Cai * * * * 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. * ***************************************************************************/ #include "KBlocksGameRecorder.h" - -#include +#include "utils.h" KBlocksGameRecorder::KBlocksGameRecorder() { mGameRecord.clear(); } KBlocksGameRecorder::~KBlocksGameRecorder() { mGameRecord.clear(); } void KBlocksGameRecorder::append(int index, int type, int value) { _game_record_data tmpLastData; tmpLastData.index = index; tmpLastData.type = type; tmpLastData.value = value; - tmpLastData.time = getMillisecOfNow(); + tmpLastData.time = Utils::getMillisecOfNow(); mGameRecord.push_back(tmpLastData); } void KBlocksGameRecorder::save(const char *fileName, bool isBinaryMode) { FILE *pFile = fopen(fileName, "w"); if (isBinaryMode) { saveBinary(pFile); } else { saveText(pFile); } fclose(pFile); } void KBlocksGameRecorder::saveText(FILE *pFile) { int tmpTime = 0; timeLong oldTime = mGameRecord.front().time; list<_game_record_data>::iterator it; for (it = mGameRecord.begin(); it != mGameRecord.end(); ++it) { tmpTime = (int)(it->time - oldTime); oldTime = it->time; fprintf(pFile, "%d %s %d %d\n", tmpTime, KBlocksRecordText[it->type], it->index, it->value); } } void KBlocksGameRecorder::saveBinary(FILE *pFile) { int tmpTime = 0; timeLong oldTime = mGameRecord.front().time; list<_game_record_data>::iterator it; for (it = mGameRecord.begin(); it != mGameRecord.end(); ++it) { tmpTime = (int)(it->time - oldTime); oldTime = it->time; if (tmpTime > 255) { while (tmpTime > 255) { writeByte(pFile, 255); writeByte(pFile, RecordDataType_Skipped); writeByte(pFile, it->index); writeByte(pFile, it->value); tmpTime -= 255; } } writeByte(pFile, tmpTime); writeByte(pFile, it->type); writeByte(pFile, it->index); writeByte(pFile, it->value); } } void KBlocksGameRecorder::writeByte(FILE *pFile, int value) { int tmpByte = (value & 0xFF); fputc(tmpByte, pFile); } -timeLong KBlocksGameRecorder::getMillisecOfNow() -{ - timeval tmpCurTime; - - gettimeofday(&tmpCurTime, NULL); - - timeLong tmpMilliTime = (timeLong)tmpCurTime.tv_usec / 1000; - tmpMilliTime += (timeLong)tmpCurTime.tv_sec * 1000; - - return tmpMilliTime; -} diff --git a/KBlocksGameRecorder.h b/KBlocksGameRecorder.h index a62a268..94898b1 100644 --- a/KBlocksGameRecorder.h +++ b/KBlocksGameRecorder.h @@ -1,50 +1,48 @@ /*************************************************************************** * KBlocks, a falling blocks game by KDE * * Copyright (C) 2010 Zhongjie Cai * * * * 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. * ***************************************************************************/ #ifndef KBLOCKSGAMERECORDER_H #define KBLOCKSGAMERECORDER_H #include "KBlocksDefine.h" #include #include #include using std::string; using std::list; struct _game_record_data { int index; int type; int value; timeLong time; }; class KBlocksGameRecorder { public: KBlocksGameRecorder(); ~KBlocksGameRecorder(); public: void append(int index, int type, int value); void save(const char *fileName, bool isBinaryMode = true); private: void saveText(FILE *pFile); void saveBinary(FILE *pFile); void writeByte(FILE *pFile, int value); - timeLong getMillisecOfNow(); - private: list<_game_record_data> mGameRecord; }; #endif diff --git a/KBlocksSingleGame.cpp b/KBlocksSingleGame.cpp index 71b633e..9224ebc 100644 --- a/KBlocksSingleGame.cpp +++ b/KBlocksSingleGame.cpp @@ -1,407 +1,396 @@ /*************************************************************************** * KBlocks, a falling blocks game by KDE * * Copyright (C) 2010 Zhongjie Cai * * * * 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. * ***************************************************************************/ #include "KBlocksSingleGame.h" #include "KBlocksField.h" #include "KBlocksPiece.h" - +#include "utils.h" KBlocksSingleGame::KBlocksSingleGame(int gameIndex, int fieldWidth, int fieldHeight, int showPieceCount, int messagePoolSize) { mGameIndex = gameIndex; mpField = new KBlocksField(fieldWidth, fieldHeight); mPieceCount = showPieceCount; mpPieceList = new KBlocksPiece*[mPieceCount]; for (int i = 0; i < mPieceCount; i++) { mpPieceList[i] = new KBlocksPiece(); } mpPieceGenerator = new KBlocksPieceGenerator(); mpGameMessage = new KBlocksGameMessage(messagePoolSize); mpGameRecorder = 0; mCurrentGameState = GameState_Stop; mStandbyMode = false; mStandbyFlag = false; mGameInterval = 0; mGameStartTime = 0; } KBlocksSingleGame::~KBlocksSingleGame() { delete mpGameMessage; delete mpPieceGenerator; for (int i = 0; i < mPieceCount; i++) { delete mpPieceList[i]; } delete [] mpPieceList; delete mpField; } KBlocksField *KBlocksSingleGame::getField() { return mpField; } int KBlocksSingleGame::getPieceCount() { return mPieceCount; } KBlocksPiece *KBlocksSingleGame::getPiece(int index) { if ((index < 0) || (index >= mPieceCount)) { return 0; } return mpPieceList[index]; } bool KBlocksSingleGame::isActive() { if ((mCurrentGameState != GameState_Running) || mStandbyFlag) { return false; } return true; } bool KBlocksSingleGame::isGameRunning() { if (mCurrentGameState == GameState_Stop) { return false; } return true; } void KBlocksSingleGame::setGameStandbyMode(bool flag) { mStandbyMode = flag; } void KBlocksSingleGame::setGameInterval(int interval) { mGameInterval = interval; } void KBlocksSingleGame::setGameRecorder(KBlocksGameRecorder *p) { mpGameRecorder = p; } int KBlocksSingleGame::forceUpdateGame() { return doUpdateGame(true); } int KBlocksSingleGame::updateGame() { return doUpdateGame(false); } int KBlocksSingleGame::punishGame(int lineCount, int punishSeed) { if (mCurrentGameState == GameState_Stop) { return GameResult_None; } int width = mpField->getWidth(); int gameResult = GameResult_None; if (mpGameRecorder) { mpGameRecorder->append(mGameIndex, RecordDataType_PunishLineCount, lineCount); mpGameRecorder->append(mGameIndex, RecordDataType_PunishLineSeed, punishSeed); } qsrand(punishSeed); int punishIndex = 0; for (int i = 0; i < lineCount; i++) { setCurrentPiece(0, -1, 0); punishIndex = qrand() % width; mpField->addPunishLine(lineCount, punishIndex); } if (lineCount > 0) { mpGameMessage->putGameAction(GameAction_Punish_Line, lineCount); } return gameResult; } bool KBlocksSingleGame::setCurrentPiece(int xPos, int yPos, int rotation) { if ((mCurrentGameState != GameState_Running) || mStandbyFlag) { return false; } //FIXME: new without delete (is the new really necessary here?) QScopedPointer tmpPiece(new KBlocksPiece()); tmpPiece->fromValue(mpPieceList[0]->toValue()); tmpPiece->setPosX(mpPieceList[0]->getPosX() + xPos); if (mpPieceList[0]->getPosY() + yPos < 0) { tmpPiece->setPosY(0); } else { tmpPiece->setPosY(mpPieceList[0]->getPosY() + yPos); } tmpPiece->setRotation(mpPieceList[0]->getRotation() + rotation); if (checkPieceTouchGround(tmpPiece.data())) { return false; } mpPieceList[0]->setPosX(tmpPiece->getPosX()); mpPieceList[0]->setPosY(tmpPiece->getPosY()); mpPieceList[0]->setRotation(tmpPiece->getRotation()); if (mpGameRecorder) { if (xPos < 0) { mpGameRecorder->append(mGameIndex, RecordDataType_MovePieceLeft, 1); } if (xPos > 0) { mpGameRecorder->append(mGameIndex, RecordDataType_MovePieceRight, 1); } if (yPos < 0) { mpGameRecorder->append(mGameIndex, RecordDataType_MovePieceUp, 1); } if (yPos > 0) { mpGameRecorder->append(mGameIndex, RecordDataType_MovePieceDown, 1); } if (rotation < 0) { mpGameRecorder->append(mGameIndex, RecordDataType_RotatePieceCW, 1); } if (rotation > 0) { mpGameRecorder->append(mGameIndex, RecordDataType_RotatePieceCCW, 1); } } return true; } int KBlocksSingleGame::startGame(int seed) { if (mCurrentGameState != GameState_Stop) { return mCurrentGameState; } mpPieceGenerator->genList(seed); for (int i = 0; i < mPieceCount; i++) { mpPieceList[i]->fromValue(mpPieceGenerator->getPiece()); } mpPieceList[0]->setPosX(mpField->getWidth() / 2); mpPieceList[0]->setPosY(0); mpPieceList[1]->setPosX(2); mpPieceList[1]->setPosY(2); mpGameMessage->clearGameResult(); mpGameMessage->clearGameAction(); mCurrentGameState = GameState_Running; - mGameStartTime = getMillisecOfNow(); + mGameStartTime = Utils::getMillisecOfNow(); return mCurrentGameState; } int KBlocksSingleGame::stopGame() { if (mCurrentGameState != GameState_Stop) { mCurrentGameState = GameState_Stop; emit gameStopped(); } return mCurrentGameState; } int KBlocksSingleGame::pauseGame(bool flag) { if ((mCurrentGameState == GameState_Running) && flag) { mCurrentGameState = GameState_Pause; } else if ((mCurrentGameState == GameState_Pause) && (!flag)) { mCurrentGameState = GameState_Running; - mGameStartTime = getMillisecOfNow(); + mGameStartTime = Utils::getMillisecOfNow(); } return mCurrentGameState; } int KBlocksSingleGame::continueGame() { if ((mCurrentGameState != GameState_Stop) && mStandbyFlag) { mStandbyFlag = false; - mGameStartTime = getMillisecOfNow(); + mGameStartTime = Utils::getMillisecOfNow(); } return mCurrentGameState; } bool KBlocksSingleGame::pickGameResult(int *result) { return mpGameMessage->pickGameResult(result); } bool KBlocksSingleGame::pickGameAction(int *type, int *action) { return mpGameMessage->pickGameAction(type, action); } int KBlocksSingleGame::doUpdateGame(bool force) { if (mCurrentGameState == GameState_Stop) { return GameResult_Game_Over; } else if ((mCurrentGameState != GameState_Running) || mStandbyFlag) { return GameResult_None; } - timeLong tmpCurTime = getMillisecOfNow(); + timeLong tmpCurTime = Utils::getMillisecOfNow(); int gameResult = GameResult_None; if (force) { runGameOneStep(&gameResult); } else { if (mGameInterval < 0) { return gameResult; } while (1) { if (mGameStartTime + mGameInterval > tmpCurTime) { break; } mGameStartTime += mGameInterval; if (runGameOneStep(&gameResult) || (mGameInterval == 0)) { break; } } } return gameResult; } bool KBlocksSingleGame::runGameOneStep(int *gameResult) { if (!setCurrentPiece(0, 1, 0)) { *gameResult = GameResult_Next_Piece; freezePieceToField(mpPieceList[0]); *gameResult += removeFieldLines(); if (mStandbyMode) { mStandbyFlag = true; } prepareNextPiece(); if (checkPieceTouchGround(mpPieceList[0])) { *gameResult = GameResult_Game_Over; mpGameMessage->putGameResult(-1); stopGame(); } if (mpGameRecorder) { mpGameRecorder->append(mGameIndex, RecordDataType_GameOneStep, 1); } return true; } else { *gameResult = GameResult_One_Step; return false; } } bool KBlocksSingleGame::checkPieceTouchGround(KBlocksPiece *p) { for (int i = 0; i < 4; i++) { int posX = p->getCellPosX(i); int posY = p->getCellPosY(i); if (mpField->getCell(posX, posY)) { return true; } } return false; } void KBlocksSingleGame::freezePieceToField(KBlocksPiece *p) { mpGameMessage->putGameAction(GameAction_Freeze_Piece_Color, mpPieceList[0]->getType()); for (int i = 0; i < 4; i++) { int posX = p->getCellPosX(i); int posY = p->getCellPosY(i); mpField->setCell(posX, posY, true); mpGameMessage->putGameAction(GameAction_Freeze_Piece_X, posX); mpGameMessage->putGameAction(GameAction_Freeze_Piece_Y, posY); } } int KBlocksSingleGame::removeFieldLines() { int lineCount = 0; int maxLines = mpField->getHeight(); for (int i = 0; i < maxLines; i++) { if (mpField->checkFilledLine(i)) { mpGameMessage->putGameAction(GameAction_Remove_Line, i); mpField->removeFilledLine(i); lineCount++; } } if (lineCount > 0) { mpGameMessage->putGameResult(lineCount); } return lineCount; } void KBlocksSingleGame::prepareNextPiece() { for (int i = 0; i < mPieceCount - 1; i++) { mpPieceList[i]->fromValue(mpPieceList[i + 1]->toValue()); } int pieceValue = mpPieceGenerator->getPiece(); mpPieceList[mPieceCount - 1]->fromValue(pieceValue); mpPieceList[0]->setPosX(mpField->getWidth() / 2); mpPieceList[0]->setPosY(0); mpPieceList[1]->setPosX(2); mpPieceList[1]->setPosY(2); for (int i = 0; i < 4; i++) { int posX = mpPieceList[0]->getCellPosX(i); int posY = mpPieceList[0]->getCellPosY(i); mpGameMessage->putGameAction(GameAction_New_Piece_X, posX); mpGameMessage->putGameAction(GameAction_New_Piece_Y, posY); } } -timeLong KBlocksSingleGame::getMillisecOfNow() -{ - timeval tmpCurTime; - - gettimeofday(&tmpCurTime, NULL); - - timeLong tmpMilliTime = (timeLong)tmpCurTime.tv_usec / 1000; - tmpMilliTime += (timeLong)tmpCurTime.tv_sec * 1000; - - return tmpMilliTime; -} diff --git a/KBlocksSingleGame.h b/KBlocksSingleGame.h index f91c105..1ffb34b 100644 --- a/KBlocksSingleGame.h +++ b/KBlocksSingleGame.h @@ -1,97 +1,94 @@ /*************************************************************************** * KBlocks, a falling blocks game by KDE * * Copyright (C) 2010 Zhongjie Cai * * * * 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. * ***************************************************************************/ #ifndef KBLOCKSSINGLEGAME_H #define KBLOCKSSINGLEGAME_H -#include #include #include "SingleGameInterface.h" #include "KBlocksField.h" #include "KBlocksPiece.h" #include "KBlocksPieceGenerator.h" #include "KBlocksGameMessage.h" #include "KBlocksGameRecorder.h" #include "KBlocksDefine.h" class KBlocksSingleGame : public QObject, public SingleGameInterface { Q_OBJECT public: explicit KBlocksSingleGame(int gameIndex, int fieldWidth = 10, int fieldHeight = 20, int showPieceCount = 2, int messagePoolSize = 256); ~KBlocksSingleGame(); public: KBlocksField *getField() override; int getPieceCount() override; KBlocksPiece *getPiece(int index) override; bool isActive() override; bool isGameRunning() override; void setGameStandbyMode(bool flag); void setGameInterval(int interval); void setGameRecorder(KBlocksGameRecorder *p); int forceUpdateGame() override; int updateGame() override; int punishGame(int lineCount, int punishSeed); bool setCurrentPiece(int xPos, int yPos, int rotation) override; int startGame(int seed); int stopGame(); int pauseGame(bool flag); int continueGame() override; bool pickGameResult(int *result) override; bool pickGameAction(int *type, int *action) override; signals: void gameStopped(); private: int doUpdateGame(bool force); bool runGameOneStep(int *gameResult); bool checkPieceTouchGround(KBlocksPiece *p); void freezePieceToField(KBlocksPiece *p); int removeFieldLines(); void prepareNextPiece(); - timeLong getMillisecOfNow(); - protected: KBlocksField *mpField = nullptr; int mPieceCount; KBlocksPiece **mpPieceList = nullptr; private: KBlocksPieceGenerator *mpPieceGenerator = nullptr; KBlocksGameMessage *mpGameMessage = nullptr; KBlocksGameRecorder *mpGameRecorder = nullptr; int mGameIndex; int mCurrentGameState; bool mStandbyMode; bool mStandbyFlag; int mGameInterval; timeLong mGameStartTime; }; #endif diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 0000000..3b09d11 --- /dev/null +++ b/utils.cpp @@ -0,0 +1,11 @@ +#include "utils.h" + +#include +#include + +timeLong Utils::getMillisecOfNow() +{ + const auto now = std::chrono::system_clock::now(); + + return std::chrono::duration_cast(now.time_since_epoch()).count(); +} diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..bbd59ba --- /dev/null +++ b/utils.h @@ -0,0 +1,9 @@ +#ifndef UTILS_H +#define UTILS_H + +#include "KBlocksDefine.h" + +namespace Utils { + timeLong getMillisecOfNow(); +} +#endif