summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaladius <Caladius@users.noreply.github.com>2025-10-15 12:35:42 -0400
committerGitHub <noreply@github.com>2025-10-15 12:35:42 -0400
commitd53bdbb239016df5abd0edd04bbcc294ce94269f (patch)
tree286d44bfce03abf2b0dc264ed5dd87920340be8e
parentdfcc80e38a6678e5c058d108574e22c75711ad5f (diff)
[Rando] Excluding Checks from Seed (#1069)
* Operational Check Exclusion List. needs logic help. * Add Search filter and Clear All * shemantics * Fix build errors * Clear out unsused code. * Better =/ * This works now, just debug boot to warp seems to be finnicky. * clang * Fix Logic Generation and Regeneration. * Feedback Fixes * Updates * Fix Logic Generation and restrict for specific Logic Types. * Update Glitchless Logic * Update rest of Logics
-rw-r--r--mm/2s2h/Rando/Logic/GlitchlessLogic.cpp12
-rw-r--r--mm/2s2h/Rando/Logic/NearlyNoLogic.cpp17
-rw-r--r--mm/2s2h/Rando/Logic/NoLogic.cpp20
-rw-r--r--mm/2s2h/Rando/Menu.cpp162
-rw-r--r--mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp25
5 files changed, 223 insertions, 13 deletions
diff --git a/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp b/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp
index b22f1a140..338733c4e 100644
--- a/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp
+++ b/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp
@@ -96,7 +96,17 @@ void ApplyGlitchlessLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& c
RandoItemId randoItemId;
- if (isShuffled) {
+ if (RANDO_SAVE_CHECKS[randoCheckId].skipped) {
+ uint32_t index = 0;
+ for (auto& item : itemPool) {
+ if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) {
+ randoItemId = item;
+ itemPool.erase(itemPool.begin() + index);
+ break;
+ }
+ index++;
+ }
+ } else if (isShuffled) {
randoItemId = itemPool.back();
itemPool.pop_back();
diff --git a/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp b/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp
index 788e94df3..c1af5a468 100644
--- a/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp
+++ b/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp
@@ -48,8 +48,21 @@ void ApplyNearlyNoLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& che
continue;
}
- RandoItemId randoItemId = itemPool.back();
- itemPool.pop_back();
+ RandoItemId randoItemId = RI_NONE;
+ if (RANDO_SAVE_CHECKS[randoCheckId].skipped) {
+ uint32_t index = 0;
+ for (auto& item : itemPool) {
+ if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) {
+ randoItemId = item;
+ itemPool.erase(itemPool.begin() + index);
+ break;
+ }
+ index++;
+ }
+ } else {
+ randoItemId = itemPool.back();
+ itemPool.pop_back();
+ }
RANDO_SAVE_CHECKS[randoCheckId].shuffled = true;
RANDO_SAVE_CHECKS[randoCheckId].randoItemId = randoItemId;
diff --git a/mm/2s2h/Rando/Logic/NoLogic.cpp b/mm/2s2h/Rando/Logic/NoLogic.cpp
index 0b4559299..e820c9176 100644
--- a/mm/2s2h/Rando/Logic/NoLogic.cpp
+++ b/mm/2s2h/Rando/Logic/NoLogic.cpp
@@ -10,6 +10,21 @@ namespace Rando {
namespace Logic {
void ApplyNoLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& checkPool, std::vector<RandoItemId>& itemPool) {
+ std::vector<RandoItemId> junkPool;
+ for (auto& [randoCheckId, _] : checkPool) {
+ if (RANDO_SAVE_CHECKS[randoCheckId].skipped) {
+ uint32_t index = 0;
+ for (auto& item : itemPool) {
+ if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) {
+ junkPool.push_back(item);
+ itemPool.erase(itemPool.begin() + index);
+ break;
+ }
+ index++;
+ }
+ }
+ }
+
for (size_t i = 0; i < itemPool.size(); i++) {
std::swap(itemPool[i], itemPool[Ship_Random(0, itemPool.size() - 1)]);
}
@@ -20,6 +35,11 @@ void ApplyNoLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& checkPool
}
RANDO_SAVE_CHECKS[randoCheckId].shuffled = true;
+ if (RANDO_SAVE_CHECKS[randoCheckId].skipped == true) {
+ RANDO_SAVE_CHECKS[randoCheckId].randoItemId = junkPool.back();
+ junkPool.pop_back();
+ continue;
+ }
RANDO_SAVE_CHECKS[randoCheckId].randoItemId = itemPool.back();
itemPool.pop_back();
}
diff --git a/mm/2s2h/Rando/Menu.cpp b/mm/2s2h/Rando/Menu.cpp
index 4612d4aa1..3cbf76f23 100644
--- a/mm/2s2h/Rando/Menu.cpp
+++ b/mm/2s2h/Rando/Menu.cpp
@@ -39,6 +39,9 @@ std::vector<int32_t> incompatibleWithVanilla = {
RO_PLENTIFUL_ITEMS,
};
+std::vector<RandoCheckId> checkExclusionList;
+bool isExcludedInitialized = false;
+
namespace BenGui {
extern std::shared_ptr<Rando::CheckTracker::CheckTrackerWindow> mRandoCheckTrackerWindow;
extern std::shared_ptr<Rando::CheckTracker::SettingsWindow> mRandoCheckTrackerSettingsWindow;
@@ -94,6 +97,35 @@ bool IncompatibleWithLogicSetting(int32_t option) {
return false;
}
+void SortExcludedChecks() {
+ std::sort(checkExclusionList.begin(), checkExclusionList.end());
+}
+
+void SaveExcludedChecks() {
+ std::string excludedString = "";
+ SortExcludedChecks();
+
+ for (auto& data : checkExclusionList) {
+ excludedString += std::to_string(data).c_str();
+ excludedString += ",";
+ }
+ CVarSetString("gRando.ExcludedChecks", excludedString.c_str());
+}
+
+void LoadExcludedChecks() {
+ std::vector<RandoCheckId> sortedExclusionList;
+ std::string checksList = CVarGetString("gRando.ExcludedChecks", "");
+
+ if (checksList != "") {
+ std::string word;
+ std::istringstream stream(checksList);
+ while (std::getline(stream, word, ',')) {
+ checkExclusionList.push_back((RandoCheckId)std::stoi(word));
+ }
+ }
+ SortExcludedChecks();
+}
+
static void DrawGeneralTab() {
ImGui::BeginChild("randoSettings");
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 0.5f));
@@ -191,11 +223,11 @@ static void DrawLogicConditionsTab() {
ImGui::EndChild();
}
-static void DrawLocationsTab() {
+static void DrawShufflesTab() {
f32 columnWidth = ImGui::GetContentRegionAvail().x / 3 - (ImGui::GetStyle().ItemSpacing.x * 2);
f32 halfHeight = ImGui::GetContentRegionAvail().y / 2 - (ImGui::GetStyle().ItemSpacing.y * 2);
ImGui::SeparatorText("Shuffle Options");
- ImGui::BeginChild("randoLocationsColumn1", ImVec2(columnWidth, halfHeight));
+ ImGui::BeginChild("randoShufflesColumn1", ImVec2(columnWidth, halfHeight));
CVarCheckbox("Shuffle Songs", "gPlaceholderBool",
CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }).DefaultValue(true));
CVarCheckbox("Shuffle Owl Statues", Rando::StaticData::Options[RO_SHUFFLE_OWL_STATUES].cvar);
@@ -216,7 +248,7 @@ static void DrawLocationsTab() {
.DefaultValue(STRAY_FAIRY_SCATTERED_TOTAL));
ImGui::EndChild();
ImGui::SameLine();
- ImGui::BeginChild("randoLocationsColumn2", ImVec2(columnWidth, halfHeight));
+ ImGui::BeginChild("randoShufflesColumn2", ImVec2(columnWidth, halfHeight));
CVarCheckbox("Shuffle Pot Drops", Rando::StaticData::Options[RO_SHUFFLE_POT_DROPS].cvar);
CVarCheckbox("Shuffle Crate Drops", Rando::StaticData::Options[RO_SHUFFLE_CRATE_DROPS].cvar);
CVarCheckbox("Shuffle Barrel Drops", Rando::StaticData::Options[RO_SHUFFLE_BARREL_DROPS].cvar);
@@ -230,11 +262,7 @@ static void DrawLocationsTab() {
CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
ImGui::EndChild();
ImGui::SameLine();
- ImGui::BeginChild("randoLocationsColumn3", ImVec2(columnWidth, halfHeight));
- ImGui::EndChild();
- ImGui::BeginChild("randoLocationsExclusions", ImVec2(0, 0));
- ImGui::SeparatorText("Exclusions");
- ImGui::TextWrapped("These checks will be guaranteed junk items, and marked as skipped in the check tracker.");
+ ImGui::BeginChild("randoShufflesColumn3", ImVec2(columnWidth, halfHeight));
ImGui::EndChild();
}
@@ -402,6 +430,117 @@ static void DrawItemsTab() {
ImGui::EndChild();
}
+static void DrawLocationsTab() {
+ if (CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, RO_LOGIC_GLITCHLESS) >= RO_LOGIC_FRENCH_VANILLA) {
+ ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Red),
+ "This setting is not compatible with French Vanilla or Vanilla Logic.");
+ return;
+ }
+
+ auto menuThemeColor = UIWidgets::Colors(CVarGetInteger("gSettings.Menu.Theme", LightBlue));
+ bool clearExcluded = false;
+ if (!isExcludedInitialized) {
+ LoadExcludedChecks();
+ isExcludedInitialized = true;
+ }
+
+ f32 columnWidth = ImGui::GetContentRegionAvail().x / 2 - (ImGui::GetStyle().ItemSpacing.x * 2);
+ ImGui::BeginChild("randoIncludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y));
+ ImGui::SeparatorText("Included Checks");
+
+ static ImGuiTextFilter includedFilter;
+ UIWidgets::PushStyleCombobox(menuThemeColor);
+
+ includedFilter.Draw("##filter", ImGui::GetContentRegionAvail().x - 5.0f);
+ UIWidgets::PopStyleCombobox();
+ if (!includedFilter.IsActive()) {
+ ImGui::SameLine(18.0f);
+ ImGui::Text("Included Search");
+ }
+
+ if (ImGui::BeginTable("Included Checks", 1)) {
+ ImGui::TableNextColumn();
+
+ for (auto& includedChecks : Rando::StaticData::Checks) {
+ if (includedChecks.first == RC_UNKNOWN) {
+ continue;
+ }
+
+ if (!includedFilter.PassFilter(
+ convertEnumToReadableName(Rando::StaticData::Checks[includedChecks.first].name).c_str())) {
+ continue;
+ }
+
+ auto it = std::find(checkExclusionList.begin(), checkExclusionList.end(), includedChecks.first);
+ if (it != checkExclusionList.end()) {
+ continue;
+ }
+
+ ImGui::BeginGroup();
+ ImGui::Text("%s", convertEnumToReadableName(Rando::StaticData::Checks[includedChecks.first].name).c_str());
+ ImGui::SameLine();
+ ImGui::Dummy(ImVec2(ImGui::GetContentRegionAvail().x, 0));
+ ImGui::EndGroup();
+
+ ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
+ ImGui::IsItemHovered() ? IM_COL32(255, 255, 0, 128) : IM_COL32(255, 255, 255, 0));
+ if (ImGui::IsItemClicked()) {
+ checkExclusionList.push_back(includedChecks.first);
+ SaveExcludedChecks();
+ }
+ ImGui::TableNextColumn();
+ }
+ ImGui::EndTable();
+ }
+ ImGui::EndChild();
+ ImGui::SameLine();
+ ImGui::BeginChild("randoExcludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y));
+ ImGui::SeparatorText("Forced Junk Checks");
+
+ static ImGuiTextFilter excludedFilter;
+ UIWidgets::PushStyleCombobox(menuThemeColor);
+ excludedFilter.Draw("##filter", ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize("Clear All").x - 30.0f);
+ if (!excludedFilter.IsActive()) {
+ ImGui::SameLine(18.0f);
+ ImGui::Text("Excluded Search");
+ }
+ ImGui::SameLine(ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize("Clear All").x - 24.0f);
+ if (ImGui::Button("Clear All")) {
+ clearExcluded = true;
+ }
+ UIWidgets::PopStyleCombobox();
+
+ if (ImGui::BeginTable("Excluded Checks", 1)) {
+ ImGui::TableNextColumn();
+ int16_t index = 0;
+ for (auto& excludedChecks : checkExclusionList) {
+ if (!excludedFilter.PassFilter(
+ convertEnumToReadableName(Rando::StaticData::Checks[excludedChecks].name).c_str())) {
+ continue;
+ }
+
+ ImGui::Text("%s", convertEnumToReadableName(Rando::StaticData::Checks[excludedChecks].name).c_str());
+
+ ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
+ ImGui::IsItemHovered() ? IM_COL32(255, 255, 0, 128) : IM_COL32(255, 255, 255, 0));
+ if (ImGui::IsItemClicked()) {
+ checkExclusionList.erase(checkExclusionList.begin() + index);
+ SaveExcludedChecks();
+ }
+ index++;
+ ImGui::TableNextColumn();
+ }
+ ImGui::EndTable();
+ }
+ ImGui::EndChild();
+
+ if (clearExcluded) {
+ checkExclusionList.clear();
+ SaveExcludedChecks();
+ clearExcluded = false;
+ }
+}
+
static void DrawHintsTab() {
f32 columnWidth = ImGui::GetContentRegionAvail().x / 3 - (ImGui::GetStyle().ItemSpacing.x * 2);
f32 halfHeight = ImGui::GetContentRegionAvail().y / 2 - (ImGui::GetStyle().ItemSpacing.y * 2);
@@ -457,12 +596,15 @@ void Rando::RegisterMenu() {
mBenMenu->AddWidget(path, "Logic/Conditions", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) {
DrawLogicConditionsTab();
});
+ mBenMenu->AddSidebarEntry("Rando", "Shuffle Options", 1);
+ path.sidebarName = "Shuffle Options";
+ mBenMenu->AddWidget(path, "Locations", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawShufflesTab(); });
mBenMenu->AddSidebarEntry("Rando", "Locations", 1);
- path.sidebarName = "Locations";
- mBenMenu->AddWidget(path, "Locations", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawLocationsTab(); });
mBenMenu->AddSidebarEntry("Rando", "Items", 1);
path.sidebarName = "Items";
mBenMenu->AddWidget(path, "Items", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawItemsTab(); });
+ path.sidebarName = "Locations";
+ mBenMenu->AddWidget(path, "Locations", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawLocationsTab(); });
mBenMenu->AddSidebarEntry("Rando", "Hints", 1);
path.sidebarName = "Hints";
mBenMenu->AddWidget(path, "Hints", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawHintsTab(); });
diff --git a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp
index 85d101dd1..668f5e7ba 100644
--- a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp
+++ b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp
@@ -105,6 +105,15 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) {
std::unordered_map<RandoCheckId, bool> checkPool;
std::vector<RandoItemId> itemPool;
+ // Create Excluded Checks List to eliminate excluded checks from the pool
+ std::vector<RandoCheckId> excludedChecks;
+ std::string excludedChecksList = CVarGetString("gRando.ExcludedChecks", "");
+ std::string word;
+ std::istringstream stream(excludedChecksList);
+ while (std::getline(stream, word, ',')) {
+ excludedChecks.push_back((RandoCheckId)std::stoi(word));
+ }
+
// First loop through all regions and add checks/items to the pool
for (auto& [randoRegionId, randoRegion] : Rando::Logic::Regions) {
for (auto& [randoCheckId, _] : randoRegion.checks) {
@@ -203,6 +212,22 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) {
}
}
+ // Skip checks that have been excluded in the Locations menu and add their vanilla item to the
+ // pool except if Logic is set to Vanilla or French Vanilla.
+ if (RANDO_SAVE_OPTIONS[RO_LOGIC] <= RO_LOGIC_NEARLY_NO_LOGIC) {
+ auto it = std::find(excludedChecks.begin(), excludedChecks.end(), randoCheckId);
+ if (it != excludedChecks.end()) {
+ RandoItemId vanillaItem = Rando::StaticData::Checks[randoCheckId].randoItemId;
+ itemPool.push_back(vanillaItem);
+
+ RANDO_SAVE_CHECKS[randoCheckId].randoItemId = RI_JUNK;
+ RANDO_SAVE_CHECKS[randoCheckId].skipped = true;
+
+ checkPool.insert({ randoCheckId, true });
+ continue;
+ }
+ }
+
checkPool.insert({ randoCheckId, true });
itemPool.push_back(randoStaticCheck.randoItemId);
}