Misc tweaks for slot4 level check

This commit is contained in:
Kurt 2024-03-09 13:50:15 -06:00
parent 78fba23eae
commit 6d8504bf82
4 changed files with 37 additions and 26 deletions

View file

@ -161,3 +161,10 @@ public enum SlotType4 : byte
Safari_Good_Rod = 13, Safari_Good_Rod = 13,
Safari_Super_Rod = 14, Safari_Super_Rod = 14,
} }
public static class SlotType4Extensions
{
public static bool IsSafari(this SlotType4 type) => type >= SlotType4.Safari_Grass;
public static bool IsLevelRandDPPt(this SlotType4 type) => type != SlotType4.Grass;
public static bool IsLevelRandHGSS(this SlotType4 type) => type != SlotType4.Grass && !type.IsSafari();
}

View file

@ -148,7 +148,7 @@ public static class MethodJ
/// <summary> /// <summary>
/// Attempts to find a matching seed for the given encounter and constraints for Cute Charm buffered PIDs. /// Attempts to find a matching seed for the given encounter and constraints for Cute Charm buffered PIDs.
/// </summary> /// </summary>
public static bool TryGetMatchCuteCharm<T>(T enc, ReadOnlySpan<uint> seeds, byte nature, byte levelMin, byte levelMax, out uint result) public static bool TryGetMatchCuteCharm<T>(T enc, ReadOnlySpan<uint> seeds, byte nature, byte levelMin, byte levelMax, byte format, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
foreach (uint seed in seeds) foreach (uint seed in seeds)
@ -157,7 +157,7 @@ public static class MethodJ
var reg = GetNature(p0) == nature; var reg = GetNature(p0) == nature;
if (!reg) if (!reg)
continue; continue;
var ctx = new FrameCheckDetails<T>(enc, seed, levelMin, levelMax, 4); var ctx = new FrameCheckDetails<T>(enc, seed, levelMin, levelMax, format);
if (!TryGetMatchCuteCharm(ctx, out result)) if (!TryGetMatchCuteCharm(ctx, out result))
continue; continue;
if (!CheckEncounterActivation(enc, ref result)) if (!CheckEncounterActivation(enc, ref result))
@ -264,12 +264,14 @@ public static class MethodJ
result = default; return false; result = default; return false;
} }
private static bool IsLevelRand<T>(T enc) where T : IEncounterSlot4 => enc.Type.IsLevelRandDPPt();
private static bool IsSlotValidFrom1Skip<T>(FrameCheckDetails<T> ctx, out uint result) private static bool IsSlotValidFrom1Skip<T>(FrameCheckDetails<T> ctx, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2))
{ {
if (IsSlotValid(ctx.Encounter, ctx.Prev3)) if (IsSlotValid(ctx.Encounter, ctx.Prev3))
{ result = ctx.Seed4; return true; } { result = ctx.Seed4; return true; }
@ -286,9 +288,9 @@ public static class MethodJ
private static bool IsSlotValidRegular<T>(in FrameCheckDetails<T> ctx, out uint result) private static bool IsSlotValidRegular<T>(in FrameCheckDetails<T> ctx, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1))
{ {
if (IsSlotValid(ctx.Encounter, ctx.Prev2)) if (IsSlotValid(ctx.Encounter, ctx.Prev2))
{ result = ctx.Seed3; return true; } { result = ctx.Seed3; return true; }
@ -312,7 +314,7 @@ public static class MethodJ
if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel)) if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel))
{ result = default; return false; } { result = default; return false; }
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
// Don't bother evaluating Prev1 for level, as it's always bumped to max after. // Don't bother evaluating Prev1 for level, as it's always bumped to max after.
if (IsSlotValid(ctx.Encounter, ctx.Prev3)) if (IsSlotValid(ctx.Encounter, ctx.Prev3))
@ -330,12 +332,12 @@ public static class MethodJ
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
lead = None; lead = None;
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered
{ result = default; return false; } { result = default; return false; }
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1))
{ {
if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead)) if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead))
{ result = ctx.Seed4; return true; } { result = ctx.Seed4; return true; }
@ -355,12 +357,12 @@ public static class MethodJ
private static bool IsSlotValidStaticMagnetFail<T>(in FrameCheckDetails<T> ctx, out uint result) private static bool IsSlotValidStaticMagnetFail<T>(in FrameCheckDetails<T> ctx, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered
{ result = default; return false; } { result = default; return false; }
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1))
{ {
if (IsSlotValid(ctx.Encounter, ctx.Prev2)) if (IsSlotValid(ctx.Encounter, ctx.Prev2))
{ result = ctx.Seed4; return true; } { result = ctx.Seed4; return true; }

View file

@ -134,7 +134,7 @@ public static class MethodK
/// <summary> /// <summary>
/// Attempts to find a matching seed for the given encounter and constraints for Cute Charm buffered PIDs. /// Attempts to find a matching seed for the given encounter and constraints for Cute Charm buffered PIDs.
/// </summary> /// </summary>
public static bool TryGetMatchCuteCharm<T>(T enc, ReadOnlySpan<uint> seeds, byte nature, byte levelMin, byte levelMax, out uint result) public static bool TryGetMatchCuteCharm<T>(T enc, ReadOnlySpan<uint> seeds, byte nature, byte levelMin, byte levelMax, byte format, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
foreach (uint seed in seeds) foreach (uint seed in seeds)
@ -143,7 +143,7 @@ public static class MethodK
var reg = GetNature(p0) == nature; var reg = GetNature(p0) == nature;
if (!reg) if (!reg)
continue; continue;
var ctx = new FrameCheckDetails<T>(enc, seed, levelMin, levelMax, 4); var ctx = new FrameCheckDetails<T>(enc, seed, levelMin, levelMax, format);
if (!TryGetMatchCuteCharm(ctx, out result)) if (!TryGetMatchCuteCharm(ctx, out result))
continue; continue;
if (CheckEncounterActivationCuteCharm(enc, ref result)) if (CheckEncounterActivationCuteCharm(enc, ref result))
@ -320,12 +320,14 @@ public static class MethodK
result = default; return false; result = default; return false;
} }
private static bool IsLevelRand<T>(T enc) where T : IEncounterSlot4 => enc.Type.IsLevelRandHGSS();
private static bool IsSlotValidFrom1Skip<T>(FrameCheckDetails<T> ctx, out uint result) private static bool IsSlotValidFrom1Skip<T>(FrameCheckDetails<T> ctx, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2))
{ {
if (IsSlotValid(ctx.Encounter, ctx.Prev3)) if (IsSlotValid(ctx.Encounter, ctx.Prev3))
{ result = ctx.Seed4; return true; } { result = ctx.Seed4; return true; }
@ -342,9 +344,9 @@ public static class MethodK
private static bool IsSlotValidRegular<T>(in FrameCheckDetails<T> ctx, out uint result) private static bool IsSlotValidRegular<T>(in FrameCheckDetails<T> ctx, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1))
{ {
if (IsSlotValid(ctx.Encounter, ctx.Prev2)) if (IsSlotValid(ctx.Encounter, ctx.Prev2))
{ result = ctx.Seed3; return true; } { result = ctx.Seed3; return true; }
@ -368,7 +370,7 @@ public static class MethodK
if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel)) if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel))
{ result = default; return false; } { result = default; return false; }
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
// Don't bother evaluating Prev1 for level, as it's always bumped to max after. // Don't bother evaluating Prev1 for level, as it's always bumped to max after.
if (IsSlotValid(ctx.Encounter, ctx.Prev3)) if (IsSlotValid(ctx.Encounter, ctx.Prev3))
@ -391,12 +393,12 @@ public static class MethodK
// -1 Level // -1 Level
// 0 Nature // 0 Nature
lead = None; lead = None;
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered
{ result = default; return false; } { result = default; return false; }
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1))
{ {
if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead)) if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead))
{ result = ctx.Seed4; return true; } { result = ctx.Seed4; return true; }
@ -416,12 +418,12 @@ public static class MethodK
private static bool IsSlotValidStaticMagnetFail<T>(in FrameCheckDetails<T> ctx, out uint result) private static bool IsSlotValidStaticMagnetFail<T>(in FrameCheckDetails<T> ctx, out uint result)
where T : IEncounterSlot4 where T : IEncounterSlot4
{ {
if (!ctx.Encounter.IsFixedLevel()) if (IsLevelRand(ctx.Encounter))
{ {
if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered
{ result = default; return false; } { result = default; return false; }
if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) if (ctx.Encounter.IsFixedLevel() || IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1))
{ {
if (IsSlotValid(ctx.Encounter, ctx.Prev2)) if (IsSlotValid(ctx.Encounter, ctx.Prev2))
{ result = ctx.Seed4; return true; } { result = ctx.Seed4; return true; }

View file

@ -48,7 +48,7 @@ public static class LeadFinder
{ {
// Needs to fetch all possible seeds for IVs. // Needs to fetch all possible seeds for IVs.
// Kinda sucks to do this every encounter, but it's relatively rare -- still good enough perf. // Kinda sucks to do this every encounter, but it's relatively rare -- still good enough perf.
var result = TryGetMatchCuteCharm4(enc, pk, evo, out var seed); var result = TryGetMatchCuteCharm4(enc, pk, evo, pk.Format, out var seed);
if (result) if (result)
return new(seed, LeadRequired.CuteCharm); return new(seed, LeadRequired.CuteCharm);
} }
@ -69,7 +69,7 @@ public static class LeadFinder
return result.IsValid(); return result.IsValid();
} }
private static bool TryGetMatchCuteCharm4<TEnc, TEvo>(TEnc enc, PKM pk, TEvo evo, out uint seed) private static bool TryGetMatchCuteCharm4<TEnc, TEvo>(TEnc enc, PKM pk, TEvo evo, byte format, out uint seed)
where TEnc : IEncounterSlot4 where TEnc : IEncounterSlot4
where TEvo : ILevelRange where TEvo : ILevelRange
{ {
@ -81,8 +81,8 @@ public static class LeadFinder
var nature = (byte)(pk.EncryptionConstant % 25); var nature = (byte)(pk.EncryptionConstant % 25);
var (min, max) = (evo.LevelMin, evo.LevelMax); var (min, max) = (evo.LevelMin, evo.LevelMax);
return pk.HGSS return pk.HGSS
? MethodK.TryGetMatchCuteCharm(enc, seeds, nature, min, max, out seed) ? MethodK.TryGetMatchCuteCharm(enc, seeds, nature, min, max, format, out seed)
: MethodJ.TryGetMatchCuteCharm(enc, seeds, nature, min, max, out seed); : MethodJ.TryGetMatchCuteCharm(enc, seeds, nature, min, max, format, out seed);
} }
private static int GetSeedsIVs(PKM pk, Span<uint> seeds) private static int GetSeedsIVs(PKM pk, Span<uint> seeds)