Misc fixes

This commit is contained in:
Kurt
2023-07-06 19:41:27 -07:00
parent 30df059544
commit 41693b0142
17 changed files with 94 additions and 60 deletions

View File

@@ -39,7 +39,7 @@ public bool IsBallValid(Ball ball, ushort currentSpecies)
protected override PKM GetBlank() => OriginFormat switch
{
PogoImportFormat.PK7 => new PK8(),
PogoImportFormat.PK7 => new PK9(),
PogoImportFormat.PB7 => new PB7(),
PogoImportFormat.PK8 => new PK8(),
PogoImportFormat.PA8 => new PA8(),

View File

@@ -57,6 +57,9 @@ public IEnumerable<IEncounterable> GetEncounters(PKM pk, EvoCriteria[] chain, Le
if (area.Species != evo.Species)
continue;
if (area.Form != evo.Form && !FormInfo.IsFormChangeable(area.Species, area.Form, evo.Form, EntityContext.Gen8, pk.Context))
continue;
var slots = area.GetMatchingSlots(pk, evo);
foreach (var z in slots)
{

View File

@@ -44,12 +44,12 @@ private static bool IsValidEvolution(PKM pk, EvolutionHistory history, IEncounte
return true; // never evolved
var current = history.Get(pk.Context);
if (!EvolutionUtil.Contains(current, curSpecies))
if (!EvolutionHistory.HasVisited(current, curSpecies))
return false; // Can't exist as current species
// Double check that our encounter was able to exist as the encounter species.
var original = history.Get(enc.Context);
if (!EvolutionUtil.Contains(original, encSpecies))
if (!EvolutionHistory.HasVisited(original, encSpecies))
return false;
// Bigender->Fixed (non-Genderless) destination species, accounting for PID-Gender relationship

View File

@@ -254,5 +254,16 @@ public bool TryDevolve(ISpeciesForm head, PKM pk, byte currentMaxLevel, byte lev
=> Tree.Reverse.TryDevolve(head, pk, currentMaxLevel, levelMin, skipChecks, out result);
public bool TryEvolve(ISpeciesForm head, ISpeciesForm next, PKM pk, byte currentMaxLevel, byte levelMin, bool skipChecks, out EvoCriteria result)
=> Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result);
{
var b = Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result);
return b && !IsEvolutionBanned(head);
}
// Unreleased Item
private static bool IsEvolutionBanned(in ISpeciesForm head) => head.Species switch
{
(int)Species.Slowpoke => head.Form != 1,
(int)Species.Slowbro => head.Form != 2,
_ => false,
};
}

View File

@@ -83,16 +83,6 @@ public static int IndexOf(Span<EvoCriteria> result, ushort species)
return -1;
}
public static bool Contains(ReadOnlySpan<EvoCriteria> result, ushort species)
{
foreach (ref readonly var z in result)
{
if (z.Species == species)
return true;
}
return false;
}
/// <summary>
/// Revises the <see cref="result"/> to account for a new maximum <see cref="level"/>.
/// </summary>

View File

@@ -238,7 +238,7 @@ public int GetLevelLearnMove(ushort move)
return Levels[index];
}
public ReadOnlySpan<ushort> GetBaseEggMoves(int level)
public ReadOnlySpan<ushort> GetBaseEggMoves(byte level)
{
// Count moves <= level
var count = 0;

View File

@@ -21,9 +21,9 @@ namespace PKHeX.Core;
public readonly ReadOnlySpan<ushort> Moves;
/// <summary> Level the egg originated at. </summary>
public readonly int Level;
public readonly byte Level;
public BreedInfo(Span<T> actual, Span<byte> possible, Learnset learnset, ReadOnlySpan<ushort> moves, int level)
public BreedInfo(Span<T> actual, Span<byte> possible, Learnset learnset, ReadOnlySpan<ushort> moves, byte level)
{
Actual = actual;
Possible = possible;

View File

@@ -85,6 +85,34 @@ public static bool IsMatchTeraTypePersonalAnyForm(in ushort species, in byte ori
return false;
}
private static bool IsMatchTeraTypeImport(PersonalInfo9SV pi, in byte original)
{
var import = TeraTypeUtil.GetTeraTypeImport(pi.Type1, pi.Type2);
return (MoveType)original == import;
}
public static bool IsMatchTeraTypePersonalImport(in ushort species, in byte form, in byte original)
{
var pi = PersonalTable.SV[species, form];
return IsMatchTeraTypeImport(pi, original);
}
public static bool IsMatchTeraTypePersonalAnyFormImport(in ushort species, in byte original)
{
var pt = PersonalTable.SV;
var pi = pt.GetFormEntry(species, 0);
if (pi.IsPresentInGame && IsMatchTeraTypeImport(pi, original))
return true;
var fc = pi.FormCount;
for (byte form = 1; form < fc; form++)
{
pi = pt.GetFormEntry(species, form);
if (pi.IsPresentInGame && IsMatchTeraTypeImport(pi, original))
return true;
}
return false;
}
public static byte GetTeraTypeFromPersonal(in ushort species, in byte form, in ulong pivot)
{
var pi = PersonalTable.SV[species, form];

View File

@@ -107,7 +107,7 @@ private static bool GetCatchRateMatchesPreEvolution(PK1 pk, byte catch_rate)
return true;
}
if (!EvolutionTree.Evolves1.Reverse.TryDevolve(head, pk, max, 2, false, out var next))
if (!EvolutionGroup1.Instance.TryDevolve(head, pk, max, 2, false, out var next))
break;
head = next;
max = next.LevelMax;

View File

@@ -110,12 +110,10 @@ public static bool IsFormChangeable(ushort species, byte oldForm, byte newForm,
}
if (species is (int)Deerling or (int)Sawsbuck)
{
return origin switch
{
EntityContext.Gen5 => true,
EntityContext.Gen9 => true,
_ => false, // todo home sv
};
if (origin == EntityContext.Gen5)
return true; // B/W
if (current.Generation() >= 8)
return true; // Via S/V
}
return false;
}

View File

@@ -35,7 +35,13 @@ private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f)
=> GetValid(LFormArgumentValid),
Furfrou when pk.Form != 0 => !IsFormArgumentDayCounterValid(f, 5, true) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid),
Hoopa when pk.Form == 1 => !IsFormArgumentDayCounterValid(f, 3) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid),
Hoopa when pk.Form == 1 => data.Info.EvoChainsAllGens switch
{
{ HasVisitedGen9: true } when arg == 0 => GetValid(LFormArgumentValid), // Value not applied on form change, and reset when reverted.
{ HasVisitedGen6: true } when IsFormArgumentDayCounterValid(f, 3) => GetValid(LFormArgumentValid), // 0-3 via OR/AS
{ HasVisitedGen7: true } when IsFormArgumentDayCounterValid(f, 3) && f.FormArgumentRemain != 0 => GetValid(LFormArgumentValid), // 1-3 via Gen7
_ => GetInvalid(LFormArgumentInvalid),
},
Yamask when pk.Form == 1 => arg switch
{
not 0 when pk.IsEgg => GetInvalid(LFormArgumentNotAllowed),

View File

@@ -63,11 +63,14 @@ private static void CheckLearnset(LegalityAnalysis data, PA8 pa)
if (moveCount == 4)
return;
// Flag move slots that are empty.
if (pa.Tracker != 0 || !ParseSettings.IgnoreTransferIfNoTracker)
return; // Can delete moves in PA8 moveset via HOME.
// Get the bare minimum moveset.
Span<ushort> expect = stackalloc ushort[4];
var minMoveCount = LoadBareMinimumMoveset(data.EncounterMatch, data.Info.EvoChainsAllGens, pa, expect);
// Flag move slots that are empty.
var moves = data.Info.Moves;
for (int i = moveCount; i < minMoveCount; i++)
{

View File

@@ -192,20 +192,20 @@ private void VerifySVStats(LegalityAnalysis data, PK9 pk9)
public static int GetTeraImportMatch(ReadOnlySpan<EvoCriteria> evos, MoveType actual, IEncounterTemplate enc)
{
// Sanitize out Form here for Arceus/Silvally -- rewrite via evotree later.
if (evos.Length == 0 || evos[0].Species is (int)Species.Arceus or (int)Species.Silvally)
// Sanitize out Form here for Arceus
if (evos.Length == 0 || evos[0].Species is (int)Species.Arceus)
return actual == MoveType.Normal ? 0 : -1;
for (int i = evos.Length - 1; i >= 0; i--)
{
var evo = evos[i];
if (FormInfo.IsFormChangeable(evo.Species, enc.Form, evo.Form, enc.Context, EntityContext.Gen9))
{
if (Tera9RNG.IsMatchTeraTypePersonalAnyForm(evo.Species, (byte)actual))
if (Tera9RNG.IsMatchTeraTypePersonalAnyFormImport(evo.Species, (byte)actual))
return i;
}
else
{
if (Tera9RNG.IsMatchTeraTypePersonal(evo.Species, evo.Form, (byte)actual))
if (Tera9RNG.IsMatchTeraTypePersonalImport(evo.Species, evo.Form, (byte)actual))
return i;
}
}

View File

@@ -399,6 +399,10 @@ private void EnsureScaleSizeExists()
{
// Fix for PLA static encounter Alphas with 127 scale.
Core.HeightScalar = Core.WeightScalar = 255;
if (DataPA8 is { Scale: not 255 } pa8)
pa8.Scale = 255;
if (DataPK9 is { Scale: not 255 } pk9)
pk9.Scale = 255;
return;
}
if (GO_HOME || FirstScaleData is IScaledSize3)

View File

@@ -150,7 +150,13 @@ public static bool IsConvertibleToFormat(PKM pk, int format)
// Every format can eventually feed into HOME. Don't bother checking current type.
var type = PKH.GetType(destType);
if (type is not HomeGameDataFormat.None)
return HOME.GetEntity(pk).ConvertToPKM(type);
{
var pkh = HOME.GetEntity(pk);
var converted = pkh.ConvertToPKM(type);
if (converted is null)
result = IncompatibleSpecies;
return converted;
}
result = NoTransferRoute;
return null;

View File

@@ -1,5 +1,3 @@
using System.Linq;
using System.Reflection;
using FluentAssertions;
using Xunit;
@@ -7,23 +5,24 @@ namespace PKHeX.Core.Tests.Legality;
public class LegalityData
{
[Fact]
public void EvolutionsOrdered() // feebas, see issue #2394
[Theory]
[InlineData(Species.Feebas, 0)] // feebas, see issue #2394
[InlineData(Species.Crabrawler, 0)] // SV Crabrawler added a second, UseItem evolution method. Need to be sure it's before the more restrictive level-up method.
public void EvolutionsOrdered(Species species, byte form)
{
int count = 0;
var trees = typeof(EvolutionTree)
.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
.Select(z => z.GetValue(typeof(EvolutionTree)))
.OfType<EvolutionTree>();
foreach (var tree in trees)
for (var context = EntityContext.None + 1; context < EntityContext.MaxInvalid; context++)
{
var feebas = tree.Forward.GetForward((int)Species.Feebas, 0).Span;
if (feebas.Length <= 1)
if (!context.IsValid())
continue;
var t1 = feebas[0].Method;
var t2 = feebas[1].Method;
var tree = EvolutionTree.GetEvolutionTree(context);
var possible = tree.Forward.GetForward((ushort)species, form).Span;
if (possible.Length <= 1)
continue;
var t1 = possible[0].Method;
var t2 = possible[1].Method;
t1.IsLevelUpRequired().Should().BeFalse();
t2.IsLevelUpRequired().Should().BeTrue();
@@ -31,20 +30,6 @@ public class LegalityData
count++;
}
count.Should().NotBe(0);
}
[Fact]
public void EvolutionsOrderedSV()
{
// SV Crabrawler added a second, UseItem evolution method. Need to be sure it's before the more restrictive level-up method.
var tree = EvolutionTree.Evolves9;
var crab = tree.Forward.GetForward((int)Species.Crabrawler, 0).Span;
var t1 = crab[0].Method;
var t2 = crab[1].Method;
t1.IsLevelUpRequired().Should().BeFalse();
t2.IsLevelUpRequired().Should().BeTrue();
count.Should().BeGreaterThan(0);
}
}