Support PLM runs in Gaia and Altair

Apparently some tool gives you moves at level 101 as padded filler. We should support decoding tables with moves learned at level 101 o_O

For known-length searches, we can keep looking to see if data is a match slightly after we find a bugged element. We can do this by expecting a certain percentage of errors in the data, somewhere between 1-2% is probably safe. This lets us find the right data even if the person editing the ROM made some mistakes.
This commit is contained in:
Benjamin Popp
2019-06-07 21:44:45 -05:00
parent a67b2644f6
commit 3ee24604de
3 changed files with 20 additions and 10 deletions

View File

@@ -257,22 +257,32 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
// some searches allow special conditions on the run. For example, we could only be intersted in runs with >100 pointers leading to it.
if (runFilter != null && !runFilter(targetRun)) continue;
// tolerate a few errors in the data. We know what length we're looking for, so if most of the elements match, then
// most likely we're just looking at the right collection but with some user-created bugs.
int errorsToTolerate = bestLength / 80;
int encounterErrors = 0;
int lastGoodLength = 0;
int currentLength = 0;
int currentAddress = targetRun.Start;
bool earlyExit = false;
for (int i = 0; i < bestLength; i++) {
var nextArray = data.GetNextAnchor(currentAddress + 1);
if (DataMatchesElementFormat(data, currentAddress, elementContent, flags, nextArray)) {
currentLength++;
currentAddress += elementLength;
bool match = DataMatchesElementFormat(data, currentAddress, elementContent, flags, nextArray);
currentLength++;
currentAddress += elementLength;
if (match) {
lastGoodLength = currentLength;
} else {
// as long as this array is at least 80% of the passed in array, we're fine and can say that these are matched.
// (the other one might have bad data at the end that needs to be removed) (example: see Gaia)
earlyExit = bestLength * .8 > currentLength;
break;
encounterErrors++;
if (encounterErrors > errorsToTolerate) {
// as long as this array is at least 80% of the passed in array, we're fine and can say that these are matched.
// (the other one might have bad data at the end that needs to be removed) (example: see Gaia)
earlyExit = bestLength * .8 > lastGoodLength;
break;
}
}
}
currentLength = lastGoodLength;
if (!earlyExit) {
var dataEmpty = Enumerable.Range(targetRun.Start, currentLength * elementLength).Select(i => data[i]).All(d => d == 0xFF || d == 0x00);

View File

@@ -39,7 +39,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
}
// validate value
var (level, move) = SplitToken(value);
if (level > 100 || level < 1) break;
if (level > 101 || level < 1) break;
if (move > this.cachedMovenames.Count) break;
}
}

View File

@@ -36,7 +36,7 @@ namespace HavenSoft.HexManiac.Tests {
var address = model.GetAddressFromAnchor(noChange, -1, EggMoveRun.PokemonNameTable);
var run = (ArrayRun)model.GetNextAnchor(address);
if (game.Contains("Gaia")) Assert.Equal(914, run.ElementCount);
if (game.Contains("Gaia")) Assert.Equal(925, run.ElementCount);
else Assert.Equal(412, run.ElementCount);
}