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
parent 5ffb7fbe5b
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();
for (auto& exit : region->exits) {
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)) {
continue;
}
@ -427,18 +427,13 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
Rando::ItemLocation* location = ctx->GetItemLocation(loc);
RandomizerGet locItem = location->GetPlacedRandomizerGet();
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, gals.calculatingAvailableChecks)) {
if (gals.calculatingAvailableChecks) {
gals.accessibleLocations.push_back(loc);
StopPerformanceTimer(PT_LOCATION_LOGIC);
return false;
}
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, logic->CalculatingAvailableChecks)) {
location->AddToPool();
if (locItem == RG_NONE) {
if (locItem == RG_NONE || logic->CalculatingAvailableChecks) {
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
// This is necessary due to the below preprocessing for playthrough generation
if (ignore != RG_NONE) {
@ -537,8 +532,11 @@ std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerChec
bool calculatingAvailableChecks /* = false */) {
auto ctx = Rando::Context::GetInstance();
GetAccessibleLocationsStruct gals(0);
gals.calculatingAvailableChecks = calculatingAvailableChecks;
ResetLogic(ctx, gals, !calculatingAvailableChecks);
if (calculatingAvailableChecks) {
logic->Reset(false);
logic->CalculatingAvailableChecks = true;
}
do {
gals.InitLoop();
for (size_t i = 0; i < gals.regionPool.size(); i++) {

View file

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

View file

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

View file

@ -2331,8 +2331,10 @@ void Logic::SetInLogic(LogicVal logicVal, bool value) {
inLogic[logicVal] = value;
}
void Logic::Reset() {
NewSaveContext();
void Logic::Reset(bool resetSaveContext /*= true*/) {
if (resetSaveContext) {
NewSaveContext();
}
StartPerformanceTimer(PT_LOGIC_RESET);
memset(inLogic, false, sizeof(inLogic));
// Settings-dependent variables
@ -2371,37 +2373,39 @@ void Logic::Reset() {
ShadowTrialClear = false;
LightTrialClear = false;
// Ocarina C Buttons
bool ocBtnShuffle = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true);
SetRandoInf(RAND_INF_HAS_OCARINA_A, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_UP, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_DOWN, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_LEFT, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_RIGHT, !ocBtnShuffle);
if (resetSaveContext) {
// Ocarina C Buttons
bool ocBtnShuffle = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true);
SetRandoInf(RAND_INF_HAS_OCARINA_A, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_UP, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_DOWN, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_LEFT, !ocBtnShuffle);
SetRandoInf(RAND_INF_HAS_OCARINA_C_RIGHT, !ocBtnShuffle);
// Progressive Items
SetUpgrade(UPG_STICKS, ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Is(true) ? 0 : 1);
SetUpgrade(UPG_NUTS, ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Is(true) ? 0 : 1);
// Progressive Items
SetUpgrade(UPG_STICKS, ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Is(true) ? 0 : 1);
SetUpgrade(UPG_NUTS, ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Is(true) ? 0 : 1);
// If we're not shuffling swim, we start with it
if (ctx->GetOption(RSK_SHUFFLE_SWIM).Is(false)) {
SetRandoInf(RAND_INF_CAN_SWIM, true);
}
// If we're not shuffling swim, we start with it
if (ctx->GetOption(RSK_SHUFFLE_SWIM).Is(false)) {
SetRandoInf(RAND_INF_CAN_SWIM, true);
}
// If we're not shuffling child's wallet, we start with it
if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) {
SetRandoInf(RAND_INF_HAS_WALLET, true);
}
// If we're not shuffling child's wallet, we start with it
if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) {
SetRandoInf(RAND_INF_HAS_WALLET, true);
}
// If we're not shuffling fishing pole, we start with it
if (ctx->GetOption(RSK_SHUFFLE_FISHING_POLE).Is(false)) {
SetRandoInf(RAND_INF_FISHING_POLE_FOUND, true);
}
// If we're not shuffling fishing pole, we start with it
if (ctx->GetOption(RSK_SHUFFLE_FISHING_POLE).Is(false)) {
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
// FiT
if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) {
SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1);
// If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in
// vanilla FiT
if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) {
SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1);
}
}
// Bottle Count
@ -2454,7 +2458,9 @@ void Logic::Reset() {
// Other
AtDay = false;
AtNight = false;
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
if (resetSaveContext) {
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
}
// Events
ShowedMidoSwordAndShield = false;
@ -2518,6 +2524,8 @@ void Logic::Reset() {
Spirit1FSilverRupees = false;
JabuRutoIn1F = false;
CalculatingAvailableChecks = false;
StopPerformanceTimer(PT_LOGIC_RESET);
}
} // namespace Rando

View file

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