Skip to content

Comments

Stringify Randomizer Enums#6223

Open
xxAtrain223 wants to merge 4 commits intoHarbourMasters:developfrom
xxAtrain223:StringifyEnums
Open

Stringify Randomizer Enums#6223
xxAtrain223 wants to merge 4 commits intoHarbourMasters:developfrom
xxAtrain223:StringifyEnums

Conversation

@xxAtrain223
Copy link
Contributor

@xxAtrain223 xxAtrain223 commented Feb 1, 2026

This PR moves the Randomizer Enums from randomizerTypes.h into separate files so they can be stringified.

There are a few different ways to do this, I chose this method to keep the enum definition co-located with the enum values.

One of the other ways to do this is with this pattern:

// randomizerTypes.h
#define DEFINE_RAND_INF(enum) enum,

typedef enum {
#include "randomizer_inf.h"
    RAND_INF_MAX,
} RandomizerInf;

#undef DEFINE_RAND_INF

// randomizer_inf.h
DEFINE_RAND_INF(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)
DEFINE_RAND_INF(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
...

// debugSaveEditor.h
#define DEFINE_RAND_INF(rand_inf) { rand_inf, #rand_inf },
...
#include "soh/Enhancements/randomizer/randomizer_inf.h"
...
#undef DEFINE_RAND_INF

This setup would expand to something like this:

// randomizerTypes.h
typedef enum {
RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE,
RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE,
...
    RAND_INF_MAX,
} RandomizerInf;

// debugSaveEditor.h
{ RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE" },
...

The way I have this implemented in this PR is like this:

// randomizerEnums.h
#if !defined(RANDO_ENUM_BEGIN) && !defined(RANDO_ENUM_ITEM) && !defined(RANDO_ENUM_END)
#define RANDO_ENUM_BEGIN(EnumName) typedef enum EnumName {
#define RANDO_ENUM_ITEM(name, ...) name __VA_OPT__(=) __VA_ARGS__,
#define RANDO_ENUM_END(EnumName) } EnumName;
#define RANDO_ENUM__CLEANUP
#endif

...
#include "randomizerEnums/RandomizerInf.h"
...

#ifdef RANDO_ENUM__CLEANUP
#undef RANDO_ENUM_BEGIN
#undef RANDO_ENUM_ITEM
#undef RANDO_ENUM_END
#undef RANDO_ENUM__CLEANUP
#endif

// RandomizerInf.h
RANDO_ENUM_BEGIN(RandomizerInf)
RANDO_ENUM_ITEM(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)
RANDO_ENUM_ITEM(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
...
RANDO_ENUM_ITEM(RAND_INF_MAX)
RANDO_ENUM_END(RandomizerInf)

// debugSaveEditor.h
#define RANDO_ENUM_ITEM(rand_inf) { rand_inf, #rand_inf },
#include "soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h"
#undef RANDO_ENUM_ITEM

This setup would expand to something like this:

// randomizerEnums.h
typedef enum RandomizerInf {
RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE,
RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE,
...
RAND_INF_MAX,
} RandomizerInf;

// debugSaveEditor.h
{ RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE" },
...

Both of these methods (and more) can achieve the same result. The reason I didn't choose the first pattern is because either all enum values need to be defined in separate files, or each of the enum values need to have different macros so they can be selectively defined where it's used. I chose the second pattern to try and get the best of both worlds, but it's still not perfect. The same macros are used for all enums, the entire enum definition is kept together, each enum can be in separate files or in shared files, but the selectively choosing an enum in a shared file (or the main include) requires creative macro definition overrides like the following.

#define RANDO_ENUM_BEGIN(EnumName) if constexpr (std::is_same_v<EnumName, RandomizerInf>)

So if a specific enum is needed for additional operations, then it'll be easier to move the enum into it's own file and included in randomizerEnums.h.

I've created a couple initial enum<=>string functions to show how macros can be redefined.

// Implemented as explicit template specializations in randomizerEnumStrings.cpp
template <typename T> const std::unordered_map<std::string_view, T>& GetStringToEnumMap();
template <typename T> const std::unordered_map<T, std::string_view>& GetEnumToStringMap();

// Simple convenience layer.
template <typename T> std::optional<T> StringToEnum(const std::string_view& str);
template <typename T> std::optional<std::string_view> EnumToString(const T& value);

Build Artifacts

@serprex
Copy link
Contributor

serprex commented Feb 4, 2026

seems relevant to #6205

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants