diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f75106c5..6c501750 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false steps: - name: Install Colobot dependencies - run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet libmpg123-dev if: matrix.container == '' - uses: actions/checkout@v2 - name: Checkout the Google Test submodule @@ -134,11 +134,11 @@ jobs: - name: Install Colobot dependencies uses: lukka/run-vcpkg@v7 with: - vcpkgGitCommitId: '210240b399fbc2f1363f4103b6a93629c207d7e3' + vcpkgGitCommitId: 'e809a42f87565e803b2178a0c11263f462d1800a' vcpkgTriplet: ${{ matrix.vcpkg_triplet }} - vcpkgArguments: 'boost-system boost-filesystem boost-regex boost-lexical-cast boost-bimap boost-algorithm boost-property-tree boost-optional boost-range sdl2 sdl2-ttf sdl2-image glew libpng libwebp tiff gettext libsndfile libvorbis libogg openal-soft physfs' + vcpkgArguments: 'boost-system boost-filesystem boost-regex boost-lexical-cast boost-bimap boost-algorithm boost-property-tree boost-optional boost-range sdl2 sdl2-ttf sdl2-image glew libpng libwebp tiff gettext libsndfile libvorbis libogg openal-soft physfs mpg123' # SHA-256 hash of the list of packages above, for caching purposes - appendedCacheKey: '35754367e6e6b4fb1b1ec24fa631e5234548fa1f9a59e4f2d80d2174a3a4e1b5' + appendedCacheKey: '84402d9834b06a1b571e0fda32a791915777d47a394a1469d4773322bd71614b' - name: Install external tools working-directory: ${{ github.workspace }} run: | @@ -194,7 +194,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Colobot dependencies - run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet doxygen graphviz + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet doxygen graphviz libmpg123-dev - uses: actions/checkout@v2 - name: Create build directory run: cmake -E make_directory build diff --git a/CMakeLists.txt b/CMakeLists.txt index 19e2fa0d..68b4d827 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,8 +329,11 @@ find_package(GLEW REQUIRED) if (OPENAL_SOUND) find_package(OpenAL REQUIRED) endif() + find_package(SndFile REQUIRED) +find_package(mpg123 QUIET) +find_package(mp3lame QUIET) if(NOT ASSERTS) add_definitions(-DNDEBUG) diff --git a/po/pl.po b/po/pl.po index 90e9f65f..8bad637b 100644 --- a/po/pl.po +++ b/po/pl.po @@ -86,7 +86,7 @@ msgid "Access to solution\\Shows the solution (detailed instructions for mission msgstr "Dostęp do rozwiązania\\Pokazuje rozwiązanie (szczegółowe instrukcje dotyczące misji)" msgid "Access to solutions\\Show program \"4: Solution\" in the exercises" -msgstr "Accčs aux solutions\\Programme \"4: Solution\" dans les exercices" +msgstr "Dostęp do rozwiązań\\Pokaż program \"4: Rozwiązanie\" w ćwiczeniach" msgid "Add new program" msgstr "Dodaj nowy program" diff --git a/src/CBot/CBotInstr/CBotExprLitNan.cpp b/src/CBot/CBotInstr/CBotExprLitNan.cpp index 52e30d5f..9ae23150 100644 --- a/src/CBot/CBotInstr/CBotExprLitNan.cpp +++ b/src/CBot/CBotInstr/CBotExprLitNan.cpp @@ -23,6 +23,8 @@ #include "CBot/CBotVar/CBotVar.h" +#include + namespace CBot { @@ -41,9 +43,9 @@ bool CBotExprLitNan::Execute(CBotStack* &pj) CBotStack* pile = pj->AddStack(this); if (pile->IfStep()) return false; - CBotVar* var = CBotVar::Create("", CBotTypInt); + CBotVar* var = CBotVar::Create("", CBotTypFloat); - var->SetInit(CBotVar::InitType::IS_NAN); // nan + var->SetValFloat(nanf("")); pile->SetVar(var); // put on the stack return pj->Return(pile); // forward below } diff --git a/src/CBot/CBotInstr/CBotExpression.cpp b/src/CBot/CBotInstr/CBotExpression.cpp index 2374a2a6..8a9e91de 100644 --- a/src/CBot/CBotInstr/CBotExpression.cpp +++ b/src/CBot/CBotInstr/CBotExpression.cpp @@ -206,12 +206,6 @@ bool CBotExpression::Execute(CBotStack* &pj) if (m_token.GetType() != ID_ASS) { pVar = pile1->GetVar(); // recovers if interrupted - initKind = pVar->GetInit(); - if (initKind == CBotVar::InitType::IS_NAN) - { - pile2->SetError(CBotErrNan, m_leftop->GetToken()); - return pj->Return(pile2); - } result = CBotVar::Create("", pVar->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC)); } diff --git a/src/CBot/CBotInstr/CBotParExpr.cpp b/src/CBot/CBotInstr/CBotParExpr.cpp index 46f72818..4986560b 100644 --- a/src/CBot/CBotInstr/CBotParExpr.cpp +++ b/src/CBot/CBotInstr/CBotParExpr.cpp @@ -38,6 +38,8 @@ #include "CBot/CBotCStack.h" +#include + namespace CBot { @@ -217,8 +219,8 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack) { CBotInstr* inst = new CBotExprLitNan(); inst->SetToken(pp); - CBotVar* var = CBotVar::Create("", CBotTypInt); - var->SetInit(CBotVar::InitType::IS_NAN); + CBotVar* var = CBotVar::Create("", CBotTypFloat); + var->SetValFloat(nanf("")); pStk->SetVar(var); return pStack->Return(inst, pStk); } diff --git a/src/CBot/CBotInstr/CBotPostIncExpr.cpp b/src/CBot/CBotInstr/CBotPostIncExpr.cpp index fac31e2c..5ce6284d 100644 --- a/src/CBot/CBotInstr/CBotPostIncExpr.cpp +++ b/src/CBot/CBotInstr/CBotPostIncExpr.cpp @@ -56,11 +56,6 @@ bool CBotPostIncExpr::Execute(CBotStack* &pj) CBotStack* pile3 = pile2->AddStack(this); if (pile3->IfStep()) return false; - if (var1->IsNAN()) - { - pile1->SetError(CBotErrNan, &m_token); - } - if (!var1->IsDefined()) { pile1->SetError(CBotErrNotInit, &m_token); diff --git a/src/CBot/CBotInstr/CBotPreIncExpr.cpp b/src/CBot/CBotInstr/CBotPreIncExpr.cpp index afb2b65c..6416215b 100644 --- a/src/CBot/CBotInstr/CBotPreIncExpr.cpp +++ b/src/CBot/CBotInstr/CBotPreIncExpr.cpp @@ -55,12 +55,6 @@ bool CBotPreIncExpr::Execute(CBotStack* &pj) // pile2 is modified on return if (!(static_cast(m_instr))->ExecuteVar(var1, pile2, nullptr, true)) return false; - if (var1->IsNAN()) - { - pile->SetError(CBotErrNan, &m_token); - return pj->Return(pile); // operation performed - } - if (!var1->IsDefined()) { pile->SetError(CBotErrNotInit, &m_token); diff --git a/src/CBot/CBotInstr/CBotTwoOpExpr.cpp b/src/CBot/CBotInstr/CBotTwoOpExpr.cpp index ad09f221..9072a48e 100644 --- a/src/CBot/CBotInstr/CBotTwoOpExpr.cpp +++ b/src/CBot/CBotInstr/CBotTwoOpExpr.cpp @@ -31,6 +31,7 @@ #include "CBot/CBotVar/CBotVar.h" #include +#include #include namespace CBot @@ -305,7 +306,13 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera static bool VarIsNAN(const CBotVar* var) { - return var->GetInit() > CBotVar::InitType::DEF; + if (var->GetType() == CBotTypFloat) + return std::isnan(var->GetValFloat()); + + if (var->GetType() == CBotTypDouble) + return std::isnan(var->GetValDouble()); + + return false; } static bool IsNan(CBotVar* left, CBotVar* right, CBotError* err = nullptr) @@ -475,13 +482,13 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack) break; case ID_EQ: if ( IsNan(left, right) ) - result->SetValInt(left->GetInit() == right->GetInit()) ; + result->SetValInt(VarIsNAN(left) == VarIsNAN(right)); else result->SetValInt(temp->Eq(left , right)); // equal break; case ID_NE: if ( IsNan(left, right) ) - result->SetValInt(left ->GetInit() != right->GetInit()) ; + result->SetValInt(VarIsNAN(left) != VarIsNAN(right)); else result->SetValInt(temp->Ne(left , right)); // different break; diff --git a/src/CBot/CBotVar/CBotVar.cpp b/src/CBot/CBotVar/CBotVar.cpp index c975ed7b..4c268cb4 100644 --- a/src/CBot/CBotVar/CBotVar.cpp +++ b/src/CBot/CBotVar/CBotVar.cpp @@ -355,7 +355,7 @@ CBotTypResult CBotVar::GetTypResult(GetTypeMode mode) } //////////////////////////////////////////////////////////////////////////////// -CBotType CBotVar::GetType(GetTypeMode mode) +CBotType CBotVar::GetType(GetTypeMode mode) const { if ( mode == GetTypeMode::CLASS_AS_POINTER && m_type.Eq(CBotTypClass) ) return CBotTypPointer; @@ -584,43 +584,43 @@ CBotVarClass* CBotVar::GetPointer() // All these functions must be defined in the subclasses // derived from class CBotVar -signed char CBotVar::GetValByte() +signed char CBotVar::GetValByte() const { assert(0); return 0; } -short CBotVar::GetValShort() +short CBotVar::GetValShort() const { assert(0); return 0; } -uint32_t CBotVar::GetValChar() +uint32_t CBotVar::GetValChar() const { assert(0); return 0; } -int CBotVar::GetValInt() +int CBotVar::GetValInt() const { assert(0); return 0; } -long CBotVar::GetValLong() +long CBotVar::GetValLong() const { assert(0); return 0; } -float CBotVar::GetValFloat() +float CBotVar::GetValFloat() const { assert(0); return 0; } -double CBotVar::GetValDouble() +double CBotVar::GetValDouble() const { assert(0); return 0; @@ -822,7 +822,7 @@ void CBotVar::SetValString(const std::string& val) } //////////////////////////////////////////////////////////////////////////////// -std::string CBotVar::GetValString() +std::string CBotVar::GetValString() const { assert(0); return std::string(); diff --git a/src/CBot/CBotVar/CBotVar.h b/src/CBot/CBotVar/CBotVar.h index e351398d..c9739e3f 100644 --- a/src/CBot/CBotVar/CBotVar.h +++ b/src/CBot/CBotVar/CBotVar.h @@ -199,7 +199,7 @@ public: * \brief GetType Returns the base type of the variable (::CBotType) * \param mode Mode, see GetTypeMode enum */ - CBotType GetType(GetTypeMode mode = GetTypeMode::NORMAL); + CBotType GetType(GetTypeMode mode = GetTypeMode::NORMAL) const; /** * \brief Returns the complete type of the variable (CBotTypResult) @@ -243,7 +243,6 @@ public: UNDEF = 0, //!< the variable value is currently not defined DEF = 1, //!< the variable value is defined IS_POINTER = 2, //!< the variable value is as a pointer - IS_NAN = 999 //!< the variable value is NAN }; /** @@ -269,12 +268,6 @@ public: */ bool IsDefined() const { return GetInit() == InitType::DEF; } - /** - * \brief Checks if the variable is currently NAN - * \return InitType::NAN - */ - bool IsNAN() const { return GetInit() == InitType::IS_NAN; } - //@} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -508,27 +501,27 @@ public: */ virtual void SetValString(const std::string& val); - virtual signed char GetValByte(); + virtual signed char GetValByte() const; - virtual short GetValShort(); + virtual short GetValShort() const; - virtual uint32_t GetValChar(); + virtual uint32_t GetValChar() const; /** * \brief Get value as integer * \return Current value */ - virtual int GetValInt(); + virtual int GetValInt() const; - virtual long GetValLong(); + virtual long GetValLong() const; /** * \brief Get value as float * \return Current value */ - virtual float GetValFloat(); + virtual float GetValFloat() const; - virtual double GetValDouble(); + virtual double GetValDouble() const; /** * \brief Get value as string @@ -539,7 +532,7 @@ public: * * \return Current value */ - virtual std::string GetValString(); + virtual std::string GetValString() const; /** * \brief Set value for pointer types diff --git a/src/CBot/CBotVar/CBotVarArray.cpp b/src/CBot/CBotVar/CBotVarArray.cpp index b0895448..be31ddd2 100644 --- a/src/CBot/CBotVar/CBotVarArray.cpp +++ b/src/CBot/CBotVar/CBotVarArray.cpp @@ -129,7 +129,7 @@ CBotVar* CBotVarArray::GetItemList() } //////////////////////////////////////////////////////////////////////////////// -std::string CBotVarArray::GetValString() +std::string CBotVarArray::GetValString() const { if ( m_pInstance == nullptr ) return ( std::string( "Null pointer" ) ) ; return m_pInstance->GetValString(); diff --git a/src/CBot/CBotVar/CBotVarArray.h b/src/CBot/CBotVar/CBotVarArray.h index 46986900..144a5050 100644 --- a/src/CBot/CBotVar/CBotVarArray.h +++ b/src/CBot/CBotVar/CBotVarArray.h @@ -49,7 +49,7 @@ public: CBotVar* GetItem(int n, bool grow = false) override; CBotVar* GetItemList() override; - std::string GetValString() override; + std::string GetValString() const override; bool Save1State(std::ostream &ostr) override; diff --git a/src/CBot/CBotVar/CBotVarChar.h b/src/CBot/CBotVar/CBotVarChar.h index 7b6031d5..168604f6 100644 --- a/src/CBot/CBotVar/CBotVarChar.h +++ b/src/CBot/CBotVar/CBotVarChar.h @@ -32,12 +32,10 @@ class CBotVarChar : public CBotVarInteger public: CBotVarChar(const CBotToken &name) : CBotVarInteger(name) {} - std::string GetValString() override + std::string GetValString() const override { if (m_binit == CBotVar::InitType::UNDEF) return LoadString(TX_UNDEF); - if (m_binit == CBotVar::InitType::IS_NAN) - return LoadString(TX_NAN); if (0x10FFFF < m_val || (0xD7FF < m_val && m_val < 0xE000)) return "\xEF\xBF\xBD"; // replacement character U+FFFD diff --git a/src/CBot/CBotVar/CBotVarClass.cpp b/src/CBot/CBotVar/CBotVarClass.cpp index c7d81cb5..5f7743e9 100644 --- a/src/CBot/CBotVar/CBotVarClass.cpp +++ b/src/CBot/CBotVar/CBotVarClass.cpp @@ -291,7 +291,7 @@ CBotVar* CBotVarClass::GetItemList() } //////////////////////////////////////////////////////////////////////////////// -std::string CBotVarClass::GetValString() +std::string CBotVarClass::GetValString() const { std::string res; diff --git a/src/CBot/CBotVar/CBotVarClass.h b/src/CBot/CBotVar/CBotVarClass.h index 254ec88b..75abca72 100644 --- a/src/CBot/CBotVar/CBotVarClass.h +++ b/src/CBot/CBotVar/CBotVarClass.h @@ -52,7 +52,7 @@ public: CBotVar* GetItemRef(int nIdent) override; CBotVar* GetItem(int n, bool bExtend) override; CBotVar* GetItemList() override; - std::string GetValString() override; + std::string GetValString() const override; bool Save1State(std::ostream &ostr) override; diff --git a/src/CBot/CBotVar/CBotVarInt.cpp b/src/CBot/CBotVar/CBotVarInt.cpp index 8a69a9f4..7e4fdc24 100644 --- a/src/CBot/CBotVar/CBotVarInt.cpp +++ b/src/CBot/CBotVar/CBotVarInt.cpp @@ -35,7 +35,7 @@ void CBotVarInt::SetValInt(int val, const std::string& defnum) m_defnum = defnum; } -std::string CBotVarInt::GetValString() +std::string CBotVarInt::GetValString() const { if (!m_defnum.empty()) return m_defnum; return CBotVarValue::GetValString(); diff --git a/src/CBot/CBotVar/CBotVarInt.h b/src/CBot/CBotVar/CBotVarInt.h index 62c4adeb..c41034d9 100644 --- a/src/CBot/CBotVar/CBotVarInt.h +++ b/src/CBot/CBotVar/CBotVarInt.h @@ -33,7 +33,7 @@ public: CBotVarInt(const CBotToken &name) : CBotVarInteger(name) {} void SetValInt(int val, const std::string& s = "") override; - std::string GetValString() override; + std::string GetValString() const override; void Copy(CBotVar* pSrc, bool bName = true) override; diff --git a/src/CBot/CBotVar/CBotVarPointer.cpp b/src/CBot/CBotVar/CBotVarPointer.cpp index ed5eda00..db979c97 100644 --- a/src/CBot/CBotVar/CBotVarPointer.cpp +++ b/src/CBot/CBotVar/CBotVarPointer.cpp @@ -90,7 +90,7 @@ CBotVar* CBotVarPointer::GetItemList() } //////////////////////////////////////////////////////////////////////////////// -std::string CBotVarPointer::GetValString() +std::string CBotVarPointer::GetValString() const { std::string s = "Pointer to "; if ( m_pVarClass == nullptr ) s = "Null pointer" ; diff --git a/src/CBot/CBotVar/CBotVarPointer.h b/src/CBot/CBotVar/CBotVarPointer.h index 4fa1d0ae..0d03ae44 100644 --- a/src/CBot/CBotVar/CBotVarPointer.h +++ b/src/CBot/CBotVar/CBotVarPointer.h @@ -47,7 +47,7 @@ public: CBotVar* GetItem(const std::string& name) override; CBotVar* GetItemRef(int nIdent) override; CBotVar* GetItemList() override; - std::string GetValString() override; + std::string GetValString() const override; void SetPointer(CBotVar* p) override; CBotVarClass* GetPointer() override; diff --git a/src/CBot/CBotVar/CBotVarString.h b/src/CBot/CBotVar/CBotVarString.h index 679c7a9a..b4ed70e4 100644 --- a/src/CBot/CBotVar/CBotVarString.h +++ b/src/CBot/CBotVar/CBotVarString.h @@ -48,12 +48,12 @@ public: SetValString(ToString(val)); } - int GetValInt() override + int GetValInt() const override { return FromString(GetValString()); } - float GetValFloat() override + float GetValFloat() const override { return FromString(GetValString()); } diff --git a/src/CBot/CBotVar/CBotVarValue.h b/src/CBot/CBotVar/CBotVarValue.h index c305aa2f..fddb6bfe 100644 --- a/src/CBot/CBotVar/CBotVarValue.h +++ b/src/CBot/CBotVar/CBotVarValue.h @@ -62,15 +62,13 @@ public: m_binit = CBotVar::InitType::DEF; } - std::string GetValString() override + std::string GetValString() const override { if (m_binit == CBotVar::InitType::UNDEF) return LoadString(TX_UNDEF); - if (m_binit == CBotVar::InitType::IS_NAN) - return LoadString(TX_NAN); std::ostringstream s; - s << m_val; + s << std::boolalpha << m_val; return s.str(); } @@ -133,37 +131,37 @@ public: this->SetValue(static_cast(val)); } - signed char GetValByte() override + signed char GetValByte() const override { return static_cast(this->m_val); } - short GetValShort() override + short GetValShort() const override { return static_cast(this->m_val); } - uint32_t GetValChar() override + uint32_t GetValChar() const override { return static_cast(this->m_val); } - int GetValInt() override + int GetValInt() const override { return static_cast(this->m_val); } - long GetValLong() override + long GetValLong() const override { return static_cast(this->m_val); } - float GetValFloat() override + float GetValFloat() const override { return static_cast(this->m_val); } - double GetValDouble() override + double GetValDouble() const override { return static_cast(this->m_val); } diff --git a/src/CBot/stdlib/FileFunctions.cpp b/src/CBot/stdlib/FileFunctions.cpp index 04e54ac1..bb48268d 100644 --- a/src/CBot/stdlib/FileFunctions.cpp +++ b/src/CBot/stdlib/FileFunctions.cpp @@ -133,7 +133,7 @@ bool rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception if (!pVar->IsDefined()) return true; // file not opened g_files.erase(pVar->GetValInt()); - pVar->SetInit(CBotVar::InitType::IS_NAN); + pVar->SetInit(CBotVar::InitType::UNDEF); return true; } @@ -203,7 +203,7 @@ bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, v g_files.erase(handleIter); - pVar->SetInit(CBotVar::InitType::IS_NAN); + pVar->SetInit(CBotVar::InitType::UNDEF); return true; } diff --git a/src/CBot/stdlib/MathFunctions.cpp b/src/CBot/stdlib/MathFunctions.cpp index 5353f80d..105f805a 100644 --- a/src/CBot/stdlib/MathFunctions.cpp +++ b/src/CBot/stdlib/MathFunctions.cpp @@ -218,6 +218,37 @@ bool rTrunc(CBotVar* var, CBotVar* result, int& exception, void* user) return true; } +// Instruction "isnan()" + +CBotTypResult cIsNAN(CBotVar*& var, void* user) +{ + if (var == nullptr) return CBotTypResult(CBotErrLowParam); + + if (var->GetType() > CBotTypDouble) return CBotTypResult(CBotErrBadNum); + + var = var->GetNext(); + if (var != nullptr) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypBoolean); +} + +bool rIsNAN(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + bool isnan = false; + + if (var->GetType() == CBotTypFloat) + { + if (std::isnan(var->GetValFloat())) isnan = true; + } + else if (var->GetType() == CBotTypDouble) + { + if (std::isnan(var->GetValDouble())) isnan = true; + } + + result->SetValInt(isnan); + return true; +} + } // namespace void InitMathFunctions() @@ -237,6 +268,7 @@ void InitMathFunctions() CBotProgram::AddFunction("ceil", rCeil, cOneFloat); CBotProgram::AddFunction("round", rRound, cOneFloat); CBotProgram::AddFunction("trunc", rTrunc, cOneFloat); + CBotProgram::AddFunction("isnan", rIsNAN, cIsNAN); } } // namespace CBot diff --git a/src/CBot/stdlib/StringFunctions.cpp b/src/CBot/stdlib/StringFunctions.cpp index c543df7f..a9d61b81 100644 --- a/src/CBot/stdlib/StringFunctions.cpp +++ b/src/CBot/stdlib/StringFunctions.cpp @@ -233,7 +233,7 @@ bool rStrFind( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser ) } else { - pResult->SetInit(CBotVar::InitType::IS_NAN); + pResult->SetValInt(-1); } return true; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 79ec4090..10def122 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -493,6 +493,20 @@ target_link_libraries(colobotbase PUBLIC SndFile::sndfile ) +if(mpg123_FOUND) + target_link_libraries(colobotbase PUBLIC + MPG123::libmpg123 + MPG123::libout123 + MPG123::libsyn123 + ) +endif() + +if(mp3lame_FOUND) + target_link_libraries(colobotbase PUBLIC + mp3lame::mp3lame + ) +endif() + # Optional libraries if(OPENAL_SOUND) target_sources(colobotbase PRIVATE diff --git a/src/app/app.cpp b/src/app/app.cpp index 68f7d68e..948c2b65 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -56,11 +56,12 @@ #include #include -#include #include #include #include +#include + using TimeUtils::TimeStamp; using TimeUtils::TimeUnit; diff --git a/src/common/restext.cpp b/src/common/restext.cpp index 7c5cf830..d23a61d8 100644 --- a/src/common/restext.cpp +++ b/src/common/restext.cpp @@ -31,10 +31,11 @@ #include "object/object_type.h" -#include #include #include +#include + const char* stringsText[RT_MAX] = { nullptr }; const char* stringsEvent[EVENT_STD_MAX] = { nullptr }; const char* stringsObject[OBJECT_MAX] = { nullptr }; diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 5b9b269a..e2ddc726 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -112,6 +112,7 @@ #include #include #include +#include #include #include @@ -4101,70 +4102,64 @@ float SearchNearestObject(CObjectManager* objMan, Math::Vector center, CObject* } return min; } + +bool BlockedByObject(CObjectManager* objMan, Math::Vector center, float space, CObject* exclu) +{ + for (CObject* obj : objMan->GetAllObjects()) + { + if (!obj->GetDetectable()) continue; // inactive? + if (IsObjectBeingTransported(obj)) continue; + + if (obj == exclu) continue; + + for (const auto &crashSphere : obj->GetAllCrashSpheres()) + { + const Math::Vector oPos = crashSphere.sphere.pos; + const float oRadius = crashSphere.sphere.radius; + const float minDist = oRadius + space; + + if (Math::DistanceSquared(center, oPos) < minDist * minDist) + return true; + } + } + return false; +} } //! Calculates a free space bool CRobotMain::FreeSpace(Math::Vector ¢er, float minRadius, float maxRadius, float space, CObject *exclu) { - if (minRadius < maxRadius) // from internal to external? + for (float radius = minRadius; radius <= maxRadius; radius += space) { - for (float radius = minRadius; radius <= maxRadius; radius += space) + float ia = space/radius; + for (float angle = 0.0f; angle < Math::PI*2.0f; angle += ia) { - float ia = space/radius; - for (float angle = 0.0f; angle < Math::PI*2.0f; angle += ia) + Math::Point p; + p.x = center.x+radius; + p.y = center.z; + p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p); + Math::Vector pos; + pos.x = p.x; + pos.z = p.y; + pos.y = 0.0f; + pos.y = m_terrain->GetFloorLevel(pos); + if (!BlockedByObject(m_objMan.get(), pos, space, exclu)) { - Math::Point p; - p.x = center.x+radius; - p.y = center.z; - p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p); - Math::Vector pos; - pos.x = p.x; - pos.z = p.y; - pos.y = 0.0f; - m_terrain->AdjustToFloor(pos, true); - float dist = SearchNearestObject(m_objMan.get(), pos, exclu); - if (dist >= space) + float flat = m_terrain->GetFlatZoneRadius(pos, space); + if (flat >= space) { - float flat = m_terrain->GetFlatZoneRadius(pos, dist/2.0f); - if (flat >= dist/2.0f) - { - center = pos; - return true; - } - } - } - } - } - else // from external to internal? - { - for (float radius=maxRadius; radius >= minRadius; radius -= space) - { - float ia = space/radius; - for (float angle=0.0f ; angleAdjustToFloor(pos, true); - float dist = SearchNearestObject(m_objMan.get(), pos, exclu); - if (dist >= space) - { - float flat = m_terrain->GetFlatZoneRadius(pos, dist/2.0f); - if (flat >= dist/2.0f) - { - center = pos; - return true; - } + center = pos; + return true; } } } } + + float nan = nanf(""); + + center = Math::Vector{ nan, nan, nan }; + return false; } @@ -4930,6 +4925,7 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot) assert(slotNum >= 0); assert(slots.find(slotNum) == slots.end()); asSlotted->SetSlotContainedObject(slotNum, power); + dynamic_cast(*power).SetTransporter(obj); } for (std::pair& slot : slots) @@ -4949,14 +4945,6 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot) assert(cargo == nullptr); } - if (power != nullptr) - { - dynamic_cast(*obj).SetSlotContainedObjectReq(CSlottedObject::Pseudoslot::POWER, power); - dynamic_cast(*power).SetTransporter(obj); - } - cargo = nullptr; - power = nullptr; - objCounter++; } } diff --git a/src/math/half.cpp b/src/math/half.cpp index a205c736..be847c81 100644 --- a/src/math/half.cpp +++ b/src/math/half.cpp @@ -100,7 +100,7 @@ float HaltToFloat(uint16_t value) // NaN else if ((exponent == 31) && (mantissa != 0)) { - result = std::nanf(""); + result = nanf(""); } // Normal number else diff --git a/src/math/vector.h b/src/math/vector.h index e57ccbb6..0af4840b 100644 --- a/src/math/vector.h +++ b/src/math/vector.h @@ -273,6 +273,14 @@ inline float Distance(const Math::Vector &a, const Math::Vector &b) (a.z-b.z)*(a.z-b.z) ); } +//! Returns the squared distance between the ends of two vectors +inline float DistanceSquared(const Math::Vector &a, const Math::Vector &b) +{ + return (a.x-b.x)*(a.x-b.x) + + (a.y-b.y)*(a.y-b.y) + + (a.z-b.z)*(a.z-b.z); +} + //! Clamps the vector \a vec to range between \a min and \a max inline Vector Clamp(const Vector &vec, const Vector &min, const Vector &max) { @@ -285,4 +293,3 @@ inline Vector Clamp(const Vector &vec, const Vector &min, const Vector &max) } // namespace Math - diff --git a/src/script/cbottoken.cpp b/src/script/cbottoken.cpp index 911b985d..d14a7068 100644 --- a/src/script/cbottoken.cpp +++ b/src/script/cbottoken.cpp @@ -301,6 +301,7 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "ceil" ) == 0 ) helpfile = "cbot/ceil"; if ( strcmp(token, "round" ) == 0 ) helpfile = "cbot/round"; if ( strcmp(token, "trunc" ) == 0 ) helpfile = "cbot/trunc"; + if ( strcmp(token, "isnan" ) == 0 ) helpfile = "cbot/isnan"; if ( strcmp(token, "retobject" ) == 0 ) helpfile = "cbot/retobj"; if ( strcmp(token, "errmode" ) == 0 ) helpfile = "cbot/errmode"; if ( strcmp(token, "isbusy" ) == 0 ) helpfile = "cbot/isbusy"; @@ -463,9 +464,10 @@ bool IsFunction(const char *token) if ( strcmp(token, "ceil" ) == 0 ) return true; if ( strcmp(token, "round" ) == 0 ) return true; if ( strcmp(token, "trunc" ) == 0 ) return true; + if ( strcmp(token, "isnan" ) == 0 ) return true; if ( strcmp(token, "retobjectbyid") == 0 ) return true; if ( strcmp(token, "retobject" ) == 0 ) return true; - if ( strcmp(token, "isbusy" ) == 0 ) return true; + if ( strcmp(token, "isbusy" ) == 0 ) return true; if ( strcmp(token, "factory" ) == 0 ) return true; if ( strcmp(token, "research" ) == 0 ) return true; if ( strcmp(token, "takeoff" ) == 0 ) return true; @@ -571,6 +573,7 @@ const char* GetHelpText(const char *token) if ( strcmp(token, "ceil" ) == 0 ) return "ceil ( value );"; if ( strcmp(token, "round" ) == 0 ) return "round ( value );"; if ( strcmp(token, "trunc" ) == 0 ) return "trunc ( value );"; + if ( strcmp(token, "isnan" ) == 0 ) return "isnan ( value );"; if ( strcmp(token, "retobject" ) == 0 ) return "retobject ( rank );"; if ( strcmp(token, "retobjectbyid") == 0 ) return "retobjectbyid ( rank );"; if ( strcmp(token, "progfunc" ) == 0 ) return "progfunc ( funcname );"; diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index f36121f7..e9cd4d40 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -67,6 +67,8 @@ #include "ui/displaytext.h" +#include + using namespace CBot; CBotTypResult CScriptFunctions::cClassNull(CBotVar* thisclass, CBotVar* &var) @@ -1836,18 +1838,30 @@ bool CScriptFunctions::rSpace(CBotVar* var, CBotVar* result, int& exception, voi } } } - script->m_main->FreeSpace(center, rMin, rMax, dist, pThis); + + bool success = script->m_main->FreeSpace(center, rMin, rMax, dist, pThis); if ( result != nullptr ) { pSub = result->GetItemList(); if ( pSub != nullptr ) { - pSub->SetValFloat(center.x/g_unit); - pSub = pSub->GetNext(); // "y" - pSub->SetValFloat(center.z/g_unit); - pSub = pSub->GetNext(); // "z" - pSub->SetValFloat(center.y/g_unit); + if (success) + { + pSub->SetValFloat(center.x / g_unit); + pSub = pSub->GetNext(); // "y" + pSub->SetValFloat(center.z / g_unit); + pSub = pSub->GetNext(); // "z" + pSub->SetValFloat(center.y / g_unit); + } + else + { + pSub->SetValFloat(center.x); + pSub = pSub->GetNext(); // "y" + pSub->SetValFloat(center.y); + pSub = pSub->GetNext(); // "z" + pSub->SetValFloat(center.z); + } } } return true; @@ -2313,7 +2327,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v if ( err != ERR_OK ) { script->m_taskExecutor->StopForegroundTask(); - result->SetInit(CBotVar::InitType::IS_NAN); + result->SetValFloat(nanf("")); return true; } @@ -2324,7 +2338,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v if ( script->m_returnValue == boost::none ) { - result->SetInit(CBotVar::InitType::IS_NAN); + result->SetValFloat(nanf("")); } else { @@ -2859,6 +2873,7 @@ CBotTypResult CScriptFunctions::cMessage(CBotVar* &var, void* user) { if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var->GetType() != CBotTypString && + var->GetType() != CBotTypBoolean && var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); var = var->GetNext(); @@ -3644,11 +3659,11 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user) if (IsObjectBeingTransported(object)) { pSub = pVar->GetItemList(); // "x" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(nanf("")); pSub = pSub->GetNext(); // "y" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(nanf("")); pSub = pSub->GetNext(); // "z" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(nanf("")); } else { @@ -3749,11 +3764,11 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user) if (IsObjectBeingTransported(object) || physics == nullptr) { pSub = pVar->GetItemList(); // "x" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(nanf("")); pSub = pSub->GetNext(); // "y" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(nanf("")); pSub = pSub->GetNext(); // "z" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(nanf("")); } else {