mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-09-14 17:25:14 -05:00
Rework match ranking to have multi levels of deferral
This commit is contained in:
@@ -2,16 +2,22 @@ namespace PKHeX.Core
|
||||
{
|
||||
public enum EncounterMatchRating
|
||||
{
|
||||
/// <summary> Unused </summary>
|
||||
None,
|
||||
|
||||
/// <summary> Matches all data, no other matches will be better. </summary>
|
||||
Match,
|
||||
|
||||
/// <summary> Matches most data, might have a better match later. </summary>
|
||||
Deferred,
|
||||
|
||||
/// <summary> Matches most data, might have a better match later. Less preferred than <see cref="Deferred"/> due to potentially small errors in secondary data. </summary>
|
||||
DeferredSecondary,
|
||||
|
||||
/// <summary> Matches most data, might have a better match later. Less preferred than <see cref="Deferred"/> due to small errors in secondary data. </summary>
|
||||
DeferredErrors,
|
||||
|
||||
/// <summary> Matches some data, but will likely have a better match later. </summary>
|
||||
PartialMatch,
|
||||
|
||||
/// <summary> Unused </summary>
|
||||
None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,25 +93,25 @@ public override EncounterMatchRating GetMatchRating(PKM pkm)
|
||||
if (pkm is IRibbonSetMark8 m)
|
||||
{
|
||||
if (m.RibbonMarkCurry && (Weather & AreaWeather8.All) == 0)
|
||||
return EncounterMatchRating.Deferred;
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
if (m.RibbonMarkFishing && (Weather & AreaWeather8.Fishing) == 0)
|
||||
return EncounterMatchRating.Deferred;
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
|
||||
// Check if it has a mark and the weather does not permit the mark.
|
||||
// Tree/Fishing slots should be deferred here and are checked later.
|
||||
if (!Weather.IsMarkCompatible(m))
|
||||
return EncounterMatchRating.Deferred;
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
|
||||
// Galar Mine hidden encounters can only be found via Curry or Fishing.
|
||||
if(Location is (30 or 54) && SlotType is AreaSlotType8.HiddenMain && !m.RibbonMarkCurry && !SlotType.CanEncounterViaFishing(Weather))
|
||||
return EncounterMatchRating.PartialMatch;
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
}
|
||||
|
||||
var req = GetRequirement(pkm);
|
||||
return req switch
|
||||
{
|
||||
MustHave when !IsOverworldCorrelationCorrect(pkm) => EncounterMatchRating.Deferred,
|
||||
MustNotHave when IsOverworldCorrelationCorrect(pkm) => EncounterMatchRating.Deferred,
|
||||
MustHave when !IsOverworldCorrelationCorrect(pkm) => EncounterMatchRating.DeferredErrors,
|
||||
MustNotHave when IsOverworldCorrelationCorrect(pkm) => EncounterMatchRating.DeferredErrors,
|
||||
_ => EncounterMatchRating.Match,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -289,15 +289,13 @@ public virtual EncounterMatchRating GetMatchRating(PKM pkm)
|
||||
{
|
||||
if (IsMatchPartial(pkm))
|
||||
return EncounterMatchRating.PartialMatch;
|
||||
if (IsMatchDeferred(pkm))
|
||||
return EncounterMatchRating.Deferred;
|
||||
return EncounterMatchRating.Match;
|
||||
return IsMatchDeferred(pkm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the provided <see cref="pkm"/> might not be the best match, or even a bad match due to minor reasons.
|
||||
/// </summary>
|
||||
protected virtual bool IsMatchDeferred(PKM pkm) => false;
|
||||
protected virtual EncounterMatchRating IsMatchDeferred(PKM pkm) => EncounterMatchRating.Match;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the provided <see cref="pkm"/> is not an exact match due to minor reasons.
|
||||
|
||||
@@ -86,7 +86,7 @@ public override EncounterMatchRating GetMatchRating(PKM pkm)
|
||||
var req = GetRequirement(pkm);
|
||||
bool correlation = IsOverworldCorrelationCorrect(pkm);
|
||||
if ((req == MustHave) != correlation)
|
||||
return EncounterMatchRating.Deferred;
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
|
||||
// Only encounter slots can have these marks; defer for collisions.
|
||||
if (pkm.Species == (int) Core.Species.Shedinja)
|
||||
@@ -94,14 +94,14 @@ public override EncounterMatchRating GetMatchRating(PKM pkm)
|
||||
// Loses Mark on evolution to Shedinja, but not affixed ribbon value.
|
||||
return pkm switch
|
||||
{
|
||||
IRibbonSetMark8 {RibbonMarkCurry: true} => EncounterMatchRating.Deferred,
|
||||
IRibbonSetMark8 {RibbonMarkCurry: true} => EncounterMatchRating.DeferredErrors,
|
||||
PK8 {AffixedRibbon: (int) RibbonIndex.MarkCurry} => EncounterMatchRating.Deferred,
|
||||
_ => EncounterMatchRating.Match
|
||||
};
|
||||
}
|
||||
|
||||
if (pkm is IRibbonSetMark8 m && (m.RibbonMarkCurry || m.RibbonMarkFishing || m.HasWeatherMark()))
|
||||
return EncounterMatchRating.Deferred;
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
|
||||
return EncounterMatchRating.Match;
|
||||
}
|
||||
|
||||
@@ -43,27 +43,32 @@ public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
return base.IsMatchExact(pkm, evo);
|
||||
}
|
||||
|
||||
protected sealed override bool IsMatchDeferred(PKM pkm)
|
||||
protected sealed override EncounterMatchRating IsMatchDeferred(PKM pkm)
|
||||
{
|
||||
var rating = EncounterMatchRating.Match;
|
||||
if (Ability != -1) // Any
|
||||
{
|
||||
bool CanBeHidden() => ((PersonalInfoSWSH) PersonalTable.SWSH.GetFormEntry(Species, Form)).HasHiddenAbility;
|
||||
|
||||
// HA-Only is a strict match. Ability Capsule and Patch can potentially change these.
|
||||
if (Ability == 0 && pkm.AbilityNumber == 4)
|
||||
return !CanBeHidden(); // 0/1
|
||||
if (Ability == 1 && pkm.AbilityNumber != 1)
|
||||
return pkm.AbilityNumber != 4 || !CanBeHidden(); // 0
|
||||
if (Ability == 2 && pkm.AbilityNumber != 2)
|
||||
return pkm.AbilityNumber != 4 || !CanBeHidden(); // 1
|
||||
if (pkm.AbilityNumber == 4)
|
||||
{
|
||||
if (Ability is not 4 && !AbilityVerifier.CanAbilityPatch(8, PersonalTable.SWSH.GetFormEntry(Species, Form).Abilities, pkm.Species))
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
rating = EncounterMatchRating.Deferred;
|
||||
}
|
||||
if (pkm.AbilityNumber != Ability) // Fixed regular ability
|
||||
{
|
||||
if (Ability is 1 or 2 && !AbilityVerifier.CanAbilityCapsule(8, PersonalTable.SWSH.GetFormEntry(Species, Form).Abilities))
|
||||
return EncounterMatchRating.DeferredErrors;
|
||||
rating = EncounterMatchRating.Deferred;
|
||||
}
|
||||
}
|
||||
|
||||
if (pkm is IMemoryOT m && MemoryPermissions.IsMoveKnowMemory(m.OT_Memory) && !Moves.Contains(m.OT_TextVar))
|
||||
return true;
|
||||
return EncounterMatchRating.DeferredSecondary;
|
||||
if (pkm is IMemoryHT h && MemoryPermissions.IsMoveKnowMemory(h.HT_Memory) && !Moves.Contains(h.HT_TextVar))
|
||||
return true;
|
||||
return EncounterMatchRating.DeferredSecondary;
|
||||
|
||||
return base.IsMatchDeferred(pkm);
|
||||
return rating;
|
||||
}
|
||||
|
||||
protected override bool IsMatchPartial(PKM pkm)
|
||||
|
||||
@@ -38,8 +38,8 @@ private static IEnumerable<IEncounterable> GetEncountersMainline(PKM pkm, IReadO
|
||||
if (ctr == 0) yield break;
|
||||
}
|
||||
|
||||
IEncounterable? deferred = null;
|
||||
IEncounterable? partial = null;
|
||||
IEncounterable? cache = null;
|
||||
EncounterMatchRating rating = None;
|
||||
|
||||
// Trades
|
||||
if (pkm.Met_Location == Locations.LinkTrade6NPC)
|
||||
@@ -47,23 +47,19 @@ private static IEnumerable<IEncounterable> GetEncountersMainline(PKM pkm, IReadO
|
||||
foreach (var z in GetValidEncounterTrades(pkm, chain))
|
||||
{
|
||||
var match = z.GetMatchRating(pkm);
|
||||
switch (match)
|
||||
if (match == Match)
|
||||
{
|
||||
case Match: yield return z; ++ctr; break;
|
||||
case Deferred: deferred ??= z; break;
|
||||
case PartialMatch: partial ??= z; break;
|
||||
yield return z;
|
||||
}
|
||||
else if (match < rating)
|
||||
{
|
||||
cache = z;
|
||||
rating = match;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctr != 0)
|
||||
{
|
||||
if (deferred != null)
|
||||
yield return deferred;
|
||||
|
||||
if (partial != null)
|
||||
yield return partial;
|
||||
}
|
||||
|
||||
if (cache != null)
|
||||
yield return cache;
|
||||
yield break;
|
||||
}
|
||||
|
||||
@@ -71,30 +67,33 @@ private static IEnumerable<IEncounterable> GetEncountersMainline(PKM pkm, IReadO
|
||||
foreach (var z in GetValidStaticEncounter(pkm, chain))
|
||||
{
|
||||
var match = z.GetMatchRating(pkm);
|
||||
switch (match)
|
||||
if (match == Match)
|
||||
{
|
||||
case Match: yield return z; break;
|
||||
case Deferred: deferred ??= z; break;
|
||||
case PartialMatch: partial ??= z; break;
|
||||
yield return z;
|
||||
}
|
||||
else if (match < rating)
|
||||
{
|
||||
cache = z;
|
||||
rating = match;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var z in GetValidWildEncounters(pkm, chain))
|
||||
{
|
||||
var match = z.GetMatchRating(pkm);
|
||||
switch (match)
|
||||
if (match == Match)
|
||||
{
|
||||
case Match: yield return z; break;
|
||||
case Deferred: deferred ??= z; break;
|
||||
case PartialMatch: partial ??= z; break;
|
||||
yield return z;
|
||||
}
|
||||
else if (match < rating)
|
||||
{
|
||||
cache = z;
|
||||
rating = match;
|
||||
}
|
||||
}
|
||||
|
||||
if (deferred != null)
|
||||
yield return deferred;
|
||||
|
||||
if (partial != null)
|
||||
yield return partial;
|
||||
if (cache != null)
|
||||
yield return cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +447,7 @@ private static bool IsAbilityCapsuleModified(PKM pkm, IReadOnlyList<int> abiliti
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CanAbilityCapsule(int format, IReadOnlyList<int> abilities)
|
||||
public static bool CanAbilityCapsule(int format, IReadOnlyList<int> abilities)
|
||||
{
|
||||
if (format < 6) // Ability Capsule does not exist
|
||||
return false;
|
||||
|
||||
@@ -173,11 +173,15 @@ private static bool GetCanKnowMove(PKM pkm, int move, int generation, IReadOnlyL
|
||||
return false;
|
||||
for (int i = 1; i <= generation; i++)
|
||||
{
|
||||
var moves = MoveList.GetValidMoves(pkm, version, evos[i], i, types: MoveSourceType.All);
|
||||
var chain = evos[i];
|
||||
if (chain.Count == 0)
|
||||
continue;
|
||||
|
||||
var moves = MoveList.GetValidMoves(pkm, version, chain, i, types: MoveSourceType.All);
|
||||
if (moves.Contains(move))
|
||||
return true;
|
||||
|
||||
if (IsOtherFormMove(pkm, evos[i], move, i, GameVersion.Any, types: MoveSourceType.All))
|
||||
if (IsOtherFormMove(pkm, chain, move, i, GameVersion.Any, types: MoveSourceType.All))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user