mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-22 17:32:19 -05:00
Fix an infinite loop in hints and better comment hint distribution (#4080)
This commit is contained in:
parent
8e520e490c
commit
980b1f1a6e
@ -531,44 +531,40 @@ int32_t getRandomWeight(int32_t totalWeight){
|
||||
}
|
||||
|
||||
static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount, std::vector<HintDistributionSetting> distTable, uint8_t junkWieght, bool addFixed = true){
|
||||
int32_t totalWeight = junkWieght;
|
||||
int32_t totalWeight = junkWieght; //Start with our Junk Weight, the natural chance of a junk hint
|
||||
|
||||
for (HintDistributionSetting setting: distTable){
|
||||
totalWeight += setting.weight;
|
||||
for (HintDistributionSetting setting: distTable){ //Gather the wieghts of each distribution and, if it's the first pass, apply fixed hints
|
||||
totalWeight += setting.weight; //Note that PlaceHints will set weights of distributions to zero if it can't place anything from them
|
||||
if (addFixed){
|
||||
selected[setting.type] += setting.fixed;
|
||||
stoneCount -= setting.fixed * setting.copies;
|
||||
}
|
||||
}
|
||||
int32_t currentWeight = getRandomWeight(totalWeight);
|
||||
while(stoneCount > 0 && totalWeight > 0){
|
||||
int32_t currentWeight = getRandomWeight(totalWeight); //Initialise with the first random weight from 1 to the total.
|
||||
while(stoneCount > 0 && totalWeight > 0){//Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0
|
||||
//and that all weights have been 0'd out for another reason, and skips to placing all junk hints
|
||||
for (uint8_t distribution = 0; distribution < distTable.size(); distribution++){
|
||||
currentWeight -= distTable[distribution].weight;
|
||||
if (currentWeight <= 0){
|
||||
if (distTable[distribution].copies == 0) {
|
||||
// This should only happen if we ran out of locations to place hints of a certain distribution earlier. Skip
|
||||
// to the next distribution.
|
||||
break;
|
||||
}
|
||||
if (stoneCount >= distTable[distribution].copies){
|
||||
selected[distribution] += 1;
|
||||
currentWeight -= distTable[distribution].weight; //go over each distribution, subtracting the weight each time. Once we reach zero or less,
|
||||
if (currentWeight <= 0){ //tell the system to make 1 of that hint, unless not enough stones remain
|
||||
if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0){
|
||||
selected[distribution] += 1; //if we have enough stones, and copies are not zero, assign 1 to this hint type, remove the stones, and break
|
||||
stoneCount -= distTable[distribution].copies;
|
||||
break;
|
||||
} else {
|
||||
totalWeight -= distTable[distribution].weight;
|
||||
distTable[distribution].weight = 0;
|
||||
break; //This leaves the whole for loop
|
||||
} else { //If we don't have the stones, or copies is 0 despite there being the wieght to trigger a hit, temporerally set wieght to zero
|
||||
totalWeight -= distTable[distribution].weight; //Unlike PlaceHint, distTable is passed by value here, making this temporary
|
||||
distTable[distribution].weight = 0; //this is so we can still roll this hint type if more stones free up later
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if there's still weight, then it's junk
|
||||
if (currentWeight > 0){
|
||||
//if there's still weight then it's junk, as the leftover weight is junkWeight
|
||||
if (currentWeight > 0){ //zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case
|
||||
selected[selected.size()-1] += 1;
|
||||
stoneCount -= 1;
|
||||
}
|
||||
currentWeight = getRandomWeight(totalWeight);
|
||||
}
|
||||
//if stones are left, assign junk
|
||||
//if stones are left, assign junk to every remaining stone as a fallback.
|
||||
if (stoneCount > 0){
|
||||
selected[selected.size()-1] += stoneCount;
|
||||
}
|
||||
@ -586,10 +582,11 @@ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints,
|
||||
RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK;
|
||||
|
||||
hintedLocation = CreateRandomHint(hintTypePool, distribution.copies, distribution.type, distribution.name);
|
||||
if (hintedLocation == RC_UNKNOWN_CHECK){ //if hint failed to place
|
||||
if (hintedLocation == RC_UNKNOWN_CHECK){ //if hint failed to place, remove all wieght and copies then return the number of stones to redistribute
|
||||
uint8_t hintsToRemove = (selectedHints[curSlot] - numHint) * distribution.copies;
|
||||
selectedHints[curSlot] = 0;
|
||||
distTable[curSlot].copies = 0;
|
||||
selectedHints[curSlot] = 0; //as distTable is passed by refernce here, these changes stick for the rest of this seed generation
|
||||
distTable[curSlot].copies = 0;//and prevent future distribution from choosing this slot
|
||||
distTable[curSlot].weight = 0;
|
||||
return hintsToRemove;
|
||||
}
|
||||
if(Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()){
|
||||
@ -661,9 +658,8 @@ void CreateStoneHints() {
|
||||
|
||||
while(totalStones != 0){
|
||||
totalStones = PlaceHints(selectedHints, distTable);
|
||||
while (totalStones != 0){
|
||||
if (totalStones != 0){
|
||||
DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight, false);
|
||||
totalStones = PlaceHints(selectedHints, distTable);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user