Add gen4 lead frame finding variants

can use level call or not at all (fixed slot)
still untested, assumed same call order as gen3.
This commit is contained in:
Kurt 2017-12-01 21:23:37 -08:00
parent 48242109fd
commit 40ec87fc9d
3 changed files with 114 additions and 21 deletions

View file

@ -2,16 +2,29 @@
{ {
public class Frame public class Frame
{ {
/// <summary>
/// Ending seed value for the frame (prior to nature call).
/// </summary>
public readonly uint Seed; public readonly uint Seed;
public readonly LeadRequired Lead; public readonly LeadRequired Lead;
private readonly FrameType FrameType; private readonly FrameType FrameType;
private readonly RNG RNG; private readonly RNG RNG;
public uint RandLevel { get; set; } /// <summary>
public uint RandESV { get; set; } /// Starting seed for the frame (to generate the frame).
/// </summary>
public uint OriginSeed { get; set; } public uint OriginSeed { get; set; }
/// <summary>
/// RNG Call Value for the Level Calc
/// </summary>
public uint RandLevel { get; set; }
/// <summary>
/// RNG Call Value for the Encounter Slot Calc
/// </summary>
public uint RandESV { get; set; }
public bool LevelSlotModified => Lead.IsLevelOrSlotModified(); public bool LevelSlotModified => Lead.IsLevelOrSlotModified();
public Frame(uint seed, FrameType type, RNG rng, LeadRequired lead) public Frame(uint seed, FrameType type, RNG rng, LeadRequired lead)
@ -30,6 +43,13 @@
/// <returns>Slot number for this frame & lead value.</returns> /// <returns>Slot number for this frame & lead value.</returns>
public bool IsSlotCompatibile(EncounterSlot slot, PKM pkm) public bool IsSlotCompatibile(EncounterSlot slot, PKM pkm)
{ {
bool usesLevel = !slot.FixedLevel;
if (FrameType != FrameType.MethodH)
{
if (Lead.HasFlag(LeadRequired.UsesLevelCall) != usesLevel)
return false;
}
// Level is before Nature, but usually isn't varied. Check ESV calc first. // Level is before Nature, but usually isn't varied. Check ESV calc first.
int s = GetSlot(slot); int s = GetSlot(slot);
if (s != slot.SlotNumber) if (s != slot.SlotNumber)

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core namespace PKHeX.Core
{ {
@ -13,10 +14,10 @@ namespace PKHeX.Core
public static IEnumerable<Frame> GetFrames(PIDIV pidiv, PKM pk) public static IEnumerable<Frame> GetFrames(PIDIV pidiv, PKM pk)
{ {
if (pidiv.RNG == null) if (pidiv.RNG == null)
yield break; return Enumerable.Empty<Frame>();
FrameGenerator info = new FrameGenerator(pidiv, pk); FrameGenerator info = new FrameGenerator(pidiv, pk);
if (info.FrameType == FrameType.None) if (info.FrameType == FrameType.None)
yield break; return Enumerable.Empty<Frame>();
info.Nature = pk.EncryptionConstant % 25; info.Nature = pk.EncryptionConstant % 25;
@ -30,8 +31,9 @@ namespace PKHeX.Core
: FilterNatureSync(seeds, pidiv, info); : FilterNatureSync(seeds, pidiv, info);
var refined = RefineFrames(frames, info); var refined = RefineFrames(frames, info);
foreach (var z in refined) if (pk.Gen4 && pidiv.Type == PIDType.CuteCharm) // only permit cute charm successful frames
yield return z; return refined.Where(z => (z.Lead & ~LeadRequired.UsesLevelCall) == LeadRequired.CuteCharm);
return refined;
} }
private static IEnumerable<Frame> RefineFrames(IEnumerable<Frame> frames, FrameGenerator info) private static IEnumerable<Frame> RefineFrames(IEnumerable<Frame> frames, FrameGenerator info)
@ -105,6 +107,8 @@ namespace PKHeX.Core
lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail; lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
yield return info.GetFrame(prev2, lead, p2, p1, prev3); yield return info.GetFrame(prev2, lead, p2, p1, prev3);
} }
if (f.Lead == LeadRequired.CuteCharm)
yield break;
// Pressure, Hustle, Vital Spirit = Force Maximum Level from slot // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
// -2 ESV // -2 ESV
@ -149,10 +153,16 @@ namespace PKHeX.Core
// Current Seed of the frame is the ESV. // Current Seed of the frame is the ESV.
var rand = f.Seed >> 16; var rand = f.Seed >> 16;
f.RandESV = rand; f.RandESV = rand;
f.RandLevel = rand; f.RandLevel = rand; // unused
f.OriginSeed = info.RNG.Prev(f.Seed); f.OriginSeed = info.RNG.Prev(f.Seed);
yield return f; yield return f;
// Create a copy for level; shift ESV and origin back
var esv = f.OriginSeed;
var origin = info.RNG.Prev(f.OriginSeed);
var withLevel = info.GetFrame(f.Seed, f.Lead | LeadRequired.UsesLevelCall, esv, f.RandLevel, origin);
yield return withLevel;
if (f.Lead != LeadRequired.None) if (f.Lead != LeadRequired.None)
continue; continue;
@ -161,20 +171,82 @@ namespace PKHeX.Core
} }
foreach (var f in list) foreach (var f in list)
{ {
// Level Modifiers between ESV and Nature var leadframes = GenerateLeadSpecificFrames4(f, info);
var prev = info.RNG.Prev(f.Seed); foreach (var frame in leadframes)
var p3 = info.RNG.Prev(prev); yield return frame;
var p16 = prev >> 16;
yield return info.GetFrame(prev, LeadRequired.IntimidateKeenEye, p16, p3);
yield return info.GetFrame(prev, LeadRequired.PressureHustleSpirit, p16, p3);
// Slot Modifiers before ESV
var force = (info.DPPt ? p16 >> 15 : p16 & 1) == 1;
var rand = f.Seed >> 16;
yield return info.GetFrame(prev, force ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail, rand, p3);
} }
} }
private static IEnumerable<Frame> GenerateLeadSpecificFrames4(Frame f, FrameGenerator info)
{
LeadRequired lead;
var prev0 = f.Seed; // 0
var prev1 = info.RNG.Prev(f.Seed); // -1
var prev2 = info.RNG.Prev(prev1); // -2
var prev3 = info.RNG.Prev(prev2); // -3
// Rand call raw values
var p0 = prev0 >> 16;
var p1 = prev1 >> 16;
var p2 = prev2 >> 16;
// Cute Charm
// -2 ESV
// -1 Level (Optional)
// 0 CC Proc (Random() % 3 != 0)
// 1 Nature
if (info.Gendered)
{
bool cc = p0 % 3 != 0;
if (f.Lead == LeadRequired.CuteCharm) // 100% required for frame base
{
if (!cc) yield break;
yield return info.GetFrame(prev2, LeadRequired.CuteCharm, p1, p1, prev2);
yield return info.GetFrame(prev2, LeadRequired.CuteCharm | LeadRequired.UsesLevelCall, p2, p1, prev3);
yield break;
}
lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
yield return info.GetFrame(prev2, lead, p1, p1, prev2);
yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3);
}
if (f.Lead == LeadRequired.CuteCharm)
yield break;
// Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
// -2 ESV
// -1 Level (Optional)
// 0 LevelMax proc (Random() & 1)
// 1 Nature
bool max = p0 % 2 == 1;
lead = max ? LeadRequired.PressureHustleSpirit : LeadRequired.PressureHustleSpiritFail;
yield return info.GetFrame(prev2, lead, p1, p1, prev2);
yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3);
// Keen Eye, Intimidate
// -2 ESV
// -1 Level (Optional)
// 0 Level Adequate Check !(Random() % 2 == 1) rejects -- rand%2==1 is adequate
// 1 Nature
// Note: if this check fails, the encounter generation routine is aborted.
if (max) // same result as above, no need to recalculate
{
lead = LeadRequired.IntimidateKeenEye;
yield return info.GetFrame(prev2, lead, p1, p1, prev2);
yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3);
}
// Static or Magnet Pull
// -2 SlotProc (Random % 2 == 0)
// -1 ESV (select slot)
// 0 Level (Optional)
// 1 Nature
var force1 = (info.DPPt ? p1 >> 15 : p1 & 1) == 1;
lead = force1 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail;
yield return info.GetFrame(prev2, lead, p0, p0, prev3);
var force2 = (info.DPPt ? p2 >> 15 : p2 & 1) == 1;
lead = (force2 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail) | LeadRequired.UsesLevelCall;
yield return info.GetFrame(prev2, lead, p1, p0, prev3);
}
/// <summary> /// <summary>
/// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern. /// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern.

View file

@ -17,7 +17,8 @@ namespace PKHeX.Core
PressureHustleSpirit = 1 << 4, PressureHustleSpirit = 1 << 4,
SuctionCups = 1 << 5, SuctionCups = 1 << 5,
NoLevelCall = 1 << 6, // Compatibility Flags
UsesLevelCall = 1 << 6,
Fail = 1 << 7, Fail = 1 << 7,
CuteCharmFail = CuteCharm | Fail, CuteCharmFail = CuteCharm | Fail,
@ -25,7 +26,7 @@ namespace PKHeX.Core
StaticMagnetFail = StaticMagnet | Fail, StaticMagnetFail = StaticMagnet | Fail,
PressureHustleSpiritFail = PressureHustleSpirit | Fail, PressureHustleSpiritFail = PressureHustleSpirit | Fail,
AllFlags = NoLevelCall | Fail, AllFlags = UsesLevelCall | Fail,
NoFlags = ~AllFlags, NoFlags = ~AllFlags,
} }