using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
///
/// Logic for getting valid movesets.
///
public static class MoveSetApplicator
{
///
/// Gets a moveset for the provided data.
///
/// PKM to generate for
/// Full movepool & shuffling
/// 4 moves
public static int[] GetMoveSet(this PKM pk, bool random = false)
{
var la = new LegalityAnalysis(pk);
var moves = la.GetMoveSet(random);
if (random)
return moves;
var clone = pk.Clone();
clone.SetMoves(moves);
clone.SetMaximumPPCurrent(moves);
var newLa = new LegalityAnalysis(clone);
// ReSharper disable once TailRecursiveCall
return newLa.Valid ? moves : GetMoveSet(pk, true);
}
///
/// Gets a moveset for the provided data.
///
/// Precomputed optional
/// Full movepool & shuffling
/// 4 moves
public static int[] GetMoveSet(this LegalityAnalysis la, bool random = false)
{
int[] m = la.GetSuggestedCurrentMoves(random ? MoveSourceType.All : MoveSourceType.Encounter);
var learn = la.GetSuggestedMovesAndRelearn();
if (!m.All(z => learn.Contains(z)))
m = m.Intersect(learn).ToArray();
if (random && !la.pkm.IsEgg)
Util.Shuffle(m.AsSpan());
const int count = 4;
if (m.Length > count)
return m.SliceEnd(m.Length - count);
Array.Resize(ref m, count);
return m;
}
///
/// Fetches based on the provided .
///
/// Pokémon to modify.
/// Encounter the relearn moves should be suggested for. If not provided, will try to detect it via legality analysis.
/// best suited for the current data.
public static IReadOnlyList GetSuggestedRelearnMoves(this PKM pk, IEncounterTemplate? enc = null) => GetSuggestedRelearnMoves(new LegalityAnalysis(pk), enc);
///
/// Fetches based on the provided .
///
/// which contains parsed information pertaining to legality.
/// Encounter the relearn moves should be suggested for. If not provided, will try to detect it via legality analysis.
/// best suited for the current data.
public static IReadOnlyList GetSuggestedRelearnMoves(this LegalityAnalysis legal, IEncounterTemplate? enc = null)
{
enc ??= legal.EncounterOriginal;
var m = legal.GetSuggestedRelearnMovesFromEncounter(enc);
if (m.Any(z => z != 0))
return m;
if (enc is MysteryGift or EncounterEgg)
return m;
if (enc is EncounterSlot6AO {CanDexNav: true} dn)
{
var moves = legal.Info.Moves;
for (int i = 0; i < moves.Length; i++)
{
if (!moves[i].ShouldBeInRelearnMoves())
continue;
var move = legal.pkm.GetMove(i);
if (dn.CanBeDexNavMove(move))
return new[] { move, 0, 0, 0 };
}
}
if (enc is EncounterSlot8b { IsUnderground: true } ug)
{
var moves = legal.Info.Moves;
for (int i = 0; i < moves.Length; i++)
{
if (!moves[i].ShouldBeInRelearnMoves())
continue;
var move = legal.pkm.GetMove(i);
if (ug.CanBeUndergroundMove(move))
return new[] { move, 0, 0, 0 };
}
if (ug.GetBaseEggMove(out int any))
return new[] { any, 0, 0, 0 };
}
var encounter = EncounterSuggestion.GetSuggestedMetInfo(legal.pkm);
if (encounter is IRelearn {Relearn: {Count: > 0} r})
return r;
return m;
}
}
}