From f2209ec7fd54131fbb7fe42a5413fc8c8aaef5f0 Mon Sep 17 00:00:00 2001 From: Kurt Date: Fri, 12 Jan 2024 18:58:23 -0800 Subject: [PATCH] Add better handling for specific GO transfers No formarg or bad EC evolution peek -> search for higher species rather than from the bottom. --- PKHeX.Core/Editing/WurmpleUtil.cs | 6 ++ .../Search/EncounterEnumerator8GO.cs | 66 +++++++++++++++++- .../Restrictions/EvolutionRestrictions.cs | 23 ++++++ PKHeX.Core/Legality/Verifiers/PIDVerifier.cs | 10 +-- .../legality/wild/encounter_go_home.pkl | Bin 122360 -> 124796 bytes .../legality/wild/encounter_go_lgpe.pkl | Bin 27248 -> 27712 bytes 6 files changed, 93 insertions(+), 12 deletions(-) diff --git a/PKHeX.Core/Editing/WurmpleUtil.cs b/PKHeX.Core/Editing/WurmpleUtil.cs index 17d5cc95c..06564ae2e 100644 --- a/PKHeX.Core/Editing/WurmpleUtil.cs +++ b/PKHeX.Core/Editing/WurmpleUtil.cs @@ -28,6 +28,12 @@ public static WurmpleEvolution GetWurmpleEvoGroup(ushort species) return (WurmpleEvolution)(wIndex >> 1); // Silcoon, Cascoon } + /// + /// Checks to see if the input species is a Wurmple evolution + /// + /// True if Wurmple evolution, false if not + public static bool IsWurmpleEvo(ushort species) => GetWurmpleEvoGroup(species) != WurmpleEvolution.None; + /// /// Gets the Wurmple for a given Evolution Value /// diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8GO.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8GO.cs index ab7ea3ad6..1952a7781 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8GO.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8GO.cs @@ -13,6 +13,7 @@ public record struct EncounterEnumerator8GO(PKM Entity, EvoCriteria[] Chain) : I private int Index; private int EvoIndex; private int SubIndex; + private SeekMode Mode; private EncounterMatchRating Rating = EncounterMatchRating.MaxNotMatch; public MatchedEncounter Current { get; private set; } private YieldState State; @@ -26,11 +27,19 @@ private enum YieldState : byte { Start, Seek, + SeekForward, + SeekReverse, Slot, Fallback, End, } + public enum SeekMode : byte + { + Forward, + Reverse, + } + public bool MoveNext() { switch (State) @@ -40,12 +49,24 @@ public bool MoveNext() break; if (!EncounterStateUtil.CanBeWildEncounter(Entity)) break; + Mode = GetSeekMode(); + if (Mode == SeekMode.Reverse) + Index = EncountersGO.SlotsGO.Length - 1; State = YieldState.Seek; goto case YieldState.Seek; case YieldState.Seek: - if (!SeekNextArea(EncountersGO.SlotsGO)) + if (Mode == SeekMode.Forward) + { State = YieldState.SeekForward; goto case YieldState.SeekForward; } + State = YieldState.SeekReverse; goto case YieldState.SeekReverse; + case YieldState.SeekForward: + if (!SeekForward(EncountersGO.SlotsGO)) goto case YieldState.Fallback; State = YieldState.Slot; goto case YieldState.Slot; + case YieldState.SeekReverse: + if (!SeekReverse(EncountersGO.SlotsGO)) + goto case YieldState.Fallback; + State = YieldState.Slot; goto case YieldState.Slot; + case YieldState.Slot: var group = EncountersGO.SlotsGO[Index]; if (TryGetNext(group.Slots)) @@ -61,7 +82,7 @@ public bool MoveNext() return false; } - private bool SeekNextArea(TArea[] areas) + private bool SeekForward(TArea[] areas) where TArea : ISpeciesForm { for (; Index < areas.Length; Index++, EvoIndex = 0) @@ -77,6 +98,41 @@ private bool SeekNextArea(TArea[] areas) return false; } + private bool SeekReverse(TArea[] areas) where TArea : ISpeciesForm + { + for (; Index > 0; Index--, EvoIndex = 0) // Only difference -- search in reverse! + { + var area = areas[Index]; + do + { + if (IsCompatible(area, Chain[EvoIndex])) + return true; + } + while (++EvoIndex < Chain.Length); + } + return false; + } + + private readonly SeekMode GetSeekMode() + { + var species = Entity.Species; + if (species is (int)Species.Dudunsparce or (int)Species.Maushold) + { + if (!EvolutionRestrictions.GetIsExpectedEvolveFormEC100(species, Entity.Form, Entity.EncryptionConstant % 100 == 0)) + return SeekMode.Reverse; + } + else if (EvolutionRestrictions.IsFormArgEvolution(species)) + { + if (Entity is IFormArgument { FormArgument: 0 }) + return SeekMode.Reverse; + } + else if (WurmpleUtil.IsWurmpleEvo(species) && !WurmpleUtil.IsWurmpleEvoValid(Entity)) + { + return SeekMode.Reverse; + } + return SeekMode.Forward; + } + private readonly bool IsCompatible(TArea area, EvoCriteria evo) where TArea : ISpeciesForm { if (area.Species != evo.Species) @@ -108,7 +164,11 @@ private bool TryGetNext(TSlot[] slots) Rating = rating; } } - EvoIndex = 0; SubIndex = 0; Index++; + EvoIndex = 0; SubIndex = 0; + if (Mode == SeekMode.Forward) + Index++; + else + Index--; return false; } diff --git a/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs b/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs index a46279e13..f69170edd 100644 --- a/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs @@ -36,6 +36,29 @@ internal static class EvolutionRestrictions _ => NONE, }; + /// + /// Gets the species-form that it will evolve into. + /// + /// + public static (ushort Species, byte Form) GetEvolvedSpeciesFormEC100(ushort species, bool rare) => species switch + { + (ushort)Tandemaus => ((ushort)Maushold, (byte)(rare ? 0 : 1)), + (ushort)Dunsparce => ((ushort)Dudunsparce, (byte)(rare ? 1 : 0)), + _ => throw new ArgumentOutOfRangeException(nameof(species), species, "Incorrect EC%100 species."), + }; + + public static bool GetIsExpectedEvolveFormEC100(ushort species, byte form, bool rare) => species switch + { + (ushort)Maushold => form == (byte)(rare ? 0 : 1), + (ushort)Dudunsparce => form == (byte)(rare ? 1 : 0), + _ => throw new ArgumentOutOfRangeException(nameof(species), species, "Incorrect EC%100 species."), + }; + + public static bool IsFormArgEvolution(ushort species) + { + return species is (int)Runerigus or (int)Wyrdeer or (int)Annihilape or (int)Basculegion or (int)Kingambit or (int)Overqwil; + } + private const ushort NONE = 0; private const ushort EEVEE = ushort.MaxValue; diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs index 18c3c52d9..7da5e2734 100644 --- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs @@ -1,4 +1,3 @@ -using System; using static PKHeX.Core.LegalityCheckStrings; namespace PKHeX.Core; @@ -105,20 +104,13 @@ private static void VerifyEC100(LegalityAnalysis data, ushort encSpecies) // Indicate the evolution for the user. uint evoVal = pk.EncryptionConstant % 100; bool rare = evoVal == 0; - var (species, form) = GetEvolvedSpeciesForm(encSpecies, rare); + var (species, form) = EvolutionRestrictions.GetEvolvedSpeciesFormEC100(encSpecies, rare); var str = GameInfo.Strings; var forms = FormConverter.GetFormList(species, str.Types, str.forms, GameInfo.GenderSymbolASCII, EntityContext.Gen9); var msg = string.Format(L_XRareFormEvo_0_1, forms[form], rare); data.AddLine(GetValid(msg, CheckIdentifier.EC)); } - private static (ushort, int) GetEvolvedSpeciesForm(ushort species, bool rare) => species switch - { - (int)Species.Tandemaus => ((ushort)Species.Maushold, rare ? 0 : 1), - (int)Species.Dunsparce => ((ushort)Species.Dudunsparce, rare ? 1 : 0), - _ => throw new ArgumentOutOfRangeException(nameof(species), species, "Incorrect EC%100 species."), - }; - private static void VerifyEC(LegalityAnalysis data) { var pk = data.Entity; diff --git a/PKHeX.Core/Resources/legality/wild/encounter_go_home.pkl b/PKHeX.Core/Resources/legality/wild/encounter_go_home.pkl index 23196e5483319e642009986b5057c99898a93801..d6c7e865369fa6de7a6f77a8cb300e3a4f2076e8 100644 GIT binary patch delta 7641 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 H32pdq9|bsj diff --git a/PKHeX.Core/Resources/legality/wild/encounter_go_lgpe.pkl b/PKHeX.Core/Resources/legality/wild/encounter_go_lgpe.pkl index d989ce6a4e4ae15fc23b2b754d723850d06a737e..7747d1f07bf49daecdbbad2a71b1d96ab873c521 100644 GIT binary patch delta 1490 zcmb`GO-x*66o%hBKiuKY6bE|g42X0nNZJOGDW#6epGquPT1Or24_K&Di?xY0alwLQ zhJ-~IE}DFeK~ocwvNA+zE{i5&QX5T(F_9+5U}B7h8fU?RY7;f-!e^9`Mp(LdX1;sw zci!`!^L=;i8|(VAl|A$3hnn+A<9=x{Ak7A)=@Mz)CRQqSJ5nSpjYOo2un0Zdcn9;K zGN}Q2VHwt-{XS_JX5kMw7L_iPORE)9|919(>q;qCSuL_qB?-{9L;4=3V~E71nkqzK ztXi6ZHE{2jGO!3WHJE}0h&~`qL86voa2MX$iP?m79VY9f&mpr5J-7y=^;zjwy_9Q^ z<{m_(kt9g$#wkoeVh?MW1?`pIhMFd(1#@uWA^w}$^DzG{QXblq(q&kKg?&<}6)jkW zYx|`@8#SRf`-qfIkqF(7QXKBU;A4yv0*^~e(9llD(9?kcOm*@eQeAWdOWic`1ZJLO zg5W-dQJ8`Si1yF`tU~%}spTN1dZp|ge)4^E`3&cLh{FB2K1_#4NQTL0DUinPa~Om1 z=cWBGNS7d$q01LB^b+x-9N#fa!18hFs}q9*A@YV9|0%U<@)gee zRh&U)gbM?gPt*BpbOQ5d80RPgFm{$HoiiW#K8ad+I{-Py^0V^i&1wJF<-Y$$y<}jI zwK;5#2LId~^$wRb>rCY$4%Y34h^pil!$Vliud~ zByYT|*=N^Aez7ep?_G@!Sj7i(H5&8wR-}CPdXgD(+sH7N+#BHyoqAKZD`w7Dj@b?a zsj%|qgB`KLw!4)x_l8O&?!0B*kG<<1iG5kpSxwCeD`@}7$1hFzs;m{e5X)J1aK)~G zoD&PJ{QWlP3x;p~vvRiwezvOv=44;oq-%FO1?vTYoMpypTmC22vJF+f70V1ax+bx6 zrj+*Vs=`e$LyeV0MhX*bPy7(Iqu5|5UR`n^P+FW$&fIQ2Xl}Ia^GieKtzgWH9B8(k z^+C~}Y47+p97Hf&5OvO*&yq2(sq=v4Yy`cLu8U6jzmtBCwbkGcXK#wZ4v(N)IiAgv(x5ylV`i=`Y&i- BPl*5k delta 1080 zcmZ|OO=uK%7{~G7Om;Jy&DgwcvN68o#Ta8v(-^n9)itj5rMA9wmBdC}nlx@}D3(UZ zAqUH@kb{RHfxn0p4|~W#f=cS&gIEtiJP3*e$svcOlv+@VhebT}AmTT*xz)pmdD&;4 zx0#(?aEkLz_S8?)nsKG!5-AptMuJkR6rL0)lWyU3Sehx93W)g9BpyJ^qyreiMYMh( zC2$sbygvQb)Bkfvy^<7h^TbDio2DxQPB*={0WE(Lj{IdTACD%ca{0G)V0j zMgd(bq$$jyb)|F-u~pI)RIa7~LXFZm5=}G)znSMSf~J-%!7X&ThNP`@iQQ|Zg*J+< zqX{e^&@N?g8y)MV`48E|2A)B(gX2fUbaMQd$?*!kUD8#IZe$3gx@i_8o20vl$B4^* z!o-`U^cL2Ic$@?XeM;Au!P%`$h|z6Q5t#(jZ09}-i1cu82h%2{l{+bbs|bBYvq)hI z$z4(of9;m;?_u!0Quh4kB-+Qyk^h2(Uoyo3UI!`<(j1D1q<_BRJ4n$nt{rBLM`#YA zURK{HJ;&vv6#JSD_A|&a20Bje6XZl9%{k@}`-X34KzcNwO`0Dh;9K775FZv|Cs{d? z8L9p|iev11raVQH!%X*sx#9k1elB@v(}6a}*s&dloWuR=Kufz