2017-05-28 04:17:53 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using static PKHeX . Core . LegalityCheckStrings ;
2020-11-27 20:00:49 +00:00
using static PKHeX . Core . LegalityAnalyzers ;
2017-05-28 04:17:53 +00:00
namespace PKHeX.Core
{
2017-10-24 06:12:58 +00:00
/// <summary>
/// Logic to verify the current <see cref="PKM.RelearnMoves"/>.
/// </summary>
2017-05-28 04:17:53 +00:00
public static class VerifyRelearnMoves
{
2020-11-07 20:25:15 +00:00
public static CheckResult [ ] VerifyRelearn ( PKM pkm , IEncounterable enc )
{
if ( enc . Generation < 6 | | ( pkm is IBattleVersion v & & v . BattleVersion ! = 0 ) )
return VerifyRelearnNone ( pkm ) ;
return enc switch
{
IRelearn s when s . Relearn . Count > 0 = > VerifyRelearnSpecifiedMoveset ( pkm , s . Relearn ) ,
EncounterEgg e = > VerifyRelearnEggBase ( pkm , e ) ,
EncounterSlot6AO z when pkm . RelearnMove1 ! = 0 & & z . CanDexNav = > VerifyRelearnDexNav ( pkm ) ,
_ = > VerifyRelearnNone ( pkm )
} ;
}
2018-12-28 04:24:24 +00:00
2020-11-07 20:25:15 +00:00
public static IReadOnlyList < int > GetSuggestedRelearn ( PKM pkm , IEncounterable enc , CheckResult [ ] relearn )
2017-05-28 04:17:53 +00:00
{
2020-11-07 20:25:15 +00:00
if ( enc . Generation < 6 | | ( pkm is IBattleVersion v & & v . BattleVersion ! = 0 ) )
return Array . Empty < int > ( ) ;
2017-05-28 04:17:53 +00:00
2020-11-07 20:25:15 +00:00
return enc switch
2018-01-26 17:19:20 +00:00
{
2020-11-07 20:25:15 +00:00
IRelearn s when s . Relearn . Count > 0 = > s . Relearn ,
EncounterEgg e = > MoveList . GetBaseEggMoves ( pkm , e . Species , e . Form , e . Version , e . Level ) ,
EncounterSlot6AO z when pkm . RelearnMove1 ! = 0 & & z . CanDexNav = > relearn . All ( r = > r . Valid ) ? pkm . RelearnMoves : Array . Empty < int > ( ) ,
_ = > Array . Empty < int > ( ) ,
2019-10-08 01:40:09 +00:00
} ;
2017-05-28 04:17:53 +00:00
}
2020-11-07 20:25:15 +00:00
private static CheckResult [ ] VerifyRelearnSpecifiedMoveset ( PKM pkm , IReadOnlyList < int > required )
2017-05-28 04:17:53 +00:00
{
CheckResult [ ] res = new CheckResult [ 4 ] ;
2020-06-21 00:44:05 +00:00
int [ ] relearn = pkm . RelearnMoves ;
2017-05-28 04:17:53 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2018-08-03 03:11:42 +00:00
{
2020-06-21 00:44:05 +00:00
res [ i ] = relearn [ i ] ! = required [ i ]
2020-11-27 20:00:49 +00:00
? new CheckResult ( Severity . Invalid , string . Format ( LMoveFExpect_0 , LegalityAnalyzers . MoveStrings [ required [ i ] ] ) , CheckIdentifier . RelearnMove )
2017-05-28 04:17:53 +00:00
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2018-08-03 03:11:42 +00:00
}
2017-05-28 04:17:53 +00:00
return res ;
}
2018-08-03 03:11:42 +00:00
2020-11-07 20:25:15 +00:00
private static CheckResult [ ] VerifyRelearnDexNav ( PKM pkm )
2017-05-28 04:17:53 +00:00
{
2018-12-28 04:24:24 +00:00
var result = new CheckResult [ 4 ] ;
2020-06-21 00:44:05 +00:00
int [ ] relearn = pkm . RelearnMoves ;
2017-05-28 04:17:53 +00:00
// DexNav Pokémon can have 1 random egg move as a relearn move.
2020-06-21 00:44:05 +00:00
var baseSpec = EvoBase . GetBaseSpecies ( pkm ) ;
2020-11-07 20:25:15 +00:00
result [ 0 ] = ! MoveEgg . GetEggMoves ( 6 , baseSpec . Species , baseSpec . Form , GameVersion . OR ) . Contains ( relearn [ 0 ] )
2018-09-01 21:11:12 +00:00
? new CheckResult ( Severity . Invalid , LMoveRelearnDexNav , CheckIdentifier . RelearnMove )
2017-05-28 04:17:53 +00:00
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
// All other relearn moves must be empty.
for ( int i = 1 ; i < 4 ; i + + )
2018-08-03 03:11:42 +00:00
{
2020-06-21 00:44:05 +00:00
result [ i ] = relearn [ i ] ! = 0
2018-09-01 21:11:12 +00:00
? new CheckResult ( Severity . Invalid , LMoveRelearnNone , CheckIdentifier . RelearnMove )
2017-05-28 04:17:53 +00:00
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2018-08-03 03:11:42 +00:00
}
2017-05-28 04:17:53 +00:00
2018-12-28 04:24:24 +00:00
return result ;
2017-05-28 04:17:53 +00:00
}
2018-08-03 03:11:42 +00:00
2020-11-07 20:25:15 +00:00
private static CheckResult [ ] VerifyRelearnNone ( PKM pkm )
2017-05-28 04:17:53 +00:00
{
2018-12-28 04:24:24 +00:00
var result = new CheckResult [ 4 ] ;
2017-05-28 04:17:53 +00:00
int [ ] RelearnMoves = pkm . RelearnMoves ;
// No relearn moves should be present.
for ( int i = 0 ; i < 4 ; i + + )
2018-08-03 03:11:42 +00:00
{
2018-12-28 04:24:24 +00:00
result [ i ] = RelearnMoves [ i ] ! = 0
2018-09-01 21:11:12 +00:00
? new CheckResult ( Severity . Invalid , LMoveRelearnNone , CheckIdentifier . RelearnMove )
2017-05-28 04:17:53 +00:00
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2018-08-03 03:11:42 +00:00
}
2017-05-28 04:17:53 +00:00
2018-12-28 04:24:24 +00:00
return result ;
2017-05-28 04:17:53 +00:00
}
2018-08-03 03:11:42 +00:00
2020-11-07 20:25:15 +00:00
private static CheckResult [ ] VerifyRelearnEggBase ( PKM pkm , EncounterEgg e )
2017-05-28 04:17:53 +00:00
{
int [ ] RelearnMoves = pkm . RelearnMoves ;
2018-12-28 04:24:24 +00:00
var result = new CheckResult [ 4 ] ;
2017-08-01 00:09:16 +00:00
// Level up moves cannot be inherited if Ditto is the parent
2018-07-04 16:15:20 +00:00
// that means genderless species and male only species except Nidoran and Volbeat (they breed with female nidoran and illumise) could not have level up moves as an egg
2018-06-19 04:56:30 +00:00
bool inheritLvlMoves = Legal . GetCanInheritMoves ( e . Species ) ;
2017-05-28 04:17:53 +00:00
// Obtain level1 moves
2020-06-21 00:44:05 +00:00
var baseMoves = MoveList . GetBaseEggMoves ( pkm , e . Species , e . Form , e . Version , 1 ) ;
2017-08-01 21:55:10 +00:00
int baseCt = Math . Min ( 4 , baseMoves . Length ) ;
2017-05-28 04:17:53 +00:00
// Obtain Inherited moves
2020-06-21 00:44:05 +00:00
var inheritMoves = MoveList . GetValidRelearn ( pkm , e . Species , e . Form , inheritLvlMoves , e . Version ) . ToList ( ) ;
2017-08-01 00:09:16 +00:00
int reqBase = GetRequiredBaseMoves ( RelearnMoves , baseMoves , baseCt , inheritMoves ) ;
2017-05-28 04:17:53 +00:00
// Check if the required amount of Base Egg Moves are present.
2018-12-28 04:24:24 +00:00
FlagBaseEggMoves ( result , reqBase , baseMoves , RelearnMoves ) ;
2017-05-28 04:17:53 +00:00
// Non-Base moves that can magically appear in the regular movepool
if ( Legal . LightBall . Contains ( pkm . Species ) )
2017-08-01 00:09:16 +00:00
inheritMoves . Add ( 344 ) ; // Volt Tackle
2017-05-28 04:17:53 +00:00
// If any splitbreed moves are invalid, flag accordingly
2018-09-02 02:55:08 +00:00
var splitMoves = e is EncounterEggSplit s
2020-06-21 00:44:05 +00:00
? MoveList . GetValidRelearn ( pkm , s . OtherSpecies , s . Form , inheritLvlMoves , e . Version ) . ToList ( )
2018-09-02 02:55:08 +00:00
: ( IReadOnlyList < int > ) Array . Empty < int > ( ) ;
2017-05-28 04:17:53 +00:00
// Inherited moves appear after the required base moves.
2017-08-01 00:09:16 +00:00
// If the pkm is capable of split-species breeding and any inherited move is from the other split scenario, flag accordingly.
2018-12-28 04:24:24 +00:00
bool splitInvalid = FlagInvalidInheritedMoves ( result , reqBase , RelearnMoves , inheritMoves , splitMoves ) ;
2020-07-19 23:30:46 +00:00
if ( splitInvalid & & e is EncounterEggSplit x )
FlagSplitbreedMoves ( result , reqBase , x ) ;
2017-08-01 00:09:16 +00:00
2020-11-27 21:05:36 +00:00
var dupe = IsAnyRelearnMoveDuplicate ( pkm ) ;
if ( dupe > 0 )
result [ dupe ] = new CheckResult ( Severity . Invalid , LMoveSourceDuplicate , CheckIdentifier . RelearnMove ) ;
2018-12-28 04:24:24 +00:00
return result ;
2017-08-01 00:09:16 +00:00
}
2018-08-03 03:11:42 +00:00
2018-12-28 04:24:24 +00:00
private static void FlagBaseEggMoves ( CheckResult [ ] result , int required , IReadOnlyList < int > baseMoves , IReadOnlyList < int > RelearnMoves )
2017-08-01 00:09:16 +00:00
{
for ( int i = 0 ; i < required ; i + + )
{
if ( ! baseMoves . Contains ( RelearnMoves [ i ] ) )
{
2018-12-28 04:24:24 +00:00
FlagRelearnMovesMissing ( result , required , baseMoves , i ) ;
2017-08-01 00:09:16 +00:00
return ;
}
2018-12-28 04:24:24 +00:00
result [ i ] = new CheckResult ( Severity . Valid , LMoveRelearnEgg , CheckIdentifier . RelearnMove ) ;
2017-08-01 00:09:16 +00:00
}
}
2018-08-03 03:11:42 +00:00
2018-12-28 04:24:24 +00:00
private static void FlagRelearnMovesMissing ( CheckResult [ ] result , int required , IReadOnlyList < int > baseMoves , int start )
2017-08-01 00:09:16 +00:00
{
for ( int z = start ; z < required ; z + + )
2018-12-28 04:24:24 +00:00
result [ z ] = new CheckResult ( Severity . Invalid , LMoveRelearnEggMissing , CheckIdentifier . RelearnMove ) ;
2017-08-01 00:09:16 +00:00
// provide the list of suggested base moves for the last required slot
2018-05-12 15:41:23 +00:00
string em = string . Join ( ", " , GetMoveNames ( baseMoves ) ) ;
2018-12-28 04:24:24 +00:00
result [ required - 1 ] . Comment + = string . Format ( Environment . NewLine + LMoveRelearnFExpect_0 , em ) ;
2017-08-01 00:09:16 +00:00
}
2018-08-03 03:11:42 +00:00
2018-12-28 04:24:24 +00:00
private static bool FlagInvalidInheritedMoves ( CheckResult [ ] result , int required , IReadOnlyList < int > RelearnMoves , IReadOnlyList < int > inheritMoves , IReadOnlyList < int > splitMoves )
2017-08-01 00:09:16 +00:00
{
bool splitInvalid = false ;
2018-07-04 16:15:20 +00:00
bool isSplit = splitMoves . Count > 0 ;
2017-08-01 00:09:16 +00:00
for ( int i = required ; i < 4 ; i + + )
2017-05-28 04:17:53 +00:00
{
if ( RelearnMoves [ i ] = = 0 ) // empty
2018-12-28 04:24:24 +00:00
result [ i ] = new CheckResult ( Severity . Valid , LMoveSourceEmpty , CheckIdentifier . RelearnMove ) ;
2017-05-28 04:17:53 +00:00
else if ( inheritMoves . Contains ( RelearnMoves [ i ] ) ) // inherited
2018-12-28 04:24:24 +00:00
result [ i ] = new CheckResult ( Severity . Valid , LMoveSourceRelearn , CheckIdentifier . RelearnMove ) ;
2018-07-04 16:15:20 +00:00
else if ( isSplit & & splitMoves . Contains ( RelearnMoves [ i ] ) ) // inherited
2017-05-28 04:17:53 +00:00
splitInvalid = true ;
else // not inheritable, flag
2018-12-28 04:24:24 +00:00
result [ i ] = new CheckResult ( Severity . Invalid , LMoveRelearnInvalid , CheckIdentifier . RelearnMove ) ;
2017-05-28 04:17:53 +00:00
}
2017-08-01 00:09:16 +00:00
return splitInvalid ;
}
2018-08-03 03:11:42 +00:00
2020-07-19 23:30:46 +00:00
private static void FlagSplitbreedMoves ( CheckResult [ ] res , int required , EncounterEggSplit x )
2017-08-01 00:09:16 +00:00
{
2019-11-19 04:26:11 +00:00
var other = x . OtherSpecies ;
2017-08-01 00:09:16 +00:00
for ( int i = required ; i < 4 ; i + + )
2017-05-28 04:17:53 +00:00
{
2020-09-06 18:24:54 +00:00
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
2017-08-01 00:09:16 +00:00
if ( res [ i ] ! = null )
continue ;
2020-07-19 23:30:46 +00:00
string message = string . Format ( LMoveEggFIncompatible0_1 , SpeciesStrings [ other ] , SpeciesStrings [ x . Species ] ) ;
2017-08-01 00:09:16 +00:00
res [ i ] = new CheckResult ( Severity . Invalid , message , CheckIdentifier . RelearnMove ) ;
2017-05-28 04:17:53 +00:00
}
2017-08-01 00:09:16 +00:00
}
2017-05-28 04:17:53 +00:00
2017-08-01 00:09:16 +00:00
private static int GetRequiredBaseMoves ( int [ ] RelearnMoves , IReadOnlyList < int > baseMoves , int baseCt , IReadOnlyList < int > inheritMoves )
{
2018-06-10 07:26:33 +00:00
var inherited = RelearnMoves . Where ( m = > m ! = 0 & & ( ! baseMoves . Contains ( m ) | | inheritMoves . Contains ( m ) ) ) . ToList ( ) ;
2017-08-01 00:09:16 +00:00
int inheritCt = inherited . Count ;
// Get required amount of base moves
2017-10-07 04:03:23 +00:00
int unique = baseMoves . Union ( inherited ) . Count ( ) ;
2017-08-01 00:09:16 +00:00
int reqBase = inheritCt = = 4 | | baseCt + inheritCt > 4 ? 4 - inheritCt : baseCt ;
2017-10-07 04:03:23 +00:00
if ( RelearnMoves . Count ( m = > m ! = 0 ) < Math . Min ( 4 , baseMoves . Count ) )
2017-08-01 00:09:16 +00:00
reqBase = Math . Min ( 4 , unique ) ;
return reqBase ;
2017-05-28 04:17:53 +00:00
}
2020-11-27 21:05:36 +00:00
private static int IsAnyRelearnMoveDuplicate ( PKM pk )
{
int m1 = pk . RelearnMove1 ;
int m2 = pk . RelearnMove2 ;
if ( m1 ! = 0 & & m1 = = m2 )
return 1 ;
int m3 = pk . RelearnMove3 ;
if ( m3 ! = 0 & & ( m1 = = m3 | | m2 = = m3 ) )
return 2 ;
int m4 = pk . RelearnMove4 ;
if ( m4 ! = 0 & & ( m1 = = m4 | | m2 = = m4 | | m3 = = m4 ) )
return 3 ;
return - 1 ;
}
2017-05-28 04:17:53 +00:00
}
}