Added missing logic variables and REGISTER_FUNCTION_WITH_DEFAULTS.

This commit is contained in:
xxAtrain223 2025-07-19 13:02:39 -05:00
commit 3e8b45165d
5 changed files with 86 additions and 30 deletions

View file

@ -909,38 +909,48 @@ void RegionTable_Init() {
}
}
#if 0 // Print all conditions for debugging
#if 1 // Print all conditions for debugging
// RANDOTODO: Remove before merging
std::ostringstream ss;
if (Rando::Context::GetInstance()->GetLogic()->mSaveContext != nullptr) {
std::function<void(std::shared_ptr<LogicExpression>)> eval;
eval = [&eval](std::shared_ptr<LogicExpression> expression) {
expression->Evaluate<bool>();
for (auto& child : expression->GetChildren()) {
eval(child);
}
};
for (uint32_t i = RR_ROOT; i <= RR_GANONS_CASTLE; i++) {
for (EventAccess& eventAccess : areaTable[i].events) {
try {
LogicExpression::Parse(eventAccess.GetConditionStr());
std::ostringstream ss;
for (uint32_t i = RR_ROOT; i <= RR_GANONS_CASTLE; i++) {
for (EventAccess& eventAccess : areaTable[i].events) {
try {
eval(LogicExpression::Parse(eventAccess.GetConditionStr()));
} catch (std::exception& ex) {
ss << eventAccess.GetConditionStr() << std::endl;
ss << ex.what() << std::endl << std::endl;
}
}
catch (std::exception& ex) {
ss << eventAccess.GetConditionStr() << std::endl;
}
}
for (LocationAccess& locPair : areaTable[i].locations) {
try {
LogicExpression::Parse(locPair.GetConditionStr());
}
catch (std::exception& ex) {
ss << locPair.GetConditionStr() << std::endl;
}
}
for (Entrance& exit : areaTable[i].exits) {
try {
LogicExpression::Parse(exit.GetConditionStr());
}
catch (std::exception& ex) {
ss << exit.GetConditionStr() << std::endl;
for (LocationAccess& locPair : areaTable[i].locations) {
try {
eval(LogicExpression::Parse(locPair.GetConditionStr()));
} catch (std::exception& ex) {
ss << locPair.GetConditionStr() << std::endl;
ss << ex.what() << std::endl << std::endl;
}
}
for (Entrance& exit : areaTable[i].exits) {
try {
eval(LogicExpression::Parse(exit.GetConditionStr()));
} catch (std::exception& ex) {
ss << exit.GetConditionStr() << std::endl;
ss << ex.what() << std::endl << std::endl;
}
}
}
SPDLOG_INFO("Parse/Eval Failure Conditions:\n{}", ss.str());
}
SPDLOG_INFO("Parse Failure Conditions:\n{}", ss.str());
#endif
}

View file

@ -429,6 +429,9 @@ std::string LogicExpression::Impl::GetExprErrorContext() const {
#define REGISTER_FUNCTION(fn) \
{ #fn, LogicExpression::Impl::RegisterFunction(#fn, fn) }
#define REGISTER_FUNCTION_WITH_DEFAULTS(fn, ...) \
{ #fn, LogicExpression::Impl::RegisterFunctionWithDefaults(#fn, fn, std::make_tuple(__VA_ARGS__)) }
#define REGISTER_LOGIC_FUNCTION(fn) \
{ #fn, LogicExpression::Impl::RegisterLogicFunction(#fn, &Rando::Logic::fn) }
@ -482,9 +485,10 @@ std::unordered_map<std::string, LogicExpression::Impl::FunctionAdapter> LogicExp
void LogicExpression::Impl::PopulateFunctionAdapters() {
functionAdapters = {
REGISTER_FUNCTION(Here),
REGISTER_FUNCTION(MQSpiritSharedBrokenWallRoom),
REGISTER_FUNCTION(MQSpiritSharedStatueRoom),
REGISTER_FUNCTION_WITH_DEFAULTS(MQSpiritSharedBrokenWallRoom, RandomizerRegion{}, ConditionFn{}, false),
REGISTER_FUNCTION_WITH_DEFAULTS(MQSpiritSharedStatueRoom, RandomizerRegion{}, ConditionFn{}, false),
REGISTER_FUNCTION(CanBuyAnother),
REGISTER_FUNCTION(CanBuyCheck),
REGISTER_FUNCTION(GetOption),
REGISTER_FUNCTION(GetTrickOption),
REGISTER_FUNCTION(HasAccessTo),
@ -781,6 +785,11 @@ void LogicExpression::Impl::PopulateVariableAdapters() {
REGISTER_LOGIC_VARIABLE(MQSpirit3SunsEnemies),
REGISTER_LOGIC_VARIABLE(Spirit1FSilverRupees),
REGISTER_LOGIC_VARIABLE(JabuRutoIn1F),
REGISTER_LOGIC_VARIABLE(THRescuedAllCarpenters),
REGISTER_LOGIC_VARIABLE(THCouldFree1TorchCarpenter),
REGISTER_LOGIC_VARIABLE(THCouldFreeDoubleCellCarpenter),
REGISTER_LOGIC_VARIABLE(TH_CouldFreeDeadEndCarpenter),
REGISTER_LOGIC_VARIABLE(THCouldRescueSlopeCarpenter),
};
}

View file

@ -220,6 +220,42 @@ class LogicExpression {
};
}
// Helper to call member function with default parameters
// This function evaluates provided arguments and fills missing ones with defaults.
template <typename Function, typename Tuple, size_t... Is>
static ValueVariant
CallFunctionWithDefaultsImpl(const std::string& functionName, Function function,
const std::vector<std::shared_ptr<LogicExpression::Impl>>& args,
const std::string& path, int depth, const EvaluationCallback& callback,
Tuple&& defaults, std::index_sequence<Is...>) {
constexpr size_t expectedArgCount = sizeof...(Is);
// Ensure the number of provided arguments does not exceed the expected count
if (args.size() > expectedArgCount) {
throw std::runtime_error("Function " + functionName + " expects up to " +
std::to_string(expectedArgCount) + " arguments, but got " +
std::to_string(args.size()));
}
// Evaluate provided arguments and fill missing ones with defaults
return function((Is < args.size() ? EvaluateArg<std::tuple_element_t<Is, std::decay_t<Tuple>>>(
args[Is], path + "." + std::to_string(Is), depth, callback)
: std::get<Is>(defaults))...);
}
// Wrapper for member functions with default parameters
template <typename Function, typename... Args>
static FunctionAdapter RegisterFunctionWithDefaults(const std::string& functionName, Function function,
std::tuple<Args...> defaults) {
return [functionName, function, defaults](const std::vector<std::shared_ptr<LogicExpression::Impl>>& args,
const std::string& path, int depth,
const EvaluationCallback& callback) -> ValueVariant {
constexpr size_t expectedArgCount = sizeof...(Args);
return CallFunctionWithDefaultsImpl(functionName, function, args, path, depth, callback, defaults,
std::make_index_sequence<expectedArgCount>{});
};
}
// Helper to call pointer-to-member function on "logic" with extracted arguments.
template <typename MemberFunction, typename... Args, size_t... Is>
static ValueVariant CallMemberFunctionImpl(const std::string& functionName, MemberFunction function,

View file

@ -111,8 +111,7 @@ static void PopulateConnectionExpression(LogicTrackerNode::Connection& connectio
try {
expression = LogicExpression::Parse(expressionStr);
}
catch (const std::exception& e) {
} catch (const std::exception& e) {
connection.ExpressionTable.Root.ErrorMessage = std::string("Parse Error: ") + e.what();
connection.ExpressionTable.Root.Children.clear();
connection.ExpressionTable.CombineAll = true;

View file

@ -441,6 +441,8 @@ typedef enum {
{ "RO_ZF_OPEN", RO_ZF_OPEN },
{ "RO_WATERFALL_CLOSED", RO_WATERFALL_CLOSED },
{ "RO_WATERFALL_OPEN", RO_WATERFALL_OPEN },
{ "RO_JABU_CLOSED", RO_JABU_CLOSED },
{ "RO_JABU_OPEN", RO_JABU_OPEN },
{ "RO_AGE_CHILD", RO_AGE_CHILD },
{ "RO_AGE_ADULT", RO_AGE_ADULT },
{ "RO_AGE_RANDOM", RO_AGE_RANDOM },