Rando: Allow strings as seed hashes (#2438)

* Allows strings to be used for rando seed hashes;
updated conversion method from `stoi` to `stoul`

* apply suggestions

* Allow spaces + autoselect on input field focus

* Added new text filter; applied suggestions

* leaving 3d rando logic alone

* Apply more suggestions

* Revert buffer size to 1024
This commit is contained in:
Ralphie Morell 2023-02-14 21:43:25 -05:00 committed by GitHub
parent e60f2b0c55
commit 7c3c662eba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 45 additions and 31 deletions

View File

@ -16,6 +16,7 @@
#include "debug.hpp" #include "debug.hpp"
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include "../../randomizer/randomizerTypes.h" #include "../../randomizer/randomizerTypes.h"
#include <boost_custom/container_hash/hash_32.hpp>
namespace { namespace {
bool seedChanged; bool seedChanged;
@ -512,16 +513,16 @@ void PrintOptionDescription() {
} }
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations,
std::string seedInput) { std::string seedString) {
srand(time(NULL)); srand(time(NULL));
// if a blank seed was entered, make a random one // if a blank seed was entered, make a random one
if (seedInput.empty()) { if (seedString.empty()) {
Settings::seed = rand() & 0xFFFFFFFF; Settings::seed = rand() & 0xFFFFFFFF;
} else if (seedInput.rfind("seed_testing_count", 0) == 0 && seedInput.length() > 18) { } else if (seedString.rfind("seed_testing_count", 0) == 0 && seedString.length() > 18) {
int count; int count;
try { try {
count = std::stoi(seedInput.substr(18), nullptr); count = std::stoi(seedString.substr(18), nullptr);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
count = 1; count = 1;
} catch (std::out_of_range &e) { } catch (std::out_of_range &e) {
@ -531,8 +532,10 @@ std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t>
return ""; return "";
} else { } else {
try { try {
int seed = std::stoi(seedInput, nullptr); uint32_t seedHash = boost::hash_32<std::string>{}(seedString);
int seed = seedHash & 0xFFFFFFFF;
Settings::seed = seed; Settings::seed = seed;
Settings::seedString = seedString;
} catch (...) { } catch (...) {
return ""; return "";
} }

View File

@ -12,7 +12,7 @@
#define TICKS_PER_SEC 268123480.0 #define TICKS_PER_SEC 268123480.0
void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarSettings, std::set<RandomizerCheck> excludedLocations, void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarSettings, std::set<RandomizerCheck> excludedLocations,
std::string seedInput) { std::string seedString) {
HintTable_Init(); HintTable_Init();
ItemTable_Init(); ItemTable_Init();
LocationTable_Init(); LocationTable_Init();
@ -20,7 +20,7 @@ void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarS
// std::string settingsFileName = "./randomizer/latest_settings.json"; // std::string settingsFileName = "./randomizer/latest_settings.json";
// CVarSetString("gLoadedPreset", settingsFileName.c_str()); // CVarSetString("gLoadedPreset", settingsFileName.c_str());
std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, seedInput).c_str()); std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, seedString).c_str());
CVarSetString("gSpoilerLog", fileName.c_str()); CVarSetString("gSpoilerLog", fileName.c_str());
CVarSave(); CVarSave();

View File

@ -23,6 +23,7 @@ namespace Settings {
std::string hash; std::string hash;
std::string version = RANDOMIZER_VERSION "-" COMMIT_NUMBER; std::string version = RANDOMIZER_VERSION "-" COMMIT_NUMBER;
std::array<uint8_t, 5> hashIconIndexes; std::array<uint8_t, 5> hashIconIndexes;
std::string seedString;
bool skipChildZelda = false; bool skipChildZelda = false;

View File

@ -891,6 +891,7 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
extern std::string version; extern std::string version;
extern std::array<uint8_t, 5> hashIconIndexes; extern std::array<uint8_t, 5> hashIconIndexes;
extern std::string hash; extern std::string hash;
extern std::string seedString;
extern bool skipChildZelda; extern bool skipChildZelda;

View File

@ -775,7 +775,7 @@ const char* SpoilerLog_Write(int language) {
jsonData.clear(); jsonData.clear();
jsonData["_version"] = (char*) gBuildVersion; jsonData["_version"] = (char*) gBuildVersion;
jsonData["_seed"] = Settings::seed; jsonData["_seed"] = Settings::seedString;
// Write Hash // Write Hash
int index = 0; int index = 0;

View File

@ -26,6 +26,7 @@
#include <functional> #include <functional>
#include "draw.h" #include "draw.h"
#include "rando_hash.h" #include "rando_hash.h"
#include <boost_custom/container_hash/hash_32.hpp>
extern "C" uint32_t ResourceMgr_IsGameMasterQuest(); extern "C" uint32_t ResourceMgr_IsGameMasterQuest();
extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum); extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
@ -39,7 +40,7 @@ std::multimap<std::tuple<s16, s16, s32>, RandomizerCheckObject> checkFromActorMu
std::set<RandomizerCheck> excludedLocations; std::set<RandomizerCheck> excludedLocations;
u8 generated; u8 generated;
char* seedInputBuffer; char* seedString;
const std::string Randomizer::getItemMessageTableID = "Randomizer"; const std::string Randomizer::getItemMessageTableID = "Randomizer";
const std::string Randomizer::hintMessageTableID = "RandomizerHints"; const std::string Randomizer::hintMessageTableID = "RandomizerHints";
@ -2949,8 +2950,6 @@ void GenerateRandomizerImgui(std::string seed = "") {
RandoMain::GenerateRando(cvarSettings, excludedLocations, seed); RandoMain::GenerateRando(cvarSettings, excludedLocations, seed);
memset(seedInputBuffer, 0, MAX_SEED_BUFFER_SIZE);
CVarSetInteger("gRandoGenerating", 0); CVarSetInteger("gRandoGenerating", 0);
CVarSave(); CVarSave();
CVarLoad(); CVarLoad();
@ -3049,27 +3048,28 @@ void DrawRandoEditor(bool& open) {
DrawPresetSelector(PRESET_TYPE_RANDOMIZER); DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
UIWidgets::EnhancementCheckbox("Manual seed entry", "gRandoManualSeedEntry", false, "");
ImGui::Text("Seed"); if (CVarGetInteger("gRandoManualSeedEntry", 0)) {
if (ImGui::InputText("##RandomizerSeed", seedInputBuffer, MAX_SEED_BUFFER_SIZE, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterNumbers)) { ImGui::Text("Seed");
uint32_t seedInput; ImGui::InputText("##RandomizerSeed", seedString, MAX_SEED_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum);
ImGui::DataTypeApplyFromText(seedInputBuffer, ImGuiDataType_U32, &seedInput, "%u"); UIWidgets::Tooltip(
strncpy(seedInputBuffer, std::to_string(seedInput).c_str(), MAX_SEED_BUFFER_SIZE); "Characters from a-z, A-Z, and 0-9 are supported.\n"
} "Character limit is 1023, after which the seed will be truncated.\n"
UIWidgets::Tooltip("Leaving this field blank will use a random seed value automatically\nSeed range is 0 - 4,294,967,295"); );
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("New Seed")) { if (ImGui::Button("New Seed")) {
strncpy(seedInputBuffer, std::to_string(rand() & 0xFFFFFFFF).c_str(), MAX_SEED_BUFFER_SIZE); strncpy(seedString, std::to_string(rand() & 0xFFFFFFFF).c_str(), MAX_SEED_STRING_SIZE);
} }
UIWidgets::Tooltip("Creates a new random seed value to be used when generating a randomizer"); UIWidgets::Tooltip("Creates a new random seed value to be used when generating a randomizer");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Clear Seed")) { if (ImGui::Button("Clear Seed")) {
memset(seedInputBuffer, 0, MAX_SEED_BUFFER_SIZE); memset(seedString, 0, MAX_SEED_STRING_SIZE);
}
} }
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
if (ImGui::Button("Generate Randomizer")) { if (ImGui::Button("Generate Randomizer")) {
GenerateRandomizer(seedInputBuffer); GenerateRandomizer(CVarGetInteger("gRandoManualSeedEntry", 0) ? seedString : std::to_string(rand() & 0xFFFFFFFF).c_str());
} }
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
@ -5305,7 +5305,7 @@ void InitRandoItemTable() {
void InitRando() { void InitRando() {
SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor); SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor);
Randomizer::CreateCustomMessages(); Randomizer::CreateCustomMessages();
seedInputBuffer = (char*)calloc(MAX_SEED_BUFFER_SIZE, sizeof(char)); seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char));
InitRandoItemTable(); InitRandoItemTable();
} }

View File

@ -12,7 +12,7 @@
#include <soh/Enhancements/custom-message/CustomMessageManager.h> #include <soh/Enhancements/custom-message/CustomMessageManager.h>
#include "soh/Enhancements/item-tables/ItemTableTypes.h" #include "soh/Enhancements/item-tables/ItemTableTypes.h"
#define MAX_SEED_BUFFER_SIZE 11 // digits for uint32 #define MAX_SEED_STRING_SIZE 1024
#define NUM_NAVI_MESSAGES 19 #define NUM_NAVI_MESSAGES 19
#define NUM_ICE_TRAP_MESSAGES 23 #define NUM_ICE_TRAP_MESSAGES 23
#define NUM_GORON_MESSAGES 9 #define NUM_GORON_MESSAGES 9

View File

@ -22,6 +22,15 @@ namespace UIWidgets {
} }
return 1; return 1;
} }
static int FilterAlphaNum(ImGuiInputTextCallbackData* data) {
const char* alphanum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ0123456789";
if (data->EventChar < 256 && strchr(alphanum, (char)data->EventChar)) {
return 0;
}
return 1;
}
}; };
// MARK: - Enums // MARK: - Enums