mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-03-21 17:48:28 -05:00
Track more move sources
No change in coloration, but will show them for past games such as Egg Moves that it could have learned.
This commit is contained in:
parent
d5bf6e67d5
commit
e45754c830
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using static PKHeX.Core.IndicatedSourceType;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
|
@ -8,16 +9,16 @@ namespace PKHeX.Core;
|
|||
/// </summary>
|
||||
public sealed class LegalMoveInfo
|
||||
{
|
||||
// Use a bool array instead of a HashSet; we have a limited range of moves.
|
||||
// Use a byte array instead of a HashSet; we have a limited range of moves.
|
||||
// This implementation is faster (no hashcode or bucket search) with lower memory overhead (1 byte per move ID).
|
||||
private readonly bool[] AllowedMoves = new bool[(int)Move.MAX_COUNT + 1];
|
||||
private readonly IndicatedSourceType[] AllowedMoves = new IndicatedSourceType[(int)Move.MAX_COUNT + 1];
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the requested <see cref="move"/> is legally able to be learned.
|
||||
/// </summary>
|
||||
/// <param name="move">Move to check if it can be learned</param>
|
||||
/// <returns>True if it can learn the move</returns>
|
||||
public bool CanLearn(ushort move) => AllowedMoves[move];
|
||||
public bool CanLearn(ushort move) => AllowedMoves[move] != None;
|
||||
|
||||
/// <summary>
|
||||
/// Reloads the legality sources to permit the provided legal info.
|
||||
|
|
@ -25,16 +26,95 @@ public sealed class LegalMoveInfo
|
|||
/// <param name="la">Details of analysis, moves to allow</param>
|
||||
public bool ReloadMoves(LegalityAnalysis la)
|
||||
{
|
||||
var rent = ArrayPool<bool>.Shared.Rent(AllowedMoves.Length);
|
||||
var span = rent.AsSpan(0, AllowedMoves.Length);
|
||||
LearnPossible.Get(la.Entity, la.EncounterOriginal, la.Info.EvoChainsAllGens, span);
|
||||
var rentLearn = ArrayPool<bool>.Shared.Rent(AllowedMoves.Length);
|
||||
var spanLearn = rentLearn.AsSpan(0, AllowedMoves.Length);
|
||||
var rentEval = ArrayPool<IndicatedSourceType>.Shared.Rent(spanLearn.Length);
|
||||
var spanEval = rentEval.AsSpan(0, spanLearn.Length);
|
||||
try
|
||||
{
|
||||
LearnPossible.Get(la.Entity, la.EncounterOriginal, la.Info.EvoChainsAllGens, spanLearn);
|
||||
ComputeEval(spanEval, spanLearn, la);
|
||||
if (spanEval.SequenceEqual(AllowedMoves))
|
||||
return false;
|
||||
spanEval.CopyTo(AllowedMoves);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (Array.TrueForAll(AllowedMoves, z => z == None))
|
||||
return false;
|
||||
AllowedMoves.AsSpan().Clear();
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
spanLearn.Clear();
|
||||
spanEval.Clear();
|
||||
ArrayPool<IndicatedSourceType>.Shared.Return(rentEval);
|
||||
ArrayPool<bool>.Shared.Return(rentLearn);
|
||||
}
|
||||
}
|
||||
|
||||
// check prior move-pool to not needlessly refresh the data set
|
||||
bool diff = !span.SequenceEqual(AllowedMoves);
|
||||
if (diff) // keep
|
||||
span.CopyTo(AllowedMoves);
|
||||
span.Clear();
|
||||
ArrayPool<bool>.Shared.Return(rent);
|
||||
return diff;
|
||||
private static void ComputeEval(Span<IndicatedSourceType> type, ReadOnlySpan<bool> learn, LegalityAnalysis la)
|
||||
{
|
||||
for (int i = 0; i < type.Length; i++)
|
||||
type[i] = learn[i] ? Learn : None;
|
||||
|
||||
if (!la.Entity.IsOriginalMovesetDeleted())
|
||||
AddEncounterMoves(type, la.EncounterOriginal);
|
||||
|
||||
type[0] = None; // Move ID 0 is always None
|
||||
}
|
||||
|
||||
private static void AddEncounterMoves(Span<IndicatedSourceType> type, IEncounterTemplate enc)
|
||||
{
|
||||
if (enc is IEncounterEgg egg)
|
||||
{
|
||||
var moves = egg.Learn.GetEggMoves(enc.Species, enc.Form);
|
||||
foreach (var move in moves)
|
||||
type[move] = Egg;
|
||||
}
|
||||
else if (enc is IMoveset {Moves: {HasMoves: true} set})
|
||||
{
|
||||
if (type[set.Move1] == None)
|
||||
type[set.Move1] = Encounter;
|
||||
if (type[set.Move2] == None)
|
||||
type[set.Move2] = Encounter;
|
||||
if (type[set.Move3] == None)
|
||||
type[set.Move3] = Encounter;
|
||||
if (type[set.Move4] == None)
|
||||
type[set.Move4] = Encounter;
|
||||
}
|
||||
else if (enc is ISingleMoveBonus single)
|
||||
{
|
||||
var moves = single.GetMoveBonusPossible();
|
||||
foreach (var move in moves)
|
||||
{
|
||||
if (type[move] == None)
|
||||
type[move] = EncounterSingle;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc is IRelearn { Relearn: {HasMoves: true} relearn})
|
||||
{
|
||||
if (type[relearn.Move1] == None)
|
||||
type[relearn.Move1] = Relearn;
|
||||
if (type[relearn.Move2] == None)
|
||||
type[relearn.Move2] = Relearn;
|
||||
if (type[relearn.Move3] == None)
|
||||
type[relearn.Move3] = Relearn;
|
||||
if (type[relearn.Move4] == None)
|
||||
type[relearn.Move4] = Relearn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum IndicatedSourceType : byte
|
||||
{
|
||||
None = 0,
|
||||
Learn,
|
||||
Egg,
|
||||
Encounter,
|
||||
EncounterSingle,
|
||||
Relearn,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user