diff options
| -rw-r--r-- | mm/2s2h/Rando/Logic/FrenchVanilla.cpp | 226 | ||||
| -rw-r--r-- | mm/2s2h/Rando/Logic/Logic.h | 1 | ||||
| -rw-r--r-- | mm/2s2h/Rando/Menu.cpp | 29 | ||||
| -rw-r--r-- | mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp | 4 | ||||
| -rw-r--r-- | mm/2s2h/Rando/Types.h | 1 |
5 files changed, 4 insertions, 257 deletions
diff --git a/mm/2s2h/Rando/Logic/FrenchVanilla.cpp b/mm/2s2h/Rando/Logic/FrenchVanilla.cpp deleted file mode 100644 index 621e8dee3..000000000 --- a/mm/2s2h/Rando/Logic/FrenchVanilla.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include "Logic.h" -#include "2s2h/Rando/Types.h" - -#include <stdexcept> -#include <spdlog/spdlog.h> - -extern "C" { -#include "variables.h" -#include "ShipUtils.h" -uint64_t GetUnixTimestamp(); -} - -namespace Rando { - -namespace Logic { - -struct RandoPoolEntry { - bool shuffled; - RandoItemId vanillaItemId; - RandoItemId placedItemId; - bool itemPlaced; - bool checkFilled; - bool inPool; -}; - -struct RandoPoolPlacement { - RandoCheckId randoCheckId; - RandoCheckId randoCheckIdFromItem; - RandoItemId placedItemId; -}; - -void ApplyFrenchVanillaLogicToSaveContext(std::vector<RandoCheckId>& checkPool, std::vector<RandoItemId>& itemPool) { - uint64_t tick = GetUnixTimestamp(); - std::set<RandoCheckId> allChecksThatAreInLogic; - std::set<RandoCheckId> allChecksThatHaveBeenReachedAtLeastOnce; - - // Used across all iterations - std::map<RandoCheckId, RandoPoolEntry> currentCheckPool; - std::set<RandoRegionId> currentReachableRegions = { RR_MAX }; - std::set<std::pair<RandoEvent, std::function<bool()>>*> currentEventsTriggered; - - // Used for backtracking - std::vector<RandoPoolPlacement> placements; - std::vector<RandoRegionId> newlyAccessibleRegions; - std::vector<int> amountOfNewlyAccessibleRegions; - std::vector<RandoCheckId> newlyAccessibleChecks; - std::vector<int> amountOfNewlyAccessibleChecks; - std::vector<std::pair<RandoEvent, std::function<bool()>>*> newlyTriggeredEvents; - std::vector<int> amountOfNewlyTriggeredEvents; - - SaveContext copiedSaveContext; - memcpy(&copiedSaveContext, &gSaveContext, sizeof(SaveContext)); - - // First loop through all regions and add checks/items to the pool - for (auto& [randoRegionId, randoRegion] : Rando::Logic::Regions) { - for (auto& [randoCheckId, _] : randoRegion.checks) { - auto& randoStaticCheck = Rando::StaticData::Checks[randoCheckId]; - bool isShuffled = std::find(checkPool.begin(), checkPool.end(), randoCheckId) != checkPool.end(); - - allChecksThatAreInLogic.insert(randoCheckId); - currentCheckPool[randoCheckId] = { - isShuffled, randoStaticCheck.randoItemId, RI_UNKNOWN, false, false, false - }; - } - } - - while (true) { - // Break if we've been running for too long - if (GetUnixTimestamp() - tick > 5000) { - tick = GetUnixTimestamp(); - - // Log checks that have never been reached - std::vector<RandoCheckId> checksThatHaveNeverBeenReached; - - std::set_difference(allChecksThatAreInLogic.begin(), allChecksThatAreInLogic.end(), - allChecksThatHaveBeenReachedAtLeastOnce.begin(), - allChecksThatHaveBeenReachedAtLeastOnce.end(), - std::inserter(checksThatHaveNeverBeenReached, checksThatHaveNeverBeenReached.begin())); - - SPDLOG_ERROR("Checks that have never been reached:"); - for (RandoCheckId randoCheckId : checksThatHaveNeverBeenReached) { - SPDLOG_ERROR("{}", Rando::StaticData::Checks[randoCheckId].name); - } - - throw std::runtime_error("Logic Generation Timeout"); - } - - // Crawl through all reachable regions and add any new reachable regions - int currentAmountOfNewlyAccessibleRegions = newlyAccessibleRegions.size(); - std::set<RandoRegionId> currentReachableRegionsCopy = currentReachableRegions; - for (RandoRegionId regionId : currentReachableRegions) { - FindReachableRegions(regionId, currentReachableRegions); - } - // Difference between the new and old reachable regions - std::set_difference(currentReachableRegions.begin(), currentReachableRegions.end(), - currentReachableRegionsCopy.begin(), currentReachableRegionsCopy.end(), - std::inserter(newlyAccessibleRegions, - newlyAccessibleRegions.begin() + currentAmountOfNewlyAccessibleRegions)); - amountOfNewlyAccessibleRegions.push_back(newlyAccessibleRegions.size() - currentAmountOfNewlyAccessibleRegions); - - // Track newly accessible checks - int currentAmountOfNewlyAccessibleChecks = newlyAccessibleChecks.size(); - for (RandoRegionId regionId : currentReachableRegions) { - auto& randoRegion = Rando::Logic::Regions[regionId]; - for (auto& [randoCheckId, accessLogicFunc] : randoRegion.checks) { - if ( - // Check is not already in the pool - currentCheckPool[randoCheckId].inPool == false && - // Check is accessible - accessLogicFunc.first()) { - allChecksThatHaveBeenReachedAtLeastOnce.insert(randoCheckId); - currentCheckPool[randoCheckId].inPool = true; - newlyAccessibleChecks.push_back(randoCheckId); - } - } - } - amountOfNewlyAccessibleChecks.push_back(newlyAccessibleChecks.size() - currentAmountOfNewlyAccessibleChecks); - - // Track newly triggered events - int currentAmountOfNewlyTriggeredEvents = newlyTriggeredEvents.size(); - for (RandoRegionId regionId : currentReachableRegions) { - auto& randoRegion = Rando::Logic::Regions[regionId]; - for (auto& randoEvent : randoRegion.events) { - if ( - // Event is not already triggered - !currentEventsTriggered.contains(&randoEvent) && - // Event condition is met - randoEvent.second()) { - currentEventsTriggered.insert(&randoEvent); - newlyTriggeredEvents.push_back(&randoEvent); - RANDO_EVENTS[randoEvent.first]++; - } - } - } - amountOfNewlyTriggeredEvents.push_back(newlyTriggeredEvents.size() - currentAmountOfNewlyTriggeredEvents); - - // Determine if we have placed all items - int checksLeft = 0; - std::vector<RandoCheckId> currentCheckList; - std::vector<std::pair<RandoItemId, RandoCheckId>> currentItemList; - for (auto& [randoCheckId, randoPoolEntry] : currentCheckPool) { - if (randoPoolEntry.inPool) { - if (!randoPoolEntry.itemPlaced && randoPoolEntry.shuffled) { - currentItemList.push_back({ randoPoolEntry.vanillaItemId, randoCheckId }); - } - if (!randoPoolEntry.checkFilled) { - currentCheckList.push_back(randoCheckId); - } - } - if (!randoPoolEntry.checkFilled) { - checksLeft++; - } - } - if (checksLeft == 0) { - break; // All items placed - } - - // If there are no items to place, backtrack - if (currentCheckList.size() == 0) { - for (int i = 0; i < amountOfNewlyAccessibleRegions.back(); i++) { - currentReachableRegions.erase(newlyAccessibleRegions.back()); - newlyAccessibleRegions.pop_back(); - } - amountOfNewlyAccessibleRegions.pop_back(); - for (int i = 0; i < amountOfNewlyAccessibleChecks.back(); i++) { - currentCheckPool[newlyAccessibleChecks.back()].inPool = false; - newlyAccessibleChecks.pop_back(); - } - amountOfNewlyAccessibleChecks.pop_back(); - for (int i = 0; i < amountOfNewlyTriggeredEvents.back(); i++) { - RANDO_EVENTS[newlyTriggeredEvents.back()->first]--; - currentEventsTriggered.erase(newlyTriggeredEvents.back()); - newlyTriggeredEvents.pop_back(); - } - amountOfNewlyTriggeredEvents.pop_back(); - auto [randoCheckId, randoCheckIdFromItem, convertedItemId] = placements.back(); - currentCheckPool[randoCheckId].checkFilled = false; - currentCheckPool[randoCheckId].placedItemId = RI_UNKNOWN; - currentCheckPool[randoCheckIdFromItem].itemPlaced = false; - RemoveItem(convertedItemId); - placements.pop_back(); - continue; - } - - // Select a random check - size_t checkIndex = currentCheckList.size() > 1 ? Ship_Random(0, currentCheckList.size() - 1) : 0; - RandoCheckId randoCheckId = currentCheckList[checkIndex]; - if (currentCheckPool[randoCheckId].shuffled) { - // Select a random item - size_t itemIndex = currentItemList.size() > 1 ? Ship_Random(0, currentItemList.size() - 1) : 0; - auto [randoItemId, randoCheckIdFromItem] = currentItemList[itemIndex]; - SPDLOG_TRACE("Placing item {} in check {}", Rando::StaticData::Items[randoItemId].spoilerName, - Rando::StaticData::Checks[randoCheckId].name); - // Place the item in the check - currentCheckPool[randoCheckId].checkFilled = true; - currentCheckPool[randoCheckId].placedItemId = randoItemId; - currentCheckPool[randoCheckIdFromItem].itemPlaced = true; - RandoItemId convertedItemId = ConvertItem(randoItemId); - GiveItem(convertedItemId); - placements.push_back({ randoCheckId, randoCheckIdFromItem, convertedItemId }); - } else { - // Place vanilla item in the check - currentCheckPool[randoCheckId].checkFilled = true; - currentCheckPool[randoCheckId].placedItemId = currentCheckPool[randoCheckId].vanillaItemId; - currentCheckPool[randoCheckId].itemPlaced = true; - RandoItemId convertedItemId = ConvertItem(currentCheckPool[randoCheckId].vanillaItemId); - GiveItem(convertedItemId); - placements.push_back({ randoCheckId, randoCheckId, convertedItemId }); - } - } - - memcpy(&gSaveContext, &copiedSaveContext, sizeof(SaveContext)); - - for (auto& [randoCheckId, randoPoolEntry] : currentCheckPool) { - if (randoPoolEntry.shuffled) { - RANDO_SAVE_CHECKS[randoCheckId].randoItemId = randoPoolEntry.placedItemId; - RANDO_SAVE_CHECKS[randoCheckId].shuffled = true; - } - } - - SPDLOG_INFO("Successfully placed all items with French Vanilla logic"); -} - -} // namespace Logic - -} // namespace Rando diff --git a/mm/2s2h/Rando/Logic/Logic.h b/mm/2s2h/Rando/Logic/Logic.h index 2c0ed8db3..31912efb2 100644 --- a/mm/2s2h/Rando/Logic/Logic.h +++ b/mm/2s2h/Rando/Logic/Logic.h @@ -19,7 +19,6 @@ namespace Logic { void FindReachableRegions(RandoRegionId currentRegion, std::set<RandoRegionId>& reachableRegions); RandoRegionId GetRegionIdFromEntrance(s32 entrance); -void ApplyFrenchVanillaLogicToSaveContext(std::vector<RandoCheckId>& checkPool, std::vector<RandoItemId>& itemPool); void ApplyGlitchlessLogicToSaveContext(std::vector<RandoCheckId>& checkPool, std::vector<RandoItemId>& itemPool); void ApplyNearlyNoLogicToSaveContext(std::vector<RandoCheckId>& checkPool, std::vector<RandoItemId>& itemPool); void ApplyNoLogicToSaveContext(std::vector<RandoCheckId>& checkPool, std::vector<RandoItemId>& itemPool); diff --git a/mm/2s2h/Rando/Menu.cpp b/mm/2s2h/Rando/Menu.cpp index 1ec1d840a..b5fc784c2 100644 --- a/mm/2s2h/Rando/Menu.cpp +++ b/mm/2s2h/Rando/Menu.cpp @@ -10,7 +10,6 @@ std::unordered_map<int32_t, const char*> logicOptions = { { RO_LOGIC_GLITCHLESS, "Glitchless" }, { RO_LOGIC_NO_LOGIC, "No Logic" }, { RO_LOGIC_NEARLY_NO_LOGIC, "Nearly No Logic" }, - { RO_LOGIC_FRENCH_VANILLA, "French Vanilla" }, { RO_LOGIC_VANILLA, "Vanilla" }, }; @@ -29,12 +28,6 @@ std::unordered_map<int32_t, const char*> accessTrialsOptions = { { RO_ACCESS_TRIALS_OPEN, "Open" }, }; -std::vector<int32_t> incompatibleWithFrenchVanilla = { - RO_SHUFFLE_BOSS_SOULS, - RO_SHUFFLE_SWIM, - RO_PLENTIFUL_ITEMS, -}; - std::vector<int32_t> incompatibleWithVanilla = { RO_SHUFFLE_BOSS_SOULS, RO_SHUFFLE_SWIM, @@ -61,14 +54,7 @@ void ClearIncompatibleSetting() { int32_t currentLogicSetting = CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, Rando::StaticData::Options[RO_LOGIC].defaultValue); switch (currentLogicSetting) { - // French Vanilla can't have any options that add items without a corresponding check - case RO_LOGIC_FRENCH_VANILLA: - CVarClear(Rando::StaticData::Options[RO_PLENTIFUL_ITEMS].cvar); - CVarClear(Rando::StaticData::Options[RO_SHUFFLE_BOSS_SOULS].cvar); - CVarClear(Rando::StaticData::Options[RO_SHUFFLE_SWIM].cvar); - // TODO: Handle Starting Items to ensure starting sword/shield - break; - // Similar to French Vanilla, Vanilla can't add items without corresponding checks + // Vanilla can't add items without corresponding checks case RO_LOGIC_VANILLA: CVarClear(Rando::StaticData::Options[RO_PLENTIFUL_ITEMS].cvar); CVarClear(Rando::StaticData::Options[RO_SHUFFLE_BOSS_SOULS].cvar); @@ -83,12 +69,6 @@ bool IncompatibleWithLogicSetting(int32_t option) { int32_t currentLogicSetting = CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, Rando::StaticData::Options[RO_LOGIC].defaultValue); switch (currentLogicSetting) { - case RO_LOGIC_FRENCH_VANILLA: - if (std::find(incompatibleWithFrenchVanilla.begin(), incompatibleWithFrenchVanilla.end(), option) != - incompatibleWithFrenchVanilla.end()) { - return true; - } - break; case RO_LOGIC_VANILLA: if (std::find(incompatibleWithVanilla.begin(), incompatibleWithVanilla.end(), option) != incompatibleWithVanilla.end()) { @@ -197,9 +177,6 @@ static void DrawLogicConditionsTab() { "- Oath to Order and Remains cannot be placed on the Moon.\n" "- Deku Mask, Zora Mask, Sonata, and Bossa Nova cannot be placed in their respective Temples or on " "the Moon.\n\n" - "French Vanilla - This is an alternative variant to Glitchless, but the items are biased to be " - "closer to their vanilla locations. Tends to be an more beginner friendly experience.\n" - "Not compatible with settings that add items to the pool, like Boss Souls or Plentiful Items.\n\n" "Vanilla - The items are not shuffled.\n" "Not compatible with settings that add items to the pool, like Boss Souls or Plentiful Items."); ImGui::EndChild(); @@ -502,9 +479,9 @@ static void DrawStartingItemsTab() { } static void DrawLocationsTab() { - if (CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, RO_LOGIC_GLITCHLESS) >= RO_LOGIC_FRENCH_VANILLA) { + if (CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, RO_LOGIC_GLITCHLESS) >= RO_LOGIC_VANILLA) { ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Red), - "This setting is not compatible with French Vanilla or Vanilla Logic."); + "This setting is not compatible with Vanilla Logic."); return; } diff --git a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp index 42e712ac5..f41e47afc 100644 --- a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp +++ b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp @@ -212,7 +212,7 @@ 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. + // pool except if Logic is set to 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()) { @@ -424,8 +424,6 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) { Rando::Logic::ApplyNearlyNoLogicToSaveContext(checkPool, itemPool); } else if (RANDO_SAVE_OPTIONS[RO_LOGIC] == RO_LOGIC_GLITCHLESS) { Rando::Logic::ApplyGlitchlessLogicToSaveContext(checkPool, itemPool); - } else if (RANDO_SAVE_OPTIONS[RO_LOGIC] == RO_LOGIC_FRENCH_VANILLA) { - Rando::Logic::ApplyFrenchVanillaLogicToSaveContext(checkPool, itemPool); } else { throw std::runtime_error("Logic option not implemented: " + std::to_string(RANDO_SAVE_OPTIONS[RO_LOGIC])); diff --git a/mm/2s2h/Rando/Types.h b/mm/2s2h/Rando/Types.h index 8841137d7..55f72831d 100644 --- a/mm/2s2h/Rando/Types.h +++ b/mm/2s2h/Rando/Types.h @@ -2828,7 +2828,6 @@ typedef enum { RO_LOGIC_GLITCHLESS, RO_LOGIC_NO_LOGIC, RO_LOGIC_NEARLY_NO_LOGIC, - RO_LOGIC_FRENCH_VANILLA, RO_LOGIC_VANILLA, } RandoOptionLogic; |
