1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

ERM VR:M,VR:U

This commit is contained in:
Andrii Danylchenko 2021-04-19 18:28:55 +03:00
parent 35566d7748
commit 061941b3ac
7 changed files with 167 additions and 30 deletions

View File

@ -13,7 +13,7 @@
class CArmedInstance; 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: protected:
fl::Engine engine; fl::Engine engine;
@ -24,7 +24,7 @@ public:
engineBase(); 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: public:
TacticalAdvantageEngine(); TacticalAdvantageEngine();
@ -37,7 +37,7 @@ private:
fl::OutputVariable * threat; 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: public:
HeroMovementGoalEngineBase(); HeroMovementGoalEngineBase();
@ -55,14 +55,14 @@ private:
float calculateTurnDistanceInputValue(const Goals::AbstractGoal & goal) const; float calculateTurnDistanceInputValue(const Goals::AbstractGoal & goal) const;
}; };
class VisitTileEngine : public HeroMovementGoalEngineBase class DLL_EXPORT VisitTileEngine : public HeroMovementGoalEngineBase
{ {
public: public:
VisitTileEngine(); VisitTileEngine();
float evaluate(Goals::VisitTile & goal); float evaluate(Goals::VisitTile & goal);
}; };
class VisitObjEngine : public HeroMovementGoalEngineBase class DLL_EXPORT VisitObjEngine : public HeroMovementGoalEngineBase
{ {
public: public:
VisitObjEngine(); VisitObjEngine();

View File

@ -774,10 +774,48 @@ namespace ERMConverter
putLine(fmt.str()); putLine(fmt.str());
} }
break; 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 case 'M': //string operations
{ {
//TODO if(!trig.params.is_initialized() || trig.params.get().size() < 2)
putLine("--VR:M not implemented"); 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; break;
case 'X': //bit xor case 'X': //bit xor
@ -788,8 +826,7 @@ namespace ERMConverter
std::string opt = boost::apply_visitor(VR_X(), trig.params.get()[0]); std::string opt = boost::apply_visitor(VR_X(), trig.params.get()[0]);
boost::format fmt("%s = bit.bxor(%s, %s)"); boost::format fmt("%s = bit.bxor(%s, %s)");
fmt % v.str() % v.str() % opt; fmt % v.str() % v.str() % opt;putLine(fmt.str());
putLine(fmt.str());
} }
break; break;
case 'R': //random variables case 'R': //random variables
@ -816,16 +853,15 @@ namespace ERMConverter
putLine("--VR:T not implemented"); putLine("--VR:T not implemented");
} }
break; break;
case 'U': //search for a substring
{
//TODO
putLine("--VR:U not implemented");
}
break;
case 'V': //convert string to value case 'V': //convert string to value
{ {
//TODO if(!trig.params.is_initialized() || trig.params.get().size() != 1)
putLine("--VR:V not implemented"); 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; break;
default: default:

View File

@ -2,7 +2,7 @@
#include "../../Global.h" #include "../../Global.h"
#include <lua.hpp> #include <luajit/lua.hpp>
// This header should be treated as a pre compiled header file(PCH) in the compiler building settings. // This header should be treated as a pre compiled header file(PCH) in the compiler building settings.

View File

@ -18,5 +18,61 @@ function VR:H(flagIndex)
self.ERM.F[flagIndex] = v ~= '' self.ERM.F[flagIndex] = v ~= ''
end 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 return VR

View File

@ -153,11 +153,30 @@ set(mock_HEADERS
vcai/mock_VCAI_CGoal.h 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_subdirectory_with_folder("3rdparty" googletest EXCLUDE_FROM_ALL)
add_executable(vcmitest ${test_SRCS} ${test_HEADERS} ${mock_HEADERS}) add_executable(vcmitest ${test_SRCS} ${test_HEADERS} ${mock_HEADERS})
target_link_libraries(vcmitest PRIVATE gtest gmock vcmi ${SYSTEM_LIBS} VCAI) 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 target_include_directories(vcmitest
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${GTestSrc} PRIVATE ${GTestSrc}

View File

@ -73,6 +73,24 @@ TEST_F(ERM_VR, H)
EXPECT_EQ(f["202"], JsonUtils::boolNode(false)) << actualState.toJson(true); 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);
}
} }
} }

View File

@ -73,13 +73,21 @@ TEST(ERM_VR_H, CheckEmptyString_ShouldGenerateCheckAndSetStatement)
ASSERT_EQ(lua.lines.size(), 9) << lua.text; ASSERT_EQ(lua.lines.size(), 9) << lua.text;
EXPECT_EQ(lua.lines[ErmRunner::REGULAR_INSTRUCTION_FIRST_LINE], "ERM.VR(z['101']):H('302')"); 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) TEST(ERM_VR_M1, AnyString_ShouldGenerateSubstringAndSetStatement)
{ {
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/2/5;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/2/5;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) 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;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M1/z102/y1/y2;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) TEST(ERM_VR_M2, AnyString_ShouldGenerateWordSplitAndSetStatement)
@ -95,7 +103,7 @@ TEST(ERM_VR_M2, AnyString_ShouldGenerateWordSplitAndSetStatement)
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M2/z102/2;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M2/z102/2;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) TEST(ERM_VR_M3, AnyInteger_ShouldGenerateIntToStringConversionAndSetStatement)
@ -103,7 +111,7 @@ TEST(ERM_VR_M3, AnyInteger_ShouldGenerateIntToStringConversionAndSetStatement)
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/102/16;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/102/16;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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 //V
TEST(ERM_VR_M3, IntegerVariable_ShouldGenerateIntToStringConversionAndSetStatement) TEST(ERM_VR_M3, IntegerVariable_ShouldGenerateIntToStringConversionAndSetStatement)
@ -111,7 +119,7 @@ TEST(ERM_VR_M3, IntegerVariable_ShouldGenerateIntToStringConversionAndSetStateme
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/v1/10;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M3/v1/10;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) TEST(ERM_VR_M4, AnyString_ShouldGenerateStringLengthAndSetStatement)
@ -119,7 +127,7 @@ TEST(ERM_VR_M4, AnyString_ShouldGenerateStringLengthAndSetStatement)
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M4/v2;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M4/v2;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) TEST(ERM_VR_M5, AnyString_ShouldGenerateFindFirstNonSpaceCharPositionAndSetStatement)
@ -127,7 +135,7 @@ TEST(ERM_VR_M5, AnyString_ShouldGenerateFindFirstNonSpaceCharPositionAndSetState
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M5/v2;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M5/v2;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) TEST(ERM_VR_M6, AnyString_ShouldGenerateFindLastNonSpaceCharPositionAndSetStatement)
@ -135,7 +143,7 @@ TEST(ERM_VR_M6, AnyString_ShouldGenerateFindLastNonSpaceCharPositionAndSetStatem
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M6/v2;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz101:M6/v2;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) TEST(ERM_VR_R, AnyVariable_ShouldGenerateRngAndSetStatement)
@ -174,8 +182,8 @@ TEST(ERM_VR_U, StringVariable_ShouldGenerateSubstringFindAndSetStatement)
{ {
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:Uz3;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:Uz3;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; ASSERT_EQ(lua.lines.size(), 9) << lua.lines[0];
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(z['3'])");
} }
TEST(ERM_VR_U, StringConstant_ShouldGenerateSubstringFindAndSetStatement) TEST(ERM_VR_U, StringConstant_ShouldGenerateSubstringFindAndSetStatement)
@ -183,7 +191,7 @@ TEST(ERM_VR_U, StringConstant_ShouldGenerateSubstringFindAndSetStatement)
LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:U^teest^;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRz2:U^teest^;"});
ASSERT_EQ(lua.lines.size(), 9) << lua.text; 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) 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']"); 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;"}); LuaStrings lua = ErmRunner::convertErmToLua({"!#VRv1:*vy2;"});