From 35566d774872d31dd6f10768ca859ad62d6b162e Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Fri, 9 Apr 2021 23:41:50 +0300 Subject: [PATCH 1/3] ERM: fix string concatenations and bit operations --- scripting/erm/ERMInterpreter.cpp | 35 +++++- scripting/erm/ERMParser.cpp | 3 +- test/erm/interpretter/ERM_VR.cpp | 210 ++++++++++++++++++++++++++++++- 3 files changed, 237 insertions(+), 11 deletions(-) diff --git a/scripting/erm/ERMInterpreter.cpp b/scripting/erm/ERMInterpreter.cpp index 4d0cfb25c..a1cf90bc8 100644 --- a/scripting/erm/ERMInterpreter.cpp +++ b/scripting/erm/ERMInterpreter.cpp @@ -651,6 +651,22 @@ namespace ERMConverter } }; + struct VR_X : public GetBodyOption + { + VR_X() + { + } + + using GetBodyOption::operator(); + + std::string operator()(const TIexp & cmp) const override + { + Variable p = boost::apply_visitor(LVL1IexpToVar(), cmp); + + return p.str(); + } + }; + struct VR : public Receiver { Variable v; @@ -677,15 +693,12 @@ namespace ERMConverter case '|': opcode = "bit.bor"; break; - case 'X': - opcode = "bit.bxor"; - break; default: throw EInterpreterError("Wrong opcode in VR logic expression!"); break; } - boost::format fmt("%s = %s %s(%s, %s)"); + boost::format fmt("%s = %s(%s, %s)"); fmt % v.str() % opcode % v.str() % rhs.str(); putLine(fmt.str()); } @@ -699,6 +712,8 @@ namespace ERMConverter switch (trig.opcode) { case '+': + opcode = v.name[0] == 'z' ? ".." : "+"; + break; case '-': case '*': case '%': @@ -765,6 +780,18 @@ namespace ERMConverter putLine("--VR:M not implemented"); } break; + case 'X': //bit xor + { + if(!trig.params.is_initialized() || trig.params.get().size() != 1) + throw EScriptExecError("VR:X option takes exactly 1 parameter!"); + + std::string opt = boost::apply_visitor(VR_X(), trig.params.get()[0]); + + boost::format fmt("%s = bit.bxor(%s, %s)"); + fmt % v.str() % v.str() % opt; + putLine(fmt.str()); + } + break; case 'R': //random variables { //TODO diff --git a/scripting/erm/ERMParser.cpp b/scripting/erm/ERMParser.cpp index 294d2066d..cfbd8a705 100644 --- a/scripting/erm/ERMParser.cpp +++ b/scripting/erm/ERMParser.cpp @@ -367,8 +367,7 @@ namespace ERM trigger %= cmdName >> -identifier >> -condition > qi::lit(";"); ///// string %= qi::lexeme['^' >> *(qi::char_ - '^') >> '^']; -// VRLogic %= qi::char_("&|X") >> iexp; - VRLogic %= qi::char_("&") >> iexp; + VRLogic %= qi::char_("&|") >> iexp; VRarithmetic %= qi::char_("+*:/%-") >> iexp; semiCompare %= +qi::char_("<=>") >> iexp; curStr %= iexp >> string; diff --git a/test/erm/interpretter/ERM_VR.cpp b/test/erm/interpretter/ERM_VR.cpp index a8fabca93..7841d860d 100644 --- a/test/erm/interpretter/ERM_VR.cpp +++ b/test/erm/interpretter/ERM_VR.cpp @@ -60,12 +60,212 @@ TEST(ERM_VR_C, SetIntegers_ShouldGenerateSetStatements) TEST(ERM_VR_C, GetInteger_ShouldGenerateSetStatement) { - LuaStrings lua = ErmRunner::convertErmToLua({ - "!#VRv100:C10/20/40;", - "!#VRv100:C?v1;"}); + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv100:C?v1;"}); - ASSERT_EQ(lua.lines.size(), 12) << lua.text; - EXPECT_EQ(lua.lines[8], "v['1'] = v['100']"); + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['100']"); +} + +TEST(ERM_VR_H, CheckEmptyString_ShouldGenerateCheckAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:H302;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "ERM.VR(z['101']):H('302')"); +} + +TEST(ERM_VR_M1, AnyString_ShouldGenerateSubstringAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/2/5;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_M1, WithVariables_ShouldGenerateSubstringAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/y1/y2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_M2, AnyString_ShouldGenerateWordSplitAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M2/z102/2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_M3, AnyInteger_ShouldGenerateIntToStringConversionAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/102/16;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} +//V +TEST(ERM_VR_M3, IntegerVariable_ShouldGenerateIntToStringConversionAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/v1/10;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_M4, AnyString_ShouldGenerateStringLengthAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M4/v2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_M5, AnyString_ShouldGenerateFindFirstNonSpaceCharPositionAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M5/v2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_M6, AnyString_ShouldGenerateFindLastNonSpaceCharPositionAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M6/v2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); +} + +TEST(ERM_VR_R, AnyVariable_ShouldGenerateRngAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:R23;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:R not implemented"); +} + +TEST(ERM_VR_S_R, AnyVariable_ShouldGenerateRngAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:R23;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:R not implemented"); +} + +TEST(ERM_VR_S, DynamicVariable_ShouldGenerateDynamicSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:Svy3;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v[tostring(y['3'])]"); +} + +TEST(ERM_VR_T, AnyVariable_ShouldGenerateTimeBasedRngAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:T23;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:T not implemented"); +} + +TEST(ERM_VR_U, StringVariable_ShouldGenerateSubstringFindAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:Uz3;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:U not implemented"); +} + +TEST(ERM_VR_U, StringConstant_ShouldGenerateSubstringFindAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:U^teest^;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:U not implemented"); +} + +TEST(ERM_VR_BIT, LogicalAndOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:&8;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = bit.band(v['1'], 8)"); +} + +TEST(ERM_VR_BITOR, LogicalOrOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:|8;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = bit.bor(v['1'], 8)"); +} + +TEST(ERM_VR_BITXOR, LogicalXorOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:Xv2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = bit.bxor(v['1'], v['2'])"); +} + +TEST(ERM_VR_PLUS, PlusOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:+8;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['1'] + 8"); +} + +TEST(ERM_VR_PLUS, ConcatenationOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz1:+z3;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "z['1'] = z['1'] .. z['3']"); +} + +TEST(ERM_VR_MINUS, MinusOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:-v2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['1'] - v['2']"); +} + +TEST(ERM_VR_MULT, NultiplicationOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:*vy2;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['1'] * v[tostring(y['2'])]"); +} + +TEST(ERM_VR_DIV, DivisionOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1::8;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['1'] / 8"); +} + +TEST(ERM_VR_MOD, ModOperator_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:%7;"}); + + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['1'] % 7"); +} + +TEST(ERM_VR_MINUS, Composition_ShouldGenerateSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:S100 -v2 *v3;"}); + + ASSERT_EQ(lua.lines.size(), 11) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = 100"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE + 1], "v['1'] = v['1'] - v['2']"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE + 2], "v['1'] = v['1'] * v['3']"); } } From 061941b3acf094a4f40cf07e59ab31893eccdf20 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Mon, 19 Apr 2021 18:28:55 +0300 Subject: [PATCH 2/3] ERM VR:M,VR:U --- AI/VCAI/FuzzyEngines.h | 10 +++--- scripting/erm/ERMInterpreter.cpp | 60 +++++++++++++++++++++++++------- scripting/lua/StdInc.h | 2 +- scripts/lib/erm/VR.lua | 56 +++++++++++++++++++++++++++++ test/CMakeLists.txt | 19 ++++++++++ test/erm/ERM_VR.cpp | 18 ++++++++++ test/erm/interpretter/ERM_VR.cpp | 32 ++++++++++------- 7 files changed, 167 insertions(+), 30 deletions(-) diff --git a/AI/VCAI/FuzzyEngines.h b/AI/VCAI/FuzzyEngines.h index 95a58c482..483d0e06c 100644 --- a/AI/VCAI/FuzzyEngines.h +++ b/AI/VCAI/FuzzyEngines.h @@ -13,7 +13,7 @@ class CArmedInstance; -class engineBase //subclasses create fuzzylite variables with "new" that are not freed - this is desired as fl::Engine wants to destroy these... +class DLL_EXPORT engineBase //subclasses create fuzzylite variables with "new" that are not freed - this is desired as fl::Engine wants to destroy these... { protected: fl::Engine engine; @@ -24,7 +24,7 @@ public: engineBase(); }; -class TacticalAdvantageEngine : public engineBase //TODO: rework this engine, it does not work well (example: AI hero with 140 beholders attacked 150 beholders - engine lowered danger 50000 -> 35000) +class DLL_EXPORT TacticalAdvantageEngine : public engineBase //TODO: rework this engine, it does not work well (example: AI hero with 140 beholders attacked 150 beholders - engine lowered danger 50000 -> 35000) { public: TacticalAdvantageEngine(); @@ -37,7 +37,7 @@ private: fl::OutputVariable * threat; }; -class HeroMovementGoalEngineBase : public engineBase //in future - maybe derive from some (GoalEngineBase : public engineBase) class for handling non-movement goals with common utility for goal engines +class DLL_EXPORT HeroMovementGoalEngineBase : public engineBase //in future - maybe derive from some (GoalEngineBase : public engineBase) class for handling non-movement goals with common utility for goal engines { public: HeroMovementGoalEngineBase(); @@ -55,14 +55,14 @@ private: float calculateTurnDistanceInputValue(const Goals::AbstractGoal & goal) const; }; -class VisitTileEngine : public HeroMovementGoalEngineBase +class DLL_EXPORT VisitTileEngine : public HeroMovementGoalEngineBase { public: VisitTileEngine(); float evaluate(Goals::VisitTile & goal); }; -class VisitObjEngine : public HeroMovementGoalEngineBase +class DLL_EXPORT VisitObjEngine : public HeroMovementGoalEngineBase { public: VisitObjEngine(); diff --git a/scripting/erm/ERMInterpreter.cpp b/scripting/erm/ERMInterpreter.cpp index a1cf90bc8..340bcc80d 100644 --- a/scripting/erm/ERMInterpreter.cpp +++ b/scripting/erm/ERMInterpreter.cpp @@ -774,10 +774,48 @@ namespace ERMConverter putLine(fmt.str()); } break; + case 'U': + { + if(!trig.params.is_initialized() || trig.params.get().size() != 1) + throw EScriptExecError("VR:H/U need 1 parameter!"); + + std::string opt = boost::apply_visitor(VR_S(), trig.params.get()[0]); + boost::format fmt("ERM.VR(%s):%c(%s)"); + fmt % v.str() % (trig.optionCode) % opt; + putLine(fmt.str()); + } + break; case 'M': //string operations { - //TODO - putLine("--VR:M not implemented"); + if(!trig.params.is_initialized() || trig.params.get().size() < 2) + throw EScriptExecError("VR:M needs at least 2 parameters!"); + + std::string opt = boost::apply_visitor(VR_X(), trig.params.get()[0]); + int paramIndex = 1; + + if(opt == "3") + { + boost::format fmt("%s = ERM.VR(%s):M3("); + fmt % v.str() % v.str(); + put(fmt.str()); + } + else + { + auto target = boost::apply_visitor(VR_X(), trig.params.get()[paramIndex++]); + + boost::format fmt("%s = ERM.VR(%s):M%s("); + fmt % target % v.str() % opt; + put(fmt.str()); + } + + for(int i = paramIndex; i < trig.params.get().size(); i++) + { + opt = boost::apply_visitor(VR_X(), trig.params.get()[i]); + if(i > paramIndex) put(","); + put(opt); + } + + putLine(")"); } break; case 'X': //bit xor @@ -788,8 +826,7 @@ namespace ERMConverter std::string opt = boost::apply_visitor(VR_X(), trig.params.get()[0]); boost::format fmt("%s = bit.bxor(%s, %s)"); - fmt % v.str() % v.str() % opt; - putLine(fmt.str()); + fmt % v.str() % v.str() % opt;putLine(fmt.str()); } break; case 'R': //random variables @@ -816,16 +853,15 @@ namespace ERMConverter putLine("--VR:T not implemented"); } break; - case 'U': //search for a substring - { - //TODO - putLine("--VR:U not implemented"); - } - break; case 'V': //convert string to value { - //TODO - putLine("--VR:V not implemented"); + if(!trig.params.is_initialized() || trig.params.get().size() != 1) + throw EScriptExecError("VR:V option takes exactly 1 parameter!"); + + std::string opt = boost::apply_visitor(VR_X(), trig.params.get()[0]); + boost::format fmt("%s = tostring(%s)"); + fmt % v.str() % opt; + putLine(fmt.str()); } break; default: diff --git a/scripting/lua/StdInc.h b/scripting/lua/StdInc.h index 6d4d7523d..494217b40 100644 --- a/scripting/lua/StdInc.h +++ b/scripting/lua/StdInc.h @@ -2,7 +2,7 @@ #include "../../Global.h" -#include +#include // This header should be treated as a pre compiled header file(PCH) in the compiler building settings. diff --git a/scripts/lib/erm/VR.lua b/scripts/lib/erm/VR.lua index 8ed5ca7d2..dfe7d1f38 100644 --- a/scripts/lib/erm/VR.lua +++ b/scripts/lib/erm/VR.lua @@ -18,5 +18,61 @@ function VR:H(flagIndex) self.ERM.F[flagIndex] = v ~= '' end +function VR:U(subString) + self.ERM.F['1'] = string.find(self.v, subString) > 0 +end + +function VR:M1(startIndex, length) + return string.sub(self.v, startIndex - 1, startIndex - 1 + length) +end + +function VR:M2(wordIndex) + local words = string.gmatch(self.v, "[^%s]+") + local i = 0 + + for w in words do + if i == wordIndex then + return w + end + i = i + 1 + end +end + +function VR:M3(val, radix) + radix = radix or 10 + + if(type(val) ~= "number") then + error("The first parameter should be of numeric type") + end + + if(type(radix) ~= "number") then + error("The second parameter should be of numeric type. Default value is 10.") + end + + if radix == 10 then + return tostring(val) + elseif radix == 16 then + return string.format("%x", val) + else + error("The second parameter value is invalid. Only 10 and 16 radix are supported for now.") + end +end + +function VR:M4() + return string.len(self.v) +end + +function VR:M5() + local firstPos = string.find(str, "[^%s]+") + + return firstPos +end + +function VR:M6() + local lastPos = 1 + string.len(self.v) - string.find(string.reverse(self.v), "[^%s]+") + + return lastPos +end + return VR diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7d3a4c18d..c5e3b9af3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -153,11 +153,30 @@ set(mock_HEADERS vcai/mock_VCAI_CGoal.h ) +if(NOT FORCE_BUNDLED_FL) + find_package(FuzzyLite) +else() + set(FL_FOUND FALSE) +endif() + +if(NOT FL_FOUND) + set(FL_BUILD_BINARY OFF CACHE BOOL "") + set(FL_BUILD_SHARED OFF CACHE BOOL "") + set(FL_BUILD_TESTS OFF CACHE BOOL "") + add_subdirectory(AI/FuzzyLite/fuzzylite EXCLUDE_FROM_ALL) +endif() + add_subdirectory_with_folder("3rdparty" googletest EXCLUDE_FROM_ALL) add_executable(vcmitest ${test_SRCS} ${test_HEADERS} ${mock_HEADERS}) target_link_libraries(vcmitest PRIVATE gtest gmock vcmi ${SYSTEM_LIBS} VCAI) +if(FL_FOUND) + target_link_libraries(vcmitest PRIVATE ${FL_LIBRARIES}) +else() + target_link_libraries(vcmitest PRIVATE fl-static) +endif() + target_include_directories(vcmitest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${GTestSrc} diff --git a/test/erm/ERM_VR.cpp b/test/erm/ERM_VR.cpp index 6a230c4a2..f61223cbf 100644 --- a/test/erm/ERM_VR.cpp +++ b/test/erm/ERM_VR.cpp @@ -73,6 +73,24 @@ TEST_F(ERM_VR, H) EXPECT_EQ(f["202"], JsonUtils::boolNode(false)) << actualState.toJson(true); } +TEST_F(ERM_VR, U) +{ + std::stringstream source; + source << "VERM" << std::endl; + source << "!?PI;" << std::endl; + source << "!!VRz100:S^Test!^;" << std::endl; + source << "!!VRz101:S^est^;" << std::endl; + source << "!!VRz100:Uz101;" << std::endl; + + JsonNode actualState = runScript(VLC->scriptHandler->erm, source.str()); + + SCOPED_TRACE("\n" + subject->code); + + const JsonNode & f = actualState["ERM"]["F"]; + + EXPECT_EQ(f["1"], JsonUtils::boolNode(true)) << actualState.toJson(true); +} + } } diff --git a/test/erm/interpretter/ERM_VR.cpp b/test/erm/interpretter/ERM_VR.cpp index 7841d860d..900c0cf2c 100644 --- a/test/erm/interpretter/ERM_VR.cpp +++ b/test/erm/interpretter/ERM_VR.cpp @@ -73,13 +73,21 @@ TEST(ERM_VR_H, CheckEmptyString_ShouldGenerateCheckAndSetStatement) ASSERT_EQ(lua.lines.size(), 9) << lua.text; EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "ERM.VR(z['101']):H('302')"); } +/* should it work? +TEST(ERM_VR_H, CheckEmptyStringWithFlagIndexInVariable_ShouldGenerateCheckAndSetStatement) +{ + LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:Hy1;"}); + ASSERT_EQ(lua.lines.size(), 9) << lua.text; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "ERM.VR(z['101']):H(y['1'])"); +} +*/ TEST(ERM_VR_M1, AnyString_ShouldGenerateSubstringAndSetStatement) { LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/2/5;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "z['102'] = ERM.VR(z['101']):M1(2,5)"); } TEST(ERM_VR_M1, WithVariables_ShouldGenerateSubstringAndSetStatement) @@ -87,7 +95,7 @@ TEST(ERM_VR_M1, WithVariables_ShouldGenerateSubstringAndSetStatement) LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/y1/y2;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "z['102'] = ERM.VR(z['101']):M1(y['1'],y['2'])"); } TEST(ERM_VR_M2, AnyString_ShouldGenerateWordSplitAndSetStatement) @@ -95,7 +103,7 @@ TEST(ERM_VR_M2, AnyString_ShouldGenerateWordSplitAndSetStatement) LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M2/z102/2;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "z['102'] = ERM.VR(z['101']):M2(2)"); } TEST(ERM_VR_M3, AnyInteger_ShouldGenerateIntToStringConversionAndSetStatement) @@ -103,7 +111,7 @@ TEST(ERM_VR_M3, AnyInteger_ShouldGenerateIntToStringConversionAndSetStatement) LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/102/16;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "z['101'] = ERM.VR(z['101']):M3(102,16)"); } //V TEST(ERM_VR_M3, IntegerVariable_ShouldGenerateIntToStringConversionAndSetStatement) @@ -111,7 +119,7 @@ TEST(ERM_VR_M3, IntegerVariable_ShouldGenerateIntToStringConversionAndSetStateme LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/v1/10;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "z['101'] = ERM.VR(z['101']):M3(v['1'],10)"); } TEST(ERM_VR_M4, AnyString_ShouldGenerateStringLengthAndSetStatement) @@ -119,7 +127,7 @@ TEST(ERM_VR_M4, AnyString_ShouldGenerateStringLengthAndSetStatement) LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M4/v2;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['2'] = ERM.VR(z['101']):M4()"); } TEST(ERM_VR_M5, AnyString_ShouldGenerateFindFirstNonSpaceCharPositionAndSetStatement) @@ -127,7 +135,7 @@ TEST(ERM_VR_M5, AnyString_ShouldGenerateFindFirstNonSpaceCharPositionAndSetState LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M5/v2;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['2'] = ERM.VR(z['101']):M5()"); } TEST(ERM_VR_M6, AnyString_ShouldGenerateFindLastNonSpaceCharPositionAndSetStatement) @@ -135,7 +143,7 @@ TEST(ERM_VR_M6, AnyString_ShouldGenerateFindLastNonSpaceCharPositionAndSetStatem LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M6/v2;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:M not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['2'] = ERM.VR(z['101']):M6()"); } TEST(ERM_VR_R, AnyVariable_ShouldGenerateRngAndSetStatement) @@ -174,8 +182,8 @@ TEST(ERM_VR_U, StringVariable_ShouldGenerateSubstringFindAndSetStatement) { LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:Uz3;"}); - ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:U not implemented"); + ASSERT_EQ(lua.lines.size(), 9) << lua.lines[0]; + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "ERM.VR(z['2']):U(z['3'])"); } TEST(ERM_VR_U, StringConstant_ShouldGenerateSubstringFindAndSetStatement) @@ -183,7 +191,7 @@ TEST(ERM_VR_U, StringConstant_ShouldGenerateSubstringFindAndSetStatement) LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:U^teest^;"}); ASSERT_EQ(lua.lines.size(), 9) << lua.text; - EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "--VR:U not implemented"); + EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "ERM.VR(z['2']):U([===[teest]===])"); } TEST(ERM_VR_BIT, LogicalAndOperator_ShouldGenerateSetStatement) @@ -234,7 +242,7 @@ TEST(ERM_VR_MINUS, MinusOperator_ShouldGenerateSetStatement) EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "v['1'] = v['1'] - v['2']"); } -TEST(ERM_VR_MULT, NultiplicationOperator_ShouldGenerateSetStatement) +TEST(ERM_VR_MULT, MultiplicationOperator_ShouldGenerateSetStatement) { LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:*vy2;"}); From fc9bbfb8950060b63517f38a50b19c895028bec3 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Mon, 19 Apr 2021 18:33:07 +0300 Subject: [PATCH 3/3] ERM: revert unwanted changes --- AI/VCAI/FuzzyEngines.h | 10 +++++----- scripting/lua/StdInc.h | 2 +- test/CMakeLists.txt | 19 ------------------- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/AI/VCAI/FuzzyEngines.h b/AI/VCAI/FuzzyEngines.h index 483d0e06c..95a58c482 100644 --- a/AI/VCAI/FuzzyEngines.h +++ b/AI/VCAI/FuzzyEngines.h @@ -13,7 +13,7 @@ class CArmedInstance; -class DLL_EXPORT engineBase //subclasses create fuzzylite variables with "new" that are not freed - this is desired as fl::Engine wants to destroy these... +class engineBase //subclasses create fuzzylite variables with "new" that are not freed - this is desired as fl::Engine wants to destroy these... { protected: fl::Engine engine; @@ -24,7 +24,7 @@ public: engineBase(); }; -class DLL_EXPORT TacticalAdvantageEngine : public engineBase //TODO: rework this engine, it does not work well (example: AI hero with 140 beholders attacked 150 beholders - engine lowered danger 50000 -> 35000) +class TacticalAdvantageEngine : public engineBase //TODO: rework this engine, it does not work well (example: AI hero with 140 beholders attacked 150 beholders - engine lowered danger 50000 -> 35000) { public: TacticalAdvantageEngine(); @@ -37,7 +37,7 @@ private: fl::OutputVariable * threat; }; -class DLL_EXPORT HeroMovementGoalEngineBase : public engineBase //in future - maybe derive from some (GoalEngineBase : public engineBase) class for handling non-movement goals with common utility for goal engines +class HeroMovementGoalEngineBase : public engineBase //in future - maybe derive from some (GoalEngineBase : public engineBase) class for handling non-movement goals with common utility for goal engines { public: HeroMovementGoalEngineBase(); @@ -55,14 +55,14 @@ private: float calculateTurnDistanceInputValue(const Goals::AbstractGoal & goal) const; }; -class DLL_EXPORT VisitTileEngine : public HeroMovementGoalEngineBase +class VisitTileEngine : public HeroMovementGoalEngineBase { public: VisitTileEngine(); float evaluate(Goals::VisitTile & goal); }; -class DLL_EXPORT VisitObjEngine : public HeroMovementGoalEngineBase +class VisitObjEngine : public HeroMovementGoalEngineBase { public: VisitObjEngine(); diff --git a/scripting/lua/StdInc.h b/scripting/lua/StdInc.h index 494217b40..6d4d7523d 100644 --- a/scripting/lua/StdInc.h +++ b/scripting/lua/StdInc.h @@ -2,7 +2,7 @@ #include "../../Global.h" -#include +#include // This header should be treated as a pre compiled header file(PCH) in the compiler building settings. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c5e3b9af3..7d3a4c18d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -153,30 +153,11 @@ set(mock_HEADERS vcai/mock_VCAI_CGoal.h ) -if(NOT FORCE_BUNDLED_FL) - find_package(FuzzyLite) -else() - set(FL_FOUND FALSE) -endif() - -if(NOT FL_FOUND) - set(FL_BUILD_BINARY OFF CACHE BOOL "") - set(FL_BUILD_SHARED OFF CACHE BOOL "") - set(FL_BUILD_TESTS OFF CACHE BOOL "") - add_subdirectory(AI/FuzzyLite/fuzzylite EXCLUDE_FROM_ALL) -endif() - add_subdirectory_with_folder("3rdparty" googletest EXCLUDE_FROM_ALL) add_executable(vcmitest ${test_SRCS} ${test_HEADERS} ${mock_HEADERS}) target_link_libraries(vcmitest PRIVATE gtest gmock vcmi ${SYSTEM_LIBS} VCAI) -if(FL_FOUND) - target_link_libraries(vcmitest PRIVATE ${FL_LIBRARIES}) -else() - target_link_libraries(vcmitest PRIVATE fl-static) -endif() - target_include_directories(vcmitest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${GTestSrc}