internal static PBEPokemonShell FromBytes(BinaryReader r) { var pkmn = new PBEPokemonShell { Species = (PBESpecies)r.ReadUInt32(), Nickname = PBEUtils.StringFromBytes(r), Level = r.ReadByte(), Friendship = r.ReadByte(), Shiny = r.ReadBoolean(), Ability = (PBEAbility)r.ReadByte(), Nature = (PBENature)r.ReadByte(), Gender = (PBEGender)r.ReadByte(), Item = (PBEItem)r.ReadUInt16(), EVs = r.ReadBytes(6), IVs = r.ReadBytes(6) }; byte numMoves = r.ReadByte(); pkmn.Moves = new PBEMove[numMoves]; for (int i = 0; i < numMoves; i++) { pkmn.Moves[i] = (PBEMove)r.ReadUInt16(); } pkmn.PPUps = r.ReadBytes(numMoves); return(pkmn); }
// 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()); }
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 IEnumerable <PBEPokemonShell> TeamFromTextFile(string path) { using (StreamReader r = File.OpenText(path)) { int amt = int.Parse(r.ReadLine()); var team = new PBEPokemonShell[amt]; for (int i = 0; i < amt; i++) { team[i] = new PBEPokemonShell { Species = (PBESpecies)Enum.Parse(typeof(PBESpecies), r.ReadLine()), Nickname = r.ReadLine(), Level = byte.Parse(r.ReadLine()), Friendship = byte.Parse(r.ReadLine()), Shiny = bool.Parse(r.ReadLine()), Ability = (PBEAbility)Enum.Parse(typeof(PBEAbility), r.ReadLine()), Nature = (PBENature)Enum.Parse(typeof(PBENature), r.ReadLine()), Gender = (PBEGender)Enum.Parse(typeof(PBEGender), r.ReadLine()), Item = (PBEItem)Enum.Parse(typeof(PBEItem), r.ReadLine()), }; // Setup for arrays string line; string[] args; void SplitNext() { line = r.ReadLine(); args = line.Split(new[] { ", " }, StringSplitOptions.None); } // EVs SplitNext(); team[i].EVs = new byte[args.Length]; for (int j = 0; j < args.Length; j++) { team[i].EVs[j] = byte.Parse(args[j]); } // IVs SplitNext(); team[i].IVs = new byte[args.Length]; for (int j = 0; j < args.Length; j++) { team[i].IVs[j] = byte.Parse(args[j]); } // Moves SplitNext(); team[i].Moves = new PBEMove[args.Length]; for (int j = 0; j < args.Length; j++) { team[i].Moves[j] = (PBEMove)Enum.Parse(typeof(PBEMove), args[j]); } // PPUps SplitNext(); team[i].PPUps = new byte[args.Length]; for (int j = 0; j < args.Length; j++) { team[i].PPUps[j] = byte.Parse(args[j]); } } return(team); } }