// TODO: Include generation?
        // TODO: Sketch
        // TODO: Same goals as MoveLegalityCheck
        public static PBEMove[] GetLegalMoves(PBESpecies species, byte level, PBESettings settings)
        {
            PBEPokemonShell.ValidateSpecies(species);
            PBEPokemonShell.ValidateLevel(level, settings);
            var evolutionChain = new List <PBESpecies>();

            void AddPreEvolutions(PBESpecies sp)
            {
                foreach (PBESpecies pkmn in PBEPokemonData.GetData(sp).PreEvolutions)
                {
                    AddPreEvolutions(pkmn);
                }
                evolutionChain.Add(sp);
            }

            AddPreEvolutions(species);

            var moves = new List <PBEMove>();

            foreach (PBESpecies pkmn in evolutionChain)
            {
                var pData = PBEPokemonData.GetData(pkmn);
                moves.AddRange(pData.LevelUpMoves.Where(t => t.Level <= level).Select(t => t.Move));
                moves.AddRange(pData.OtherMoves.Select(t => t.Move));
                if (PBEEventPokemon.Events.TryGetValue(pkmn, out ReadOnlyCollection <PBEEventPokemon> events))
                {
                    moves.AddRange(events.SelectMany(e => e.Moves));
                }
            }

            return(moves.Distinct().Where(m => m != PBEMove.None).ToArray());
        }
Example #2
0
        public PBEReadOnlyPartyMoveset(PBESettings settings, IPBEMoveset other)
        {
            settings.ShouldBeReadOnly(nameof(settings));
            int count = other.Count;

            _list = new PBEReadOnlyPartyMovesetSlot[count];
            for (int i = 0; i < count; i++)
            {
                IPBEMovesetSlot oSlot = other[i];
                _list[i] = new PBEReadOnlyPartyMovesetSlot(settings, oSlot.Move, oSlot.PPUps);
            }
        }
        internal PBETeamShell(PBESettings settings, BinaryReader r)
        {
            sbyte count = r.ReadSByte();

            if (count < 1 || count > settings.MaxPartySize)
            {
                throw new InvalidDataException();
            }
            Settings = settings;
            Settings.PropertyChanged += OnSettingsChanged;
            _list = new List <PBEPokemonShell>(Settings.MaxPartySize);
            for (int i = 0; i < count; i++)
            {
                InsertWithEvents(false, new PBEPokemonShell(Settings, r), i);
            }
        }
Example #4
0
        public bool HasSecondaryEffects(PBESettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (!settings.IsReadOnly)
            {
                throw new ArgumentException("Settings must be read-only.", nameof(settings));
            }
            switch (Effect)
            {
            case PBEMoveEffect.Hit__MaybeBurn:
            case PBEMoveEffect.Hit__MaybeBurn__10PercentFlinch:
            case PBEMoveEffect.Hit__MaybeConfuse:
            case PBEMoveEffect.Hit__MaybeFlinch:
            case PBEMoveEffect.Hit__MaybeFreeze:
            case PBEMoveEffect.Hit__MaybeFreeze__10PercentFlinch:
            case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1:
            case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1:
            case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1:
            case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1:
            case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1:
            case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2:
            case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1:
            case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1:
            case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1:
            case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2:
            case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1:
            case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1:
            case PBEMoveEffect.Hit__MaybeParalyze:
            case PBEMoveEffect.Hit__MaybeParalyze__10PercentFlinch:
            case PBEMoveEffect.Hit__MaybePoison:
            case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1:
            case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1:
            case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1:
            case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1:
            case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1:
            case PBEMoveEffect.Hit__MaybeToxic:
            case PBEMoveEffect.Snore: return(true);

            // BUG: SecretPower is unaffected by SereneGrace and the Rainbow
            case PBEMoveEffect.SecretPower: return(settings.BugFix);

            default: return(false);
            }
        }
 public PBETeamShell(PBESettings settings, int numPkmnToGenerate, bool setToMaxLevel)
 {
     if (settings == null)
     {
         throw new ArgumentNullException(nameof(settings));
     }
     if (numPkmnToGenerate < 1 || numPkmnToGenerate > settings.MaxPartySize)
     {
         throw new ArgumentOutOfRangeException(nameof(numPkmnToGenerate));
     }
     Settings = settings;
     Settings.PropertyChanged += OnSettingsChanged;
     _list = new List <PBEPokemonShell>(Settings.MaxPartySize);
     for (int i = 0; i < numPkmnToGenerate; i++)
     {
         Insert(PBEUtils.RandomSpecies(), setToMaxLevel ? Settings.MaxLevel : PBEUtils.RandomLevel(Settings), false, i);
     }
 }
        public PBETeamShell(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            var json = JObject.Parse(File.ReadAllText(path));

            Settings = new PBESettings(json[nameof(Settings)].Value <string>());
            var jArray = (JArray)json["Party"];

            if (jArray.Count < 1 || jArray.Count > Settings.MaxPartySize)
            {
                throw new InvalidDataException("Invalid party size.");
            }
            Settings.PropertyChanged += OnSettingsChanged;
            _list = new List <PBEPokemonShell>(Settings.MaxPartySize);
            for (int i = 0; i < jArray.Count; i++)
            {
                InsertWithEvents(false, new PBEPokemonShell(Settings, jArray[i]), i);
            }
        }
Example #7
0
        public PBEReadOnlyPartyMoveset(PBESettings settings, IPBEMoveset other)
        {
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (!settings.IsReadOnly)
            {
                throw new ArgumentException("Settings must be read-only.", nameof(settings));
            }
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }
            int count = other.Count;

            _list = new PBEReadOnlyPartyMovesetSlot[count];
            for (int i = 0; i < count; i++)
            {
                IPBEMovesetSlot oSlot = other[i];
                _list[i] = new PBEReadOnlyPartyMovesetSlot(settings, oSlot.Move, oSlot.PPUps);
            }
        }
Example #8
0
        public static void MoveLegalityCheck(PBESpecies species, byte level, IEnumerable <PBEMove> moves, PBESettings settings)
        {
            // Validate basic move rules first
            if (moves == null || moves.Count() != settings.NumMoves)
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"A Pokémon must have exactly {settings.NumMoves} moves.");
            }
            if (moves.Any(m => moves.Count(m2 => m != PBEMove.None && m == m2) > 1))
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"A Pokémon cannot have duplicate moves other than {PBEMove.None}.");
            }
            if (moves.All(m => m == PBEMove.None))
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"A Pokémon must have at least one move other than {PBEMove.None}.");
            }
            if (species == PBESpecies.Keldeo_Resolute && !moves.Contains(PBEMove.SecretSword))
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"{species} must have {PBEMove.SecretSword}.");
            }

            // Combine all moves from pre-evolutions
            IEnumerable <PBESpecies> evolutionChain = PBEPokemonData.Data[species].PreEvolutions.Concat(new[] { species });

            IEnumerable <Tuple <PBEMove, byte, PBEMoveObtainMethod> > levelUp = new Tuple <PBEMove, byte, PBEMoveObtainMethod> [0];
            IEnumerable <Tuple <PBEMove, PBEMoveObtainMethod> >       other   = new Tuple <PBEMove, PBEMoveObtainMethod> [0];

            foreach (PBESpecies pkmn in evolutionChain)
            {
                PBEPokemonData pData = PBEPokemonData.Data[pkmn];
                levelUp = levelUp.Union(pData.LevelUpMoves.Where(t => t.Item2 <= level));
                other   = other.Union(pData.OtherMoves);
            }
            // TODO:
            IEnumerable <PBEMove> allAsMoves = GetLegalMoves(species, level);

            // Check if there's a move it cannot possibly learn
            foreach (PBEMove m in moves)
            {
                if (m != PBEMove.None && !allAsMoves.Contains(m))
                {
                    throw new ArgumentOutOfRangeException(nameof(moves), $"{species} cannot learn {m}.");
                }
            }

            // Check generational rules
            bool HasGen3Method(PBEMoveObtainMethod method)
            {
                return(method.HasFlag(PBEMoveObtainMethod.LevelUp_RS) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_FR) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_LG) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_E) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_Colo) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_XD) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_RSFRLGE) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_RSFRLGE) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_FRLG) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_E) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_XD) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_RSFRLG) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_E));
            }

            bool HasGen4Method(PBEMoveObtainMethod method)
            {
                return(method.HasFlag(PBEMoveObtainMethod.LevelUp_DP) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_Pt) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_DPPtHGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_DPPt) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_DP) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_Pt) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_DPPt) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_HGSS));
            }

            bool HasGen5Method(PBEMoveObtainMethod method)
            {
                return(method.HasFlag(PBEMoveObtainMethod.LevelUp_BW) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_B2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_BW) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_B2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_BWB2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_BW) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_B2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_BWB2W2));
            }

            IEnumerable <Tuple <PBEMove, PBEMoveObtainMethod> > movesAsObtainMethods = levelUp.Where(t => moves.Contains(t.Item1)).Select(t => Tuple.Create(t.Item1, t.Item3)).Union(other.Where(t => moves.Contains(t.Item1)));

            // Check to see where the Pokémon DEFINITELY has been
            bool definitelyBeenInGeneration3 = false,
                 definitelyBeenInGeneration4 = false,
                 definitelyBeenInGeneration5 = false;

            foreach (Tuple <PBEMove, PBEMoveObtainMethod> m in movesAsObtainMethods)
            {
                bool gen3 = HasGen3Method(m.Item2),
                                                          gen4 = HasGen4Method(m.Item2),
                                                          gen5 = HasGen5Method(m.Item2);
                if (gen3 && !gen4 && !gen5)
                {
                    definitelyBeenInGeneration3 = true;
                }
                else if (!gen3 && gen4 && !gen5)
                {
                    definitelyBeenInGeneration4 = true;
                }
                else if (!gen3 && !gen4 && gen5)
                {
                    definitelyBeenInGeneration5 = true;
                }
            }

            // TODO: Check where the species was born
            // TODO: Check if moves make sense (example: learns a move in gen4 but was born in gen5/caught in dreamworld/is gen5 event)
            // TODO: Check if HMs were transferred
            // TODO: Check events for moves
            ;
        }
Example #9
0
        public static void ValidateShell(this PBEPokemonShell shell, PBESettings settings)
        {
            // Validate Species
            PBEPokemonData pData;

            switch (shell.Species)
            {
            case PBESpecies.Darmanitan_Zen:
            case PBESpecies.Meloetta_Pirouette:
                throw new ArgumentOutOfRangeException(nameof(shell.Species), $"{shell.Species} must be in its base forme.");

            default:
                try
                {
                    pData = PBEPokemonData.Data[shell.Species];
                }
                catch (KeyNotFoundException)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Species), "Invalid species.");
                }
                break;
            }

            // Validate Nickname
            if (string.IsNullOrWhiteSpace(shell.Nickname))
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Nickname), $"{nameof(shell.Nickname)} cannot be empty.");
            }
            if (shell.Nickname.Length > settings.MaxPokemonNameLength)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Nickname), $"{nameof(shell.Nickname)} cannot exceed {settings.MaxPokemonNameLength} characters.");
            }

            // Validate Level
            if (shell.Level < settings.MinLevel || shell.Level > settings.MaxLevel)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Level), $"A {shell.Species}'s level must be at least {settings.MinLevel} and cannot exceed {settings.MaxLevel}.");
            }

            // Validate Ability
            if (!pData.HasAbility(shell.Ability))
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Ability), $"{shell.Species} cannot have {shell.Ability}.");
            }

            // Validate Nature
            if (shell.Nature >= PBENature.MAX)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Nature), "Invalid nature.");
            }

            // Validate Gender
            if (shell.Gender >= PBEGender.MAX ||
                (shell.Gender == PBEGender.Male && (pData.GenderRatio == PBEGenderRatio.M0_F1 || pData.GenderRatio == PBEGenderRatio.M0_F0)) ||
                (shell.Gender == PBEGender.Female && (pData.GenderRatio == PBEGenderRatio.M1_F0 || pData.GenderRatio == PBEGenderRatio.M0_F0)) ||
                (shell.Gender == PBEGender.Genderless && pData.GenderRatio != PBEGenderRatio.M0_F0)
                )
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Gender), $"Invalid gender for {shell.Species}.");
            }

            // Validate Item
            if (shell.Item != PBEItem.None)
            {
                try
                {
                    PBEItemData iData = PBEItemData.Data[shell.Item];
                }
                catch
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), "Invalid item.");
                }
            }

            // Validate EVs
            if (shell.EVs == null || shell.EVs.Length != 6)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.EVs), $"{nameof(shell.EVs)} array can only have a length of 6.");
            }
            if (shell.EVs.Select(e => (int)e).Sum() > settings.MaxTotalEVs)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.EVs), $"Total EVs cannot exceed {settings.MaxTotalEVs}.");
            }
            // Validate IVs
            if (shell.IVs == null || shell.IVs.Length != 6)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.IVs), $"{nameof(shell.IVs)} array can only have a length of 6.");
            }
            if (shell.IVs.Any(i => i > settings.MaxIVs))
            {
                throw new ArgumentOutOfRangeException(nameof(shell.IVs), $"Each IV cannot exceed {settings.MaxIVs}.");
            }

            // Validate Moves
            try
            {
                MoveLegalityCheck(shell.Species, shell.Level, shell.Moves, settings);
            }
            catch (Exception e)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.Moves), e.Message);
            }

            // Validate PPUps
            if (shell.PPUps == null || shell.PPUps.Length != settings.NumMoves)
            {
                throw new ArgumentOutOfRangeException(nameof(shell.PPUps), $"{nameof(shell.PPUps)} array can only have a length of {settings.NumMoves}.");
            }
            if (shell.PPUps.Any(p => p > settings.MaxPPUps))
            {
                throw new ArgumentOutOfRangeException(nameof(shell.PPUps), $"Each PP-Up cannot exceed {settings.MaxPPUps}.");
            }

            // Validate Forme-Specific Requirements
            switch (shell.Species)
            {
            case PBESpecies.Shedinja:
                if (shell.EVs[0] > 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.EVs), $"{shell.Species} cannot have any HP EVs.");
                }
                break;

            case PBESpecies.Giratina:
                if (shell.Item == PBEItem.GriseousOrb)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} cannot hold a {shell.Item}.");
                }
                break;

            case PBESpecies.Giratina_Origin:
                if (shell.Item != PBEItem.GriseousOrb)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.GriseousOrb}.");
                }
                break;

            case PBESpecies.Arceus:
                if (shell.Item == PBEItem.DracoPlate ||
                    shell.Item == PBEItem.DreadPlate ||
                    shell.Item == PBEItem.EarthPlate ||
                    shell.Item == PBEItem.FistPlate ||
                    shell.Item == PBEItem.FlamePlate ||
                    shell.Item == PBEItem.IciclePlate ||
                    shell.Item == PBEItem.InsectPlate ||
                    shell.Item == PBEItem.IronPlate ||
                    shell.Item == PBEItem.MeadowPlate ||
                    shell.Item == PBEItem.MindPlate ||
                    shell.Item == PBEItem.SkyPlate ||
                    shell.Item == PBEItem.SplashPlate ||
                    shell.Item == PBEItem.SpookyPlate ||
                    shell.Item == PBEItem.StonePlate ||
                    shell.Item == PBEItem.ToxicPlate ||
                    shell.Item == PBEItem.ZapPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} cannot hold a {shell.Item}.");
                }
                break;

            case PBESpecies.Arceus_Bug:
                if (shell.Item != PBEItem.InsectPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.InsectPlate}.");
                }
                break;

            case PBESpecies.Arceus_Dark:
                if (shell.Item != PBEItem.DreadPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.DreadPlate}.");
                }
                break;

            case PBESpecies.Arceus_Dragon:
                if (shell.Item != PBEItem.DracoPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.DracoPlate}.");
                }
                break;

            case PBESpecies.Arceus_Electric:
                if (shell.Item != PBEItem.ZapPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.ZapPlate}.");
                }
                break;

            case PBESpecies.Arceus_Fighting:
                if (shell.Item != PBEItem.FistPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.FistPlate}.");
                }
                break;

            case PBESpecies.Arceus_Fire:
                if (shell.Item != PBEItem.FlamePlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.FlamePlate}.");
                }
                break;

            case PBESpecies.Arceus_Flying:
                if (shell.Item != PBEItem.SkyPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.SkyPlate}.");
                }
                break;

            case PBESpecies.Arceus_Ghost:
                if (shell.Item != PBEItem.SpookyPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.SpookyPlate}.");
                }
                break;

            case PBESpecies.Arceus_Grass:
                if (shell.Item != PBEItem.MeadowPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.MeadowPlate}.");
                }
                break;

            case PBESpecies.Arceus_Ground:
                if (shell.Item != PBEItem.EarthPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.EarthPlate}.");
                }
                break;

            case PBESpecies.Arceus_Ice:
                if (shell.Item != PBEItem.IciclePlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.IciclePlate}.");
                }
                break;

            case PBESpecies.Arceus_Poison:
                if (shell.Item != PBEItem.ToxicPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.ToxicPlate}.");
                }
                break;

            case PBESpecies.Arceus_Psychic:
                if (shell.Item != PBEItem.MindPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.MindPlate}.");
                }
                break;

            case PBESpecies.Arceus_Rock:
                if (shell.Item != PBEItem.StonePlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.StonePlate}.");
                }
                break;

            case PBESpecies.Arceus_Steel:
                if (shell.Item != PBEItem.IronPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.IronPlate}.");
                }
                break;

            case PBESpecies.Arceus_Water:
                if (shell.Item != PBEItem.SplashPlate)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.SplashPlate}.");
                }
                break;

            case PBESpecies.Genesect:
                if (shell.Item == PBEItem.BurnDrive ||
                    shell.Item == PBEItem.ChillDrive ||
                    shell.Item == PBEItem.DouseDrive ||
                    shell.Item == PBEItem.ShockDrive)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} cannot hold a {shell.Item}.");
                }
                break;

            case PBESpecies.Genesect_Burn:
                if (shell.Item != PBEItem.BurnDrive)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.BurnDrive}.");
                }
                break;

            case PBESpecies.Genesect_Chill:
                if (shell.Item != PBEItem.ChillDrive)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.ChillDrive}.");
                }
                break;

            case PBESpecies.Genesect_Douse:
                if (shell.Item != PBEItem.DouseDrive)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.DouseDrive}.");
                }
                break;

            case PBESpecies.Genesect_Shock:
                if (shell.Item != PBEItem.ShockDrive)
                {
                    throw new ArgumentOutOfRangeException(nameof(shell.Item), $"{shell.Species} must hold a {PBEItem.ShockDrive}.");
                }
                break;
            }
        }
 public static byte GetHiddenPowerBasePower(this IPBEReadOnlyStatCollection stats, PBESettings settings)
 {
     return(PBEDataUtils.GetHiddenPowerBasePower(stats.HP, stats.Attack, stats.Defense, stats.SpAttack, stats.SpDefense, stats.Speed, settings));
 }
Example #11
0
 public static bool HasSecondaryEffects(this IPBEMoveData mData, PBESettings settings)
 {
     return(PBEDataUtils.HasSecondaryEffects(mData.Effect, settings));
 }
Example #12
0
 internal PBEReadOnlyPartyMovesetSlot(PBESettings settings, PBEMove move, byte ppUps)
 {
     Move  = move;
     PP    = PBEDataUtils.CalcMaxPP(move, ppUps, settings);
     PPUps = ppUps;
 }
Example #13
0
        // TODO: Check where the species was born
        // TODO: Check if moves make sense (example: learns a move in gen4 but was born in gen5/caught in dreamworld/is gen5 event)
        // TODO: Check if HMs were transferred
        // TODO: Check events for moves
        // TODO: EggMove_Special
        public static void MoveLegalityCheck(PBESpecies species, byte level, IEnumerable <PBEMove> moves, PBESettings settings)
        {
            // Validate basic move rules first
            if (moves == null || moves.Count() != settings.NumMoves)
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"A Pokémon must have exactly {settings.NumMoves} moves.");
            }
            if (moves.Any(m => moves.Count(m2 => m != PBEMove.None && m == m2) > 1))
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"A Pokémon cannot have duplicate moves other than {PBEMove.None}.");
            }
            if (moves.All(m => m == PBEMove.None))
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"A Pokémon must have at least one move other than {PBEMove.None}.");
            }
            if (species == PBESpecies.Keldeo_Resolute && !moves.Contains(PBEMove.SecretSword))
            {
                throw new ArgumentOutOfRangeException(nameof(moves), $"{species} must have {PBEMove.SecretSword}.");
            }

            // Combine all moves from pre-evolutions
            IEnumerable <PBESpecies> evolutionChain = PBEPokemonData.GetData(species).PreEvolutions.Concat(new[] { species });

            var levelUp = new List <(PBEMove Move, byte Level, PBEMoveObtainMethod ObtainMethod)>();
            var other   = new List <(PBEMove Move, PBEMoveObtainMethod ObtainMethod)>();

            foreach (PBESpecies pkmn in evolutionChain)
            {
                var pData = PBEPokemonData.GetData(pkmn);
                levelUp.AddRange(pData.LevelUpMoves.Where(t => t.Level <= level));
                other.AddRange(pData.OtherMoves);
            }
            // TODO:
            IEnumerable <PBEMove> allAsMoves = GetLegalMoves(species, level);

            // Check if there's a move it cannot possibly learn
            foreach (PBEMove m in moves)
            {
                if (m != PBEMove.None && !allAsMoves.Contains(m))
                {
                    throw new ArgumentOutOfRangeException(nameof(moves), $"{species} cannot learn {m}.");
                }
            }

            // Check generational rules
            bool HasGen3Method(PBEMoveObtainMethod method)
            {
                return(method.HasFlag(PBEMoveObtainMethod.LevelUp_RSColoXD) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_FR) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_LG) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_E) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_RSFRLGEColoXD) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_RSFRLGEColoXD) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_FRLG) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_E) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_XD) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_RSFRLGE));
            }

            bool HasGen4Method(PBEMoveObtainMethod method)
            {
                return(method.HasFlag(PBEMoveObtainMethod.LevelUp_DP) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_Pt) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_DPPt) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_DPPt) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_DP) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_Pt) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_HGSS) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_DPPt) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_HGSS));
            }

            bool HasGen5Method(PBEMoveObtainMethod method)
            {
                return(method.HasFlag(PBEMoveObtainMethod.LevelUp_BW) ||
                       method.HasFlag(PBEMoveObtainMethod.LevelUp_B2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_BW) ||
                       method.HasFlag(PBEMoveObtainMethod.TM_B2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.HM_BWB2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_BW) ||
                       method.HasFlag(PBEMoveObtainMethod.MoveTutor_B2W2) ||
                       method.HasFlag(PBEMoveObtainMethod.EggMove_BWB2W2));
            }

            IEnumerable <(PBEMove Move, PBEMoveObtainMethod ObtainMethod)> movesAsObtainMethods = levelUp.Where(t => moves.Contains(t.Move)).Select(t => (t.Move, t.ObtainMethod)).Union(other.Where(t => moves.Contains(t.Move)));

            // Check to see where the Pokémon DEFINITELY has been
            bool definitelyBeenInGeneration3 = false,
                 definitelyBeenInGeneration4 = false,
                 definitelyBeenInGeneration5 = false;

            foreach ((PBEMove Move, PBEMoveObtainMethod ObtainMethod) in movesAsObtainMethods)
            {
                bool gen3 = HasGen3Method(ObtainMethod),
                     gen4 = HasGen4Method(ObtainMethod),
                     gen5 = HasGen5Method(ObtainMethod);
                if (gen3 && !gen4 && !gen5)
                {
                    definitelyBeenInGeneration3 = true;
                }
                else if (!gen3 && gen4 && !gen5)
                {
                    definitelyBeenInGeneration4 = true;
                }
                else if (!gen3 && !gen4 && gen5)
                {
                    definitelyBeenInGeneration5 = true;
                }
            }
        }