Skip to content

Commit

Permalink
Merge pull request #57 from cjohnson57/playthrough-change
Browse files Browse the repository at this point in the history
App: Change to playthrough output and adding retries
  • Loading branch information
gamestabled authored Mar 23, 2021
2 parents 3c3feb4 + 08a13bd commit d0d38b8
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 80 deletions.
124 changes: 87 additions & 37 deletions source/fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ static std::vector<ItemLocation*> GetAccessibleLocations(std::vector<ItemLocatio
Logic::UpdateHelpers();
std::vector<Exit *> exitPool = {&Exits::Root};

//Variables for playthrough
int gsCount = 0;
bool bombchusFound = false;
//Variables for search
std::vector<ItemLocation *> newItemLocations;
bool firstIteration = true;
//If no new items are found, then the next iteration won't provide any new location
Expand All @@ -94,6 +98,8 @@ static std::vector<ItemLocation*> GetAccessibleLocations(std::vector<ItemLocatio
}
newItemLocations.clear();

std::vector<ItemLocation *> sphere;

for (size_t i = 0; i < exitPool.size(); i++) {
Exit* area = exitPool[i];

Expand Down Expand Up @@ -154,15 +160,42 @@ static std::vector<ItemLocation*> GetAccessibleLocations(std::vector<ItemLocatio
newItemLocations.push_back(location); //Add item to cache to be considered in logic next iteration
}

if (playthrough && location->GetPlacedItem().IsPlaythrough() && location->GetPlacedItem().IsAdvancement()) {
playthroughLocations.push_back(location);
//Playthrough stuff
if (playthrough && !playthroughBeatable && location->GetPlacedItem().IsAdvancement()) {
ItemType type = location->GetPlacedItem().GetItemType();
bool bombchus = location->GetPlacedItem().GetName().find("Bombchu") != std::string::npos;
//Don't print Buy locations
if(type != ITEMTYPE_SHOP && type != ITEMTYPE_TOKEN && !bombchus) {
sphere.push_back(location);
}
//Only print first 50 token locations
else if(type == ITEMTYPE_TOKEN && gsCount < 50 && !bombchus) {
sphere.push_back(location);
gsCount++;
}
//Only print first bombchu location found
else if (type != ITEMTYPE_SHOP && type != ITEMTYPE_TOKEN && bombchus && !bombchusFound) {
sphere.push_back(location);
bombchusFound = true;
}
}
//Triforce has been found, seed is beatable, nothing else in this or future spheres matters
else if(playthrough && location->GetPlacedItem().GetName() == "Triforce") {
sphere.clear();
sphere.push_back(location);
playthroughBeatable = true;
}
}
}
}
}

erase_if(exitPool, [](Exit* e){ return e->AllAccountedFor();});

if(playthrough && sphere.size() > 0) {
playthroughLocations.push_back(sphere);
}

}
erase_if(accessibleLocations, [allowedLocations](ItemLocation* loc){
for (ItemLocation* allowedLocation : allowedLocations) {
Expand Down Expand Up @@ -352,43 +385,60 @@ static void RandomizeOwnDungeonItems() {
RandomizeOwnDungeon(Category::cGanonsCastle, GanonsCastle_BossKey, NoItem, NoItem, GanonsCastle_SmallKey, keyCount);
}

void Fill() {
GenerateLocationPool();
GenerateItemPool();
GenerateStartingInventory();
RemoveStartingItemsFromPool();
RandomizeDungeonRewards();
FillExcludedLocations();
RandomizeOwnDungeonItems();

//Place songs first if song shuffle is set to specific locations
if (ShuffleSongs.IsNot(SONGSHUFFLE_ANYWHERE)) {

//Get each song
std::vector<Item> songs = FilterAndEraseFromPool(ItemPool, [](const Item& i) { return i.GetItemType() == ITEMTYPE_SONG;});

//Get each song location
std::vector<ItemLocation*> songLocations = {};
if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) {
songLocations = FilterFromPool(allLocations, [](ItemLocation * loc){ return loc->IsCategory(Category::cSong);});
int Fill() {
int retries = 0;
while(retries < 5) {
GenerateLocationPool();
GenerateItemPool();
GenerateStartingInventory();
RemoveStartingItemsFromPool();
RandomizeDungeonRewards();
FillExcludedLocations();
RandomizeOwnDungeonItems();

//Place songs first if song shuffle is set to specific locations
if (ShuffleSongs.IsNot(SONGSHUFFLE_ANYWHERE)) {

//Get each song
std::vector<Item> songs = FilterAndEraseFromPool(ItemPool, [](const Item& i) { return i.GetItemType() == ITEMTYPE_SONG;});

//Get each song location
std::vector<ItemLocation*> songLocations = {};
if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) {
songLocations = FilterFromPool(allLocations, [](ItemLocation * loc){ return loc->IsCategory(Category::cSong);});

} else if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) {
songLocations = FilterFromPool(allLocations, [](ItemLocation * loc){ return loc->IsCategory(Category::cSongDungeonReward);});
}

} else if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) {
songLocations = FilterFromPool(allLocations, [](ItemLocation * loc){ return loc->IsCategory(Category::cSongDungeonReward);});
AssumedFill(songs, songLocations);
}

AssumedFill(songs, songLocations);
//Then place the rest of the advancement items
std::vector<Item> remainingAdvancementItems = FilterAndEraseFromPool(ItemPool, [](const Item& i) { return i.IsAdvancement();});
AssumedFill(remainingAdvancementItems, allLocations);

//Fast fill for the rest of the pool
std::vector<Item> remainingPool = FilterAndEraseFromPool(ItemPool, [](const Item& i) {return true;});
LogicReset();
FastFill(remainingPool, GetAccessibleLocations(allLocations));

LogicReset();
GeneratePlaythrough();
//Successful placement, produced beatable result
if(playthroughBeatable) {
printf("Done");
return 1;
}
//Unsuccessful placement
if(retries < 4) {
printf("\x1b[9;10HFailed. Retrying... %d", retries+2);
Exits::ResetAllLocations();
LogicReset();
playthroughLocations.clear();
}
retries++;
}

//Then place the rest of the advancement items
std::vector<Item> remainingAdvancementItems = FilterAndEraseFromPool(ItemPool, [](const Item& i) { return i.IsAdvancement();});
AssumedFill(remainingAdvancementItems, allLocations);

//Fast fill for the rest of the pool
std::vector<Item> remainingPool = FilterAndEraseFromPool(ItemPool, [](const Item& i) {return true;});
LogicReset();
FastFill(remainingPool, GetAccessibleLocations(allLocations));

LogicReset();
GeneratePlaythrough();
printf("Done");
//All retries failed
return -1;
}
2 changes: 1 addition & 1 deletion source/fill.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#pragma once

extern void Fill();
extern int Fill();
5 changes: 3 additions & 2 deletions source/item_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ ItemLocation ShadowTemple_FallingSpikesUpperChest = ItemLocation::Ch
ItemLocation ShadowTemple_FallingSpikesSwitchChest = ItemLocation::Chest (0x07, 0x04, "Shadow Temple Falling Spikes Switch Chest", {Category::cShadowTemple, Category::cVanillaSmallKey});
ItemLocation ShadowTemple_InvisibleSpikesChest = ItemLocation::Chest (0x07, 0x09, "Shadow Temple Invisible Spikes Chest", {Category::cShadowTemple,});
ItemLocation ShadowTemple_WindHintChest = ItemLocation::Chest (0x07, 0x15, "Shadow Temple Wind Hint Chest", {Category::cShadowTemple,});
ItemLocation ShadowTemple_AfterWindEnemyChest = ItemLocation::Chest (0x07, 0x08, "Shadow Temple After Wind Enemey Chest", {Category::cShadowTemple,});
ItemLocation ShadowTemple_AfterWindEnemyChest = ItemLocation::Chest (0x07, 0x08, "Shadow Temple After Wind Enemy Chest", {Category::cShadowTemple,});
ItemLocation ShadowTemple_AfterWindHiddenChest = ItemLocation::Chest (0x07, 0x14, "Shadow Temple After Wind Hidden Chest", {Category::cShadowTemple, Category::cVanillaSmallKey});
ItemLocation ShadowTemple_SpikeWallsLeftChest = ItemLocation::Chest (0x07, 0x0A, "Shadow Temple Spike Walls Left Chest", {Category::cShadowTemple,});
ItemLocation ShadowTemple_BossKeyChest = ItemLocation::Chest (0x07, 0x0B, "Shadow Temple Boss Key Chest", {Category::cShadowTemple, Category::cVanillaBossKey});
Expand Down Expand Up @@ -1624,7 +1624,8 @@ std::vector<ItemLocation*> everyPossibleLocation = {};
//set of overrides to write to the patch
std::set<ItemOverride, ItemOverride_Compare> overrides = {};

std::vector<ItemLocation*> playthroughLocations = {};
std::vector<std::vector<ItemLocation*>> playthroughLocations;
bool playthroughBeatable = false;

u16 itemsPlaced = 0;

Expand Down
3 changes: 2 additions & 1 deletion source/item_location.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,8 @@ extern std::vector<ItemLocation *> everyPossibleLocation;
//set of overrides to write to the patch
extern std::set<ItemOverride, ItemOverride_Compare> overrides;

extern std::vector<ItemLocation*> playthroughLocations;
extern std::vector<std::vector<ItemLocation*>> playthroughLocations;
extern bool playthroughBeatable;

extern u16 itemsPlaced;

Expand Down
26 changes: 26 additions & 0 deletions source/location_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2707,4 +2707,30 @@ namespace Exits { //name, scene, hint, events, locations, exits
}
}
}

//Reset exits and clear items from locations
void ResetAllLocations() {
for (Exit* exit : allExits) {
exit->ResetVariables();
//Erase item from every location in this exit
for (ItemLocationPairing& locPair : exit->locations) {
ItemLocation* location = locPair.GetLocation();
location->ResetVariables();
}
}

if(Settings::HasNightStart) {
if(Settings::StartingAge.Is(AGE_CHILD)) {
Exits::Root.nightChild = true;
} else {
Exits::Root.nightAdult = true;
}
} else {
if(Settings::StartingAge.Is(AGE_CHILD)) {
Exits::Root.dayChild = true;
} else {
Exits::Root.dayAdult = true;
}
}
}
}
1 change: 1 addition & 0 deletions source/location_access.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,4 +524,5 @@ namespace Exits {
extern Exit GanonsCastle_Tower;

extern void AccessReset();
extern void ResetAllLocations();
} //namespace Exits
18 changes: 12 additions & 6 deletions source/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,13 +585,19 @@ void GenerateRandomizer() {
unsigned int finalHash = std::hash<std::string>{}(Settings::seed + settingsStr);

int ret = Playthrough::Playthrough_Init(finalHash);
if (ret < 0) {
printf("Error %d with fill. Press Select to exit.\n", ret);
return;
}
if (ret < 0) {
if(ret == -1) { //Failed to generate after 5 tries
printf("\n\nFailed to generate after 5 tries.\nPress Select to exit or B to go back to the menu.\n");
return;
}
else {
printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret);
return;
}
}
printf("\x1b[11;10HWriting Patch...");
if (WritePatch()) {
printf("Done");
if (WritePatch()) {
printf("Done");
if (Settings::PlayOption == PATCH_CONSOLE) {
printf("\x1b[13;10HQuit out using the home menu. Then\n");
printf("\x1b[14;10Henable game patching and launch OoT3D!\n");
Expand Down
57 changes: 30 additions & 27 deletions source/playthrough.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,43 @@
namespace Playthrough {

int Playthrough_Init(u32 seed) {
Random_Init(seed);
Random_Init(seed);

overrides.clear();
ItemReset();
Exits::AccessReset();
overrides.clear();
ItemReset();
Exits::AccessReset();

Settings::UpdateSettings();
Logic::UpdateHelpers();
Fill();
Settings::UpdateSettings();
Logic::UpdateHelpers();

GenerateHash();
int ret = Fill();
if (ret < 0) {
return ret;
}

if (Settings::GenerateSpoilerLog) {
//write logs
printf("\x1b[9;10HWriting Spoiler Log...");
if (SpoilerLog_Write()) {
printf("Done");
} else {
printf("Failed");
}
GenerateHash();

#ifdef ENABLE_DEBUG
printf("\x1b[10;10HWriting Placement Log...");
if (PlacementLog_Write()) {
printf("Done\n");
} else {
printf("Failed\n");
}
#endif
if (Settings::GenerateSpoilerLog) {
//write logs
printf("\x1b[9;10HWriting Spoiler Log...");
if (SpoilerLog_Write()) {
printf("Done");
} else {
playthroughLocations = {};
printf("Failed");
}

return 1;
#ifdef ENABLE_DEBUG
printf("\x1b[10;10HWriting Placement Log...");
if (PlacementLog_Write()) {
printf("Done\n");
} else {
printf("Failed\n");
}
#endif
} else {
playthroughLocations.clear();
playthroughBeatable = false;
}
return 1;
}

//used for generating a lot of seeds at once
Expand Down
19 changes: 13 additions & 6 deletions source/spoiler_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,26 @@ bool SpoilerLog_Write() {

logtxt += "Hash: ";
for (std::string& str : randomizerHash) {
logtxt += str + " ";
logtxt += str + ", ";
}
logtxt.erase(logtxt.length() - 2); //Erase last comma
logtxt += "\n\n";

WriteSettings();

//Write playthrough to spoiler, by accessibility sphere
logtxt += "Playthrough:\n";
for (ItemLocation* location : playthroughLocations) {
logtxt += "\t";
SpoilerLog_SaveLocation(location->GetName(), location->GetPlacedItemName());
logtxt += '\n';
for (uint i = 0; i < playthroughLocations.size(); i++) {
logtxt += "Sphere " + std::to_string(i+1) + ":\n";
//Print all item locations in this sphere
for (ItemLocation* location : playthroughLocations[i]) {
logtxt += "\t";
SpoilerLog_SaveLocation(location->GetName(), location->GetPlacedItemName());
logtxt += '\n';
}
}
playthroughLocations = {};
playthroughLocations.clear();
playthroughBeatable = false;

logtxt += "\nAll Locations:\n";
for (ItemLocation* location : dungeonRewardLocations) {
Expand Down

0 comments on commit d0d38b8

Please sign in to comment.