Reset logic and ApplyOrStoreItems without applying the item effects to the save when calculating available checks.

This commit is contained in:
Anthony Stewart 2025-04-18 20:07:14 -05:00
commit 23812b384b
5 changed files with 59 additions and 47 deletions

View file

@ -210,7 +210,7 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
for (auto& exit : region->exits) { for (auto& exit : region->exits) {
int16_t entranceIndex = exit.GetIndex(); int16_t entranceIndex = exit.GetIndex();
if (gals.calculatingAvailableChecks && ctx->GetOption(RSK_SHUFFLE_ENTRANCES).Get() && exit.IsShuffled() && if (logic->CalculatingAvailableChecks && ctx->GetOption(RSK_SHUFFLE_ENTRANCES).Get() && exit.IsShuffled() &&
entranceIndex != -1 && !Entrance_GetIsEntranceDiscovered(entranceIndex)) { entranceIndex != -1 && !Entrance_GetIsEntranceDiscovered(entranceIndex)) {
continue; continue;
} }
@ -427,18 +427,13 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
Rando::ItemLocation* location = ctx->GetItemLocation(loc); Rando::ItemLocation* location = ctx->GetItemLocation(loc);
RandomizerGet locItem = location->GetPlacedRandomizerGet(); RandomizerGet locItem = location->GetPlacedRandomizerGet();
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, gals.calculatingAvailableChecks)) { if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, logic->CalculatingAvailableChecks)) {
if (gals.calculatingAvailableChecks) {
gals.accessibleLocations.push_back(loc);
StopPerformanceTimer(PT_LOCATION_LOGIC);
return false;
}
location->AddToPool(); location->AddToPool();
if (locItem == RG_NONE) { if (locItem == RG_NONE || logic->CalculatingAvailableChecks) {
gals.accessibleLocations.push_back(loc); // Empty location, consider for placement gals.accessibleLocations.push_back(loc); // Empty location, consider for placement
} else { }
if (locItem != RG_NONE) {
// If ignore has a value, we want to check if the item location should be considered or not // If ignore has a value, we want to check if the item location should be considered or not
// This is necessary due to the below preprocessing for playthrough generation // This is necessary due to the below preprocessing for playthrough generation
if (ignore != RG_NONE) { if (ignore != RG_NONE) {
@ -537,8 +532,11 @@ std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerChec
bool calculatingAvailableChecks /* = false */) { bool calculatingAvailableChecks /* = false */) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
GetAccessibleLocationsStruct gals(0); GetAccessibleLocationsStruct gals(0);
gals.calculatingAvailableChecks = calculatingAvailableChecks;
ResetLogic(ctx, gals, !calculatingAvailableChecks); ResetLogic(ctx, gals, !calculatingAvailableChecks);
if (calculatingAvailableChecks) {
logic->Reset(false);
logic->CalculatingAvailableChecks = true;
}
do { do {
gals.InitLoop(); gals.InitLoop();
for (size_t i = 0; i < gals.regionPool.size(); i++) { for (size_t i = 0; i < gals.regionPool.size(); i++) {

View file

@ -34,8 +34,6 @@ struct GetAccessibleLocationsStruct {
std::vector<RandomizerCheck> itemSphere; std::vector<RandomizerCheck> itemSphere;
std::list<Rando::Entrance*> entranceSphere; std::list<Rando::Entrance*> entranceSphere;
bool calculatingAvailableChecks = false;
GetAccessibleLocationsStruct(int _maxGsCount){ GetAccessibleLocationsStruct(int _maxGsCount){
regionPool = {RR_ROOT}; regionPool = {RR_ROOT};
gsCount = 0; gsCount = 0;

View file

@ -46,14 +46,20 @@ Item::~Item() = default;
void Item::ApplyEffect() const { void Item::ApplyEffect() const {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true); auto logic = ctx->GetLogic();
ctx->GetLogic()->SetInLogic(logicVal, true); if (!logic->CalculatingAvailableChecks) {
logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true);
}
logic->SetInLogic(logicVal, true);
} }
void Item::UndoEffect() const { void Item::UndoEffect() const {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false); auto logic = ctx->GetLogic();
ctx->GetLogic()->SetInLogic(logicVal, false); if (!logic->CalculatingAvailableChecks) {
logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false);
}
logic->SetInLogic(logicVal, false);
} }
const Text& Item::GetName() const { const Text& Item::GetName() const {

View file

@ -2331,8 +2331,10 @@ void Logic::SetInLogic(LogicVal logicVal, bool value) {
inLogic[logicVal] = value; inLogic[logicVal] = value;
} }
void Logic::Reset() { void Logic::Reset(bool resetSaveContext /*= true*/) {
if (resetSaveContext) {
NewSaveContext(); NewSaveContext();
}
StartPerformanceTimer(PT_LOGIC_RESET); StartPerformanceTimer(PT_LOGIC_RESET);
memset(inLogic, false, sizeof(inLogic)); memset(inLogic, false, sizeof(inLogic));
// Settings-dependent variables // Settings-dependent variables
@ -2371,6 +2373,7 @@ void Logic::Reset() {
ShadowTrialClear = false; ShadowTrialClear = false;
LightTrialClear = false; LightTrialClear = false;
if (resetSaveContext) {
// Ocarina C Buttons // Ocarina C Buttons
bool ocBtnShuffle = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true); bool ocBtnShuffle = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true);
SetRandoInf(RAND_INF_HAS_OCARINA_A, !ocBtnShuffle); SetRandoInf(RAND_INF_HAS_OCARINA_A, !ocBtnShuffle);
@ -2398,11 +2401,12 @@ void Logic::Reset() {
SetRandoInf(RAND_INF_FISHING_POLE_FOUND, true); SetRandoInf(RAND_INF_FISHING_POLE_FOUND, true);
} }
// If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla // If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in
// FiT // vanilla FiT
if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) {
SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1); SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1);
} }
}
// Bottle Count // Bottle Count
Bottles = 0; Bottles = 0;
@ -2454,7 +2458,9 @@ void Logic::Reset() {
// Other // Other
AtDay = false; AtDay = false;
AtNight = false; AtNight = false;
if (resetSaveContext) {
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get(); GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
}
// Events // Events
ShowedMidoSwordAndShield = false; ShowedMidoSwordAndShield = false;
@ -2518,6 +2524,8 @@ void Logic::Reset() {
Spirit1FSilverRupees = false; Spirit1FSilverRupees = false;
JabuRutoIn1F = false; JabuRutoIn1F = false;
CalculatingAvailableChecks = false;
StopPerformanceTimer(PT_LOGIC_RESET); StopPerformanceTimer(PT_LOGIC_RESET);
} }
} // namespace Rando } // namespace Rando

View file

@ -183,6 +183,8 @@ class Logic {
/* --- END OF HELPERS AND LOCATION ACCESS --- */ /* --- END OF HELPERS AND LOCATION ACCESS --- */
bool CalculatingAvailableChecks = false;
SaveContext* mSaveContext = nullptr; SaveContext* mSaveContext = nullptr;
Logic(); Logic();
bool CanUse(RandomizerGet itemName); bool CanUse(RandomizerGet itemName);
@ -254,7 +256,7 @@ class Logic {
bool CanUseProjectile(); bool CanUseProjectile();
bool CanBuildRainbowBridge(); bool CanBuildRainbowBridge();
bool CanTriggerLACS(); bool CanTriggerLACS();
void Reset(); void Reset(bool resetSaveContext = true);
void SetContext(std::shared_ptr<Context> _ctx); void SetContext(std::shared_ptr<Context> _ctx);
bool GetInLogic(LogicVal logicVal); bool GetInLogic(LogicVal logicVal);
void SetInLogic(LogicVal logicVal, bool remove); void SetInLogic(LogicVal logicVal, bool remove);