private static void SetValuesFromSeedLCRNG(PKM pk, PIDType type, uint seed) { var rng = RNG.LCRNG; var A = rng.Next(seed); var B = rng.Next(A); var skipBetweenPID = type is PIDType.Method_3 or PIDType.Method_3_Unown; if (skipBetweenPID) // VBlank skip between PID rand() [RARE] { B = rng.Next(B); } var swappedPIDHalves = type is >= PIDType.Method_1_Unown and <= PIDType.Method_4_Unown; if (swappedPIDHalves) // switched order of PID halves, "BA.." { pk.PID = (A & 0xFFFF0000) | B >> 16; } else { pk.PID = (B & 0xFFFF0000) | A >> 16; } var C = rng.Next(B); var skipIV1Frame = type is PIDType.Method_2 or PIDType.Method_2_Unown; if (skipIV1Frame) // VBlank skip after PID { C = rng.Next(C); } var D = rng.Next(C); var skipIV2Frame = type is PIDType.Method_4 or PIDType.Method_4_Unown; if (skipIV2Frame) // VBlank skip between IVs { D = rng.Next(D); } Span <int> IVs = stackalloc int[6]; MethodFinder.GetIVsInt32(IVs, C >> 16, D >> 16); if (type == PIDType.Method_1_Roamer) { // Only store lowest 8 bits of IV data; zero out the other bits. IVs[1] &= 7; for (int i = 2; i < 6; i++) { IVs[i] = 0; } } pk.SetIVs(IVs); }
public static IEnumerable <IEncounterable> GetEncounters(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); var deferredPIDIV = new List <IEncounterable>(); var deferredEType = new List <IEncounterable>(); foreach (var z in GenerateRawEncounters4(pkm, info)) { if (!info.PIDIV.Type.IsCompatible4(z, pkm)) { deferredPIDIV.Add(z); } else if (pkm is IGroundTile e && !(z is IGroundTypeTile t ? t.GroundTile.Contains(e.GroundTile) : e.GroundTile == 0)) { deferredEType.Add(z); }
private string GetVerboseLegalityReport() { if (!Parsed) return V189; const string separator = "==="; string[] br = {separator, ""}; var lines = new List<string> {br[1]}; lines.AddRange(br); int rl = lines.Count; var vMoves = Info.Moves; var vRelearn = Info.Relearn; for (int i = 0; i < 4; i++) if (vMoves[i].Valid) lines.Add(string.Format(V191, vMoves[i].Judgement.Description(), i + 1, vMoves[i].Comment)); if (pkm.Format >= 6) for (int i = 0; i < 4; i++) if (vRelearn[i].Valid) lines.Add(string.Format(V192, vRelearn[i].Judgement.Description(), i + 1, vRelearn[i].Comment)); if (rl != lines.Count) // move info added, break for next section lines.Add(br[1]); var outputLines = Parse.Where(chk => chk != null && chk.Valid && chk.Comment != V).OrderBy(chk => chk.Judgement); // Fishy sorted to top lines.AddRange(outputLines.Select(chk => string.Format(V196, chk.Judgement.Description(), chk.Comment))); lines.AddRange(br); lines.Add(string.Format(V195, EncounterName)); var pidiv = Info.PIDIV ?? MethodFinder.Analyze(pkm); if (pidiv != null) { if (!pidiv.NoSeed) lines.Add(string.Format(V248, pidiv.OriginSeed.ToString("X8"))); lines.Add(string.Format(V249, pidiv.Type)); } if (!Valid && Info.InvalidMatches != null) { lines.Add("Other match(es):"); lines.AddRange(Info.InvalidMatches.Select(z => $"{z.Name}: {z.Reason}")); } return GetLegalityReport() + string.Join(Environment.NewLine, lines); }
private static IEnumerable <IEncounterable> GetEncounters3(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); var deferred = new List <IEncounterable>(); foreach (var z in GenerateRawEncounters3(pkm, info)) { if (pkm.Version == (int)GameVersion.CXD) // C/XD { if (z is EncounterSlot w) { var seeds = MethodFinder.GetPokeSpotSeeds(pkm, w.SlotNumber).FirstOrDefault(); info.PIDIV = seeds ?? info.PIDIV; } else if (z is EncounterStaticShadow s) { bool valid = GetIsShadowLockValid(pkm, info, s); if (!valid) { deferred.Add(s); continue; } } } if (info.PIDIV.Type.IsCompatible3(z, pkm)) { yield return(z); } else { deferred.Add(z); } } if (deferred.Count == 0) { yield break; } info.PIDIVMatches = false; foreach (var z in deferred) { yield return(z); } }
private static void SetValuesFromSeedLCRNG(PKM pk, PIDType type, uint seed) { var rng = RNG.LCRNG; var A = rng.Next(seed); var B = rng.Next(A); var pid = (B & 0xFFFF0000) | A >> 16; if (type == PIDType.Method_1_Unown || type == PIDType.Method_2_Unown || type == PIDType.Method_4_Unown) { pk.PID = (pid >> 16) | (pid << 16); // swap halves } else { pk.PID = pid; } var skipIV1Frame = type == PIDType.Method_2 || type == PIDType.Method_2_Unown; if (skipIV1Frame) { B = rng.Next(B); } var C = rng.Next(B); var D = rng.Next(C); var skipIV2Frame = type == PIDType.Method_4 || type == PIDType.Method_4_Unown; if (skipIV2Frame) { D = rng.Next(D); } var IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16); if (type == PIDType.Method_1_Roamer) { IVs[1] &= 7; for (int i = 2; i < 6; i++) { IVs[i] = 0; } } pk.IVs = IVs; }
private static IEnumerable <IEncounterable> GetEncounters3CXD(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); IEncounterable?Partial = null; foreach (var z in GenerateRawEncounters3CXD(pkm)) { if (z is EncounterSlot3PokeSpot w) { var seeds = MethodFinder.GetPokeSpotSeeds(pkm, w.SlotNumber); foreach (var s in seeds) { info.PIDIV = s; break; } } else if (z is EncounterStaticShadow s) { bool valid = GetIsShadowLockValid(pkm, info, s); if (!valid) { Partial ??= s; continue; } } if (info.PIDIV.Type.IsCompatible3(z, pkm)) { yield return(z); } else { Partial ??= z; } } if (Partial == null) { yield break; } info.PIDIVMatches = false; yield return(Partial); }
private static void VerifyFatefulMysteryGift(LegalityAnalysis data, MysteryGift g) { var pkm = data.pkm; if (g is PGF p && p.IsShiny) { var Info = data.Info; Info.PIDIV = MethodFinder.Analyze(pkm); if (Info.PIDIV.Type != PIDType.G5MGShiny && pkm.Egg_Location != 30003) { data.AddLine(GetInvalid(LPIDTypeMismatch, CheckIdentifier.PID)); } } var result = pkm.FatefulEncounter ? GetValid(LFatefulMystery, CheckIdentifier.Fateful) : GetInvalid(LFatefulMysteryMissing, CheckIdentifier.Fateful); data.AddLine(result); }
public static void SetRandomChainShinyPID(PKM pk, uint seed) { // 13 rand bits // 1 3-bit for upper // 1 3-bit for lower uint Next() => (seed = RNG.LCRNG.Next(seed)) >> 16; uint lower = Next() & 7; uint upper = Next() & 7; for (int i = 0; i < 13; i++) { lower |= (Next() & 1) << (3 + i); } upper = ((uint)(lower ^ pk.TID ^ pk.SID) & 0xFFF8) | (upper & 0x7); pk.PID = upper << 16 | lower; pk.IVs = MethodFinder.GetIVsInt32(Next(), Next()); }
private static IEnumerable <IEncounterable> GetEncounters3(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); var deferred = new List <IEncounterable>(); foreach (var z in GenerateRawEncounters3(pkm, info)) { if (pkm.Version == 15) { if (z is EncounterSlot w) { var seeds = MethodFinder.GetPokeSpotSeeds(pkm, w.SlotNumber).FirstOrDefault(); info.PIDIV = seeds ?? info.PIDIV; } else if (ParseSettings.FlagCXDShadowFirstLockMismatch && z is EncounterStaticShadow s && !LockFinder.IsFirstShadowLockValid(s, info.PIDIV)) { deferred.Add(s); continue; } } if (info.PIDIV.Type.IsCompatible3(z, pkm)) { yield return(z); } else { deferred.Add(z); } } if (deferred.Count == 0) { yield break; } info.PIDIVMatches = false; foreach (var z in deferred) { yield return(z); } }
private static bool GetIsShadowLockValid(PKM pkm, LegalInfo info, EncounterStaticShadow s) { if (s.IVs.Count == 0) // not E-Reader { return(LockFinder.IsAllShadowLockValid(s, info.PIDIV, pkm)); } // E-Reader have fixed IVs, and aren't recognized as CXD (no PID-IV correlation). var possible = MethodFinder.GetColoEReaderMatches(pkm.EncryptionConstant); foreach (var poss in possible) { if (!LockFinder.IsAllShadowLockValid(s, poss, pkm)) { continue; } info.PIDIV = poss; return(true); } return(false); }
private static IEnumerable <IEncounterable> GetEncounters4(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); var deferredPIDIV = new List <IEncounterable>(); var deferredEType = new List <IEncounterable>(); foreach (var z in GenerateRawEncounters4(pkm, info)) { if (!info.PIDIV.Type.IsCompatible4(z, pkm)) { deferredPIDIV.Add(z); } else if (pkm.Format <= 6 && !IsEncounterTypeMatch(z, pkm.EncounterType)) { deferredEType.Add(z); } else { yield return(z); } } foreach (var z in deferredEType) { yield return(z); } if (deferredPIDIV.Count == 0) { yield break; } info.PIDIVMatches = false; foreach (var z in deferredPIDIV) { yield return(z); } }
private void VerifyFatefulMysteryGift(LegalityAnalysis data, MysteryGift g) { var pkm = data.pkm; if (g is PGF p && p.IsShiny) { var Info = data.Info; Info.PIDIV = MethodFinder.Analyze(pkm); if (Info.PIDIV.Type != PIDType.G5MGShiny && pkm.Egg_Location != 30003) { data.AddLine(GetInvalid(V411, CheckIdentifier.PID)); } } if (pkm.FatefulEncounter) { data.AddLine(GetValid(V321, CheckIdentifier.Fateful)); } else { data.AddLine(GetInvalid(V322, CheckIdentifier.Fateful)); } }
private static void SetValuesFromSeedBACD(PKM pk, PIDType type, uint seed) { var rng = RNG.LCRNG; bool shiny = type == PIDType.BACD_R_S || type == PIDType.BACD_U_S; uint X = shiny ? rng.Next(seed) : seed; var A = rng.Next(X); var B = rng.Next(A); var C = rng.Next(B); var D = rng.Next(C); if (shiny) { uint PID = (X & 0xFFFF0000) | ((uint)pk.SID ^ (uint)pk.TID ^ X >> 16); PID &= 0xFFFFFFF8; PID |= B >> 16 & 0x7; // lowest 3 bits pk.PID = PID; } else if (type == PIDType.BACD_R_AX || type == PIDType.BACD_U_AX) { uint low = B >> 16; pk.PID = ((A & 0xFFFF0000) ^ (((uint)pk.TID ^ (uint)pk.SID ^ low) << 16)) | low; } else { pk.PID = (A & 0xFFFF0000) | B >> 16; } pk.IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16); bool antishiny = type == PIDType.BACD_R_A || type == PIDType.BACD_U_A; while (antishiny && pk.IsShiny) { pk.PID = unchecked (pk.PID + 1); } }
public static void SetRandomPokeSpotPID(PKM pk, int nature, int gender, int ability, int slot) { while (true) { var seed = Util.Rand32(); if (!MethodFinder.IsPokeSpotActivation(slot, seed, out var _)) { continue; } var rng = RNG.XDRNG; var D = rng.Next(seed); // PID var E = rng.Next(D); // PID pk.PID = (D & 0xFFFF0000) | E >> 16; if (!IsValidCriteria4(pk, nature, ability, gender)) { continue; } pk.SetRandomIVs(); return; } }
private static IEnumerable <IEncounterable> GetEncounters3(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); IEncounterable?Partial = null; foreach (var z in GenerateRawEncounters3(pkm, info)) { if (info.PIDIV.Type.IsCompatible3(z, pkm)) { yield return(z); } else { Partial ??= z; } } if (Partial == null) { yield break; } info.PIDIVMatches = false; yield return(Partial); }
private string GetVerboseLegalityReport() { if (!Parsed || Info == null) { return(L_AnalysisUnavailable); } const string separator = "==="; string[] br = { separator, string.Empty }; var lines = new List <string> { br[1] }; lines.AddRange(br); int rl = lines.Count; var vMoves = Info.Moves; var vRelearn = Info.Relearn; for (int i = 0; i < 4; i++) { var move = vMoves[i]; if (!move.Valid) { continue; } var msg = string.Format(L_F0_M_1_2, move.Rating, i + 1, move.Comment); if (pkm.Format != move.Generation) { msg += $" [Gen{move.Generation}]"; } lines.Add(msg); } if (pkm.Format >= 6) { for (int i = 0; i < 4; i++) { if (vRelearn[i].Valid) { lines.Add(string.Format(L_F0_RM_1_2, vRelearn[i].Rating, i + 1, vRelearn[i].Comment)); } } } if (rl != lines.Count) // move info added, break for next section { lines.Add(br[1]); } var outputLines = Parse.Where(chk => chk?.Valid == true && chk.Comment != L_AValid).OrderBy(chk => chk.Judgement); // Fishy sorted to top lines.AddRange(outputLines.Select(chk => string.Format(L_F0_1, chk.Rating, chk.Comment))); lines.AddRange(br); lines.Add(string.Format(L_FEncounterType_0, EncounterName)); var loc = EncounterLocation; if (!string.IsNullOrEmpty(loc)) { lines.Add(string.Format(L_F0_1, "Location", loc)); } if (pkm.VC) { lines.Add(string.Format(L_F0_1, nameof(GameVersion), Info.Game)); } var pidiv = Info.PIDIV ?? MethodFinder.Analyze(pkm); if (pidiv != null) { if (!pidiv.NoSeed) { lines.Add(string.Format(L_FOriginSeed_0, pidiv.OriginSeed.ToString("X8"))); } lines.Add(string.Format(L_FPIDType_0, pidiv.Type)); } if (!Valid && Info.InvalidMatches != null) { lines.Add("Other match(es):"); lines.AddRange(Info.InvalidMatches.Select(z => $"{z.LongName}: {z.Reason}")); } return(GetLegalityReport() + string.Join(Environment.NewLine, lines)); }
private static IEnumerable <IEncounterable> GetEncounters3(PKM pkm, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pkm); var deferred = new List <IEncounterable>(); foreach (var z in GenerateRawEncounters3(pkm, info)) { if (pkm.Version == (int)GameVersion.CXD) // C/XD { if (z is EncounterSlot w) { var seeds = MethodFinder.GetPokeSpotSeeds(pkm, w.SlotNumber).FirstOrDefault(); info.PIDIV = seeds ?? info.PIDIV; } else if (z is EncounterStaticShadow s) { bool valid = false; if (s.IVs == null) // not ereader { valid = LockFinder.IsAllShadowLockValid(s, info.PIDIV, pkm); } else { var possible = MethodFinder.GetColoEReaderMatches(pkm.EncryptionConstant); foreach (var poss in possible) { if (!LockFinder.IsAllShadowLockValid(s, poss, pkm)) { continue; } valid = true; info.PIDIV = poss; break; } } if (!valid) { deferred.Add(s); continue; } } } if (info.PIDIV.Type.IsCompatible3(z, pkm)) { yield return(z); } else { deferred.Add(z); } } if (deferred.Count == 0) { yield break; } info.PIDIVMatches = false; foreach (var z in deferred) { yield return(z); } }
private string GetVerboseLegalityReport() { if (!Parsed || Info == null) { return(V189); } const string separator = "==="; string[] br = { separator, "" }; var lines = new List <string> { br[1] }; lines.AddRange(br); int rl = lines.Count; var vMoves = Info.Moves; var vRelearn = Info.Relearn; for (int i = 0; i < 4; i++) { if (vMoves[i].Valid) { lines.Add(string.Format(V191, vMoves[i].Rating, i + 1, vMoves[i].Comment)); } } if (pkm.Format >= 6) { for (int i = 0; i < 4; i++) { if (vRelearn[i].Valid) { lines.Add(string.Format(V192, vRelearn[i].Rating, i + 1, vRelearn[i].Comment)); } } } if (rl != lines.Count) // move info added, break for next section { lines.Add(br[1]); } var outputLines = Parse.Where(chk => chk?.Valid == true && chk.Comment != V).OrderBy(chk => chk.Judgement); // Fishy sorted to top lines.AddRange(outputLines.Select(chk => string.Format(V196, chk.Rating, chk.Comment))); lines.AddRange(br); lines.Add(string.Format(V195, EncounterName)); var loc = EncounterLocation; if (!string.IsNullOrEmpty(loc)) { lines.Add(string.Format(V196, "Location", loc)); } if (pkm.VC) { lines.Add(string.Format(V196, nameof(GameVersion), Info.Game)); } var pidiv = Info.PIDIV ?? MethodFinder.Analyze(pkm); if (pidiv != null) { if (!pidiv.NoSeed) { lines.Add(string.Format(V248, pidiv.OriginSeed.ToString("X8"))); } lines.Add(string.Format(V249, pidiv.Type)); } if (!Valid && Info.InvalidMatches != null) { lines.Add("Other match(es):"); lines.AddRange(Info.InvalidMatches.Select(z => $"{z.Name}: {z.Reason}")); } return(GetLegalityReport() + string.Join(Environment.NewLine, lines)); }