0
\$\begingroup\$

I'm back with a hopefully revised and improved version of my RPG pokemon console game! Well, it's more like a "randomized" pokemon simulation as there isn't really any kind of strategy, it's only about getting lucky lol.

I have added more functionalities and made lots of changes and corrections as suggested, but I'm sure there's a lot more room for improvement so here I am.

Could anyone please take a look and let me know what they think? I won't leave this project alone until it is (near) perfect. Warning: It's LONG. (sorry)

Full code on pastebin: https://pastebin.com/iDZDCgZD

ConsoleUI.Progam.cs

using System;
using System.Collections.Generic;
using System.Linq;
using GameLogic;

namespace ConsoleUI
{
    public static class Program
    {
        private static readonly Dictionary<string, string> Choices =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                {"CatchWildPokemon", "1"},
                {"TrainPokemon", "2"},
                {"FightRival", "3"},
                {"Exit", "4"}
            };

        private static readonly Dictionary<string, string> YesOrNo =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                {"Yes", "Y"},
                {"No", "N"}
            };

        private static readonly string Y = YesOrNo["Yes"];
        private static readonly string N = YesOrNo["No"];
        private static readonly string CatchWildPokemon = Choices["CatchWildPokemon"];
        private static readonly string TrainPokemon = Choices["TrainPokemon"];
        private static readonly string FightRival = Choices["FightRival"];
        private static readonly string Exit = Choices["Exit"];

        private static readonly IPokemonGenerator PokemonGenerator = new PokemonGenerator();
        private static readonly PokemonLevelSystem LevelSystem = new PokemonLevelSystem();
        private static readonly IPokemonWorld PokemonWorld = new PokemonWorld();
        private static readonly IGameState GameState = new GameState();

        private static IRandomPokemonPicker _pokemonPicker;
        private static IPlayersCollection _playersCollection;
        private static IRivalsCollection _rivalsCollection;

        private static readonly ICollection<Pokemon> GymTeam = new List<Pokemon>();
        private static readonly ICollection<Pokemon> FightingTeam = new List<Pokemon>();
        private static readonly IList<Pokemon> RivalsTeam = new List<Pokemon>();

        private static bool _isGameOn;
        private static bool _trainPokemon;
        private static bool _fightRival;
        private static int _wins;
        private static int _ties;
        private static int _losses;

        private static void Main()
        {
            PokemonWorld.Populate(PokemonGenerator, PokemonGenerator.Generate().Count());
            _pokemonPicker = new RandomPokemonPicker(PokemonWorld);
            _playersCollection = new PlayersCollection(_pokemonPicker, PokemonWorld);
            _rivalsCollection = new RivalsCollection(PokemonWorld);
            GameState.LoadGame(_playersCollection, _pokemonPicker);
            _isGameOn = true;

            Menu();
        }

        // *** MENU ***

        private static void DisplayMenu()
        {
            Console.WriteLine("\nWhat do you want to do?\n");
            Console.WriteLine($"{CatchWildPokemon}. Catch wild pokémon");
            Console.WriteLine($"{TrainPokemon}. Train your pokémon in gym");
            Console.WriteLine($"{FightRival}. Fight rival [Min level: {_rivalsCollection.MinLevel}]");
            Console.WriteLine($"{Exit}. Exit");
            Console.WriteLine("");
        }

        public static void Menu()
        {
            while (_isGameOn)
            {
                DisplayMenu();

                var choice = Console.ReadLine();
                while (Choices.All(n => n.Value != choice))
                {
                    Console.WriteLine(
                        $"\nPlease type '{CatchWildPokemon}', '{TrainPokemon}' or '{FightRival}', or exit typing '{Exit}'.\n");
                    choice = Console.ReadLine();
                }
                if (choice == Exit)
                {
                    GameState.SaveGame(_playersCollection.GetCollection(), _pokemonPicker.GetCurrentPopulation());
                    _isGameOn = false;
                    break;
                }
                PlayerChoice(choice);
            }
            Console.WriteLine("");
        }

        private static void PlayerChoice(string choice)
        {
            if (choice == CatchWildPokemon)
            {
                if (AreRequirementsMetToCatchPokemon())
                    ChoiceCatchWildPokemon();
            }

            else if (choice == TrainPokemon)
            {
                if (AreRequirementsMetToTrainPokemon())
                    ChoiceTrainPokemon();
            }

            else if (choice == FightRival)
            {
                if (AreRequirementsMetToFightRival())
                    ChoiceFightRival();
            }
            else
            {
                throw new Exception("Unexpected error occurred. Player's choice is invalid.");
            }
        }

        // *** CHECK REQUIREMENTS FOR EACH CHOICE ***

        private static bool AreRequirementsMetToCatchPokemon()
        {
            if (!_playersCollection.IsCompleted) return true;

            Console.WriteLine("\nYou've caught all wild pokémon!");
            return false;
        }

        private static bool AreRequirementsMetToTrainPokemon()
        {
            if (_playersCollection.IsEmpty)
            {
                Console.WriteLine("\nYou haven't caught any pokémon yet!");
                return false;
            }
            if (_playersCollection.GetCollection().Any(p => p.Level < LevelSystem.MaxLevel)) return true;

            Console.WriteLine("\nAll your pokémon have reached max level!");
            return false;
        }

        private static bool AreRequirementsMetToFightRival()
        {
            if (_playersCollection.IsEmpty)
            {
                Console.WriteLine("\nYou haven't caught any pokémon yet!");
                return false;
            }
            if (_playersCollection.GetCollection().Any(p => p.Level >= _rivalsCollection.MinLevel)) return true;

            Console.WriteLine("\nAt least one of your pokémon must meet this rival's minimum level requirement.");
            Console.WriteLine("Try leveling up some pokémon at the gym first!");
            return false;
        }

        // *** CATCH WILD POKEMON *** 

        private static void CatchWildPokemonTextIntro()
        {
            Console.WriteLine("\nTime to catch some pokémon!");
            Console.WriteLine("Let's explore this area.");
        }

        private static void ChoiceCatchWildPokemon()
        {
            CatchWildPokemonTextIntro();
            Console.ReadKey();

            while (true)
            {
                var wildPokemon = _playersCollection.GetRandomWildPokemon();

                Console.WriteLine($"\nYou find a wild pokémon. It's a {wildPokemon.Name}. Let's catch it!");
                Console.ReadKey();
                Console.WriteLine($"\nFighting {wildPokemon.Name}...");
                Console.ReadKey();

                if (IsCatchSuccessful())
                {
                    _playersCollection.AddPokemonToCollection(wildPokemon);
                    _pokemonPicker.RemoveFromCurrentPopulation();

                    Console.WriteLine($"\nAwesome! You caught {PokemonInfo(wildPokemon)}");
                }
                else
                {
                    Console.WriteLine($"\nOh no! {wildPokemon.Name} escaped!");
                }

                if (_playersCollection.GetCollection().Count > 0)
                    Console.WriteLine($"\nPokémon in your collection:\n\n{DisplayOwnedPokemon()}");

                if (!Confirm("\nDo you want to keep catching pokémons?"))
                    break;

                if (!_playersCollection.IsCompleted) continue;

                Console.WriteLine("\nYou've caught all wild pokémon!");
                break;
            }
        }

        private static bool IsCatchSuccessful()
        {
            return new Random().Next(100) >= 50;
        }

        // *** TRAIN POKEMON *** 

        private static void TrainPokemonTextIntro()
        {
            Console.WriteLine("\nTime to head to pokémon gym!");
            Console.WriteLine("Let's level up some pokémon.");
        }

        private static void ChoiceTrainPokemon()
        {
            TrainPokemonTextIntro();
            _trainPokemon = true;

            while (_trainPokemon)
            {
                Console.WriteLine($"\nPokemon in your collection:\n\n{DisplayOwnedPokemon()}");

                if (_playersCollection.GetCollection().Count == 1)
                {
                    if (!GymTeam.Any()) AddSingleDefaultPokemonToTeam(GymTeam);
                }
                else
                {
                    SetTeam(GymTeam, 6);
                }
                TrainChosenTeam();
            }

            GymTeam.Clear();
        }

        private static void TrainChosenTeam()
        {
            do
            {
                TrainedTeamText();

                if (TrainAgain())
                {
                    if (GymTeam.Count == 1 && _playersCollection.GetCollection().Count == 1)
                        break;
                    continue;
                }
                _trainPokemon = false;
                break;
            } while (TrainSameTeam() && _playersCollection.GetCollection().Count > 1);
        }

        private static void TrainedTeamText()
        {
            Console.WriteLine("\nTraining...\n");
            Console.ReadKey();

            foreach (var pokemon in GymTeam)
            {
                LevelSystem.IncreasePokemonExp(pokemon);

                if (LevelSystem.HasPokemonReachedMaxLevel(pokemon))
                    Console.WriteLine($"{pokemon.Name} has reached max level! ");
                else
                    Console.WriteLine(LevelSystem.HasPokemonLeveledUp(pokemon)
                        ? $"{pokemon.Name} has leveled up!"
                        : $"{pokemon.Name} has gained experience!");
            }

            Console.WriteLine($"\n{DisplayTeam(GymTeam)}");
        }

        private static bool TrainAgain()
        {
            return Confirm("\nDo you want to train again?");
        }

        private static bool TrainSameTeam()
        {
            return Confirm("\nDo you want to train the same pokémon?");
        }

        // *** FIGHT RIVAL ***

        private static void FightRivalTextIntro()
        {
            Console.WriteLine("\nTime to battle!");
            Console.WriteLine("Let's become a Pokémon Master.");
        }

        private static void ChoiceFightRival()
        {
            FightRivalTextIntro();
            _fightRival = true;

            while (_fightRival)
            {
                Console.WriteLine($"\nPokémon in your collection:\n\n{DisplayOwnedPokemon()}");

                if (_playersCollection.GetCollection().Count == 1)
                {
                    if (!FightingTeam.Any())
                        AddSingleDefaultPokemonToTeam(FightingTeam);
                }
                else
                {
                    SetTeam(FightingTeam, 4);
                }

                FightRivalWithChosenTeam();
            }
            ResetFightRivalVariables();
            _fightRival = false;
        }

        private static void AssignOpponents()
        {
            foreach (var pokemon in _rivalsCollection.GetTeam())
                RivalsTeam.Add(pokemon);

            var random = new Random();

            foreach (var pokemon in FightingTeam)
            {
                var opponentId = random.Next(RivalsTeam.Count);
                pokemon.Opponent = RivalsTeam[opponentId];
                RivalsTeam.RemoveAt(opponentId);
            }
        }

        private static void SetTeamChanceAgainstTheirOpponents()
        {
            if (FightingTeam == null)
                throw new NullReferenceException("Unexpected error occurred. Fighting team is null.");

            var chanceByType = new SuccessChanceByPokemonTypes();

            foreach (var pokemon in FightingTeam)
                pokemon.SuccessChance = chanceByType.GetChance(pokemon.Type, pokemon.Opponent.Type);
        }

        private static void FightRivalWithChosenTeam()
        {
            do
            {
                AssignOpponents();
                SetTeamChanceAgainstTheirOpponents();
                BattleStartText();
                BattleResults();

                if (FightRivalAgain())
                {
                    if (FightingTeam.Count == 1 && _playersCollection.GetCollection().Count == 1)
                    {
                        ResetFightRivalVariables(true);
                        break;
                    }

                    if (FightingTeam.Count == 1 && !ArePokemonWithValidLevelLeftInCollection())
                    {
                        ResetFightRivalVariables(true);
                        break;
                    }

                    if (FightRivalWithSameTeam())
                    {
                        ResetFightRivalVariables(true);
                    }
                    else
                    {
                        ResetFightRivalVariables();
                        break;
                    }
                }
                else
                {
                    _fightRival = false;
                    break;
                }
            } while (true);
        }

        private static bool ArePokemonWithValidLevelLeftInCollection()
        {
            var pokemonLeftInCollection = _playersCollection.GetCollection().Select(p => p)
                .Except(FightingTeam.Select(p => p));

            return pokemonLeftInCollection.Any(p => p.Level >= _rivalsCollection.MinLevel);
        }

        private static void BattleStartText()
        {
            Console.WriteLine("\nLet's battle!");
            Console.ReadKey();

            if (FightingTeam == null)
                throw new NullReferenceException("Unexpected error occurred. Fighting team is null.");

            foreach (var pokemon in FightingTeam)
            {
                Console.WriteLine($"\n{pokemon.Name} was matched against {pokemon.Opponent.Name}.");
                Console.WriteLine($"{pokemon.Name} is type {GetFormattedTypes(pokemon)}, " +
                                  $"while {pokemon.Opponent.Name} is type {GetFormattedTypes(pokemon.Opponent)}.");
                Console.ReadKey();
                DisplaySuccessChanceMessage(pokemon, pokemon.SuccessChance);
                Console.ReadKey();
            }
        }

        private static void DisplaySuccessChanceMessage(Pokemon pokemon, int chance)
        {
            switch (chance)
            {
                case 50:
                    Console.WriteLine($"{pokemon.Name} will do average damage to {pokemon.Opponent.Name}.");
                    Console.WriteLine("It's a 50/50 match!");
                    break;
                case -1:
                    Console.WriteLine(
                        $"{pokemon.Name} and {pokemon.Opponent.Name} cannot do any damage to each other.");
                    Console.WriteLine("It's a tie!");
                    break;
                case 0:
                    Console.WriteLine($"{pokemon.Name} cannot do any damage to {pokemon.Opponent.Name}.");
                    Console.WriteLine($"{pokemon.Name} loses!");
                    break;
                case 20:
                    Console.WriteLine($"{pokemon.Name} is weak against {pokemon.Opponent.Name}.");
                    Console.WriteLine($"{pokemon.Name} has a small chance of winning.");
                    break;
                case 80:
                    Console.WriteLine($"{pokemon.Name} is super effective against {pokemon.Opponent.Name}.");
                    Console.WriteLine($"{pokemon.Name} has a big chance of winning.");
                    break;
                default:
                    throw new Exception("Unexpected error occurred. Pokémon's success chance is an invalid integer.");
            }
        }

        private static void BattleResults()
        {
            if (IsMatchAutomaticallyOver())
            {
                DisplayAutomaticMatchResultMessage();
            }
            else
            {
                OngoingBattles();
                DisplayMatchResults();
                DisplayMatchResultMessage();
            }
        }

        // Automatic match result

        private static bool IsMatchAutomaticallyATie()
        {
            return FightingTeam.All(p => p.SuccessChance == -1);
        }

        private static bool IsMatchAutomaticallyALoss()
        {
            return FightingTeam.All(p => p.SuccessChance == 0);
        }

        private static bool IsMatchAutomaticallyOver()
        {
            return IsMatchAutomaticallyATie() || IsMatchAutomaticallyALoss();
        }

        private static void DisplayAutomaticMatchResultMessage()
        {
            if (IsMatchAutomaticallyATie())
                Console.WriteLine("\nYour match against Rival ended in a tie.");
            else if (IsMatchAutomaticallyALoss())
                Console.WriteLine("\nYou lost the match against Rival.");
        }

        // Random battles result

        private static void OngoingBattles()
        {
            Console.WriteLine("\nFighting...\n");

            foreach (var pokemon in FightingTeam)
                if (IsDraw(pokemon))
                {
                    _ties++;
                }
                else if (IsWin(pokemon))
                {
                    Console.WriteLine($"Cool! {pokemon.Name} won!");
                    _wins++;
                }
                else
                {
                    Console.WriteLine($"Oh no! {pokemon.Name} lost!");
                    _losses++;
                }
        }

        private static bool IsDraw(Pokemon pokemon)
        {
            if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

            return pokemon.SuccessChance == -1;
        }

        private static bool IsWin(Pokemon pokemon)
        {
            if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

            var random = new Random();
            return random.Next(100) < pokemon.SuccessChance;
        }

        // Match result

        private static void DisplayMatchResults()
        {
            if (_wins <= 0 && _losses <= 0 && _ties <= 0)
                throw new Exception("Unexpected error occurred. Invalid battle results.");
            Console.WriteLine($"\nWins: {_wins}");
            Console.WriteLine($"Losses: {_losses}");
            if (_ties > 0)
                Console.WriteLine($"Ties: {_ties}");
        }

        private static void DisplayMatchResultMessage()
        {
            Console.WriteLine(_wins == FightingTeam.Count
                ? "\nCongrats! You won the match against Rival. "
                : "\nYou did not win the match against Rival.");
        }

        private static bool FightRivalAgain()
        {
            return Confirm("\nDo you want to fight this rival again?");
        }

        private static bool FightRivalWithSameTeam()
        {
            return Confirm("\nDo you want to fight with the same pokémon?");
        }

        private static void ResetFightRivalVariables(bool sameTeam = false)
        {
            if (!sameTeam)
                FightingTeam.Clear();

            foreach (var pokemon in FightingTeam)
            {
                pokemon.SuccessChance = 50;
                pokemon.Opponent = null;
            }
            RivalsTeam.Clear();
            _wins = 0;
            _losses = 0;
            _ties = 0;
        }

        // **** HELPER METHODS **** 

        private static bool Confirm(string prompt)
        {
            do
            {
                Console.WriteLine($"{prompt} ({Y}/{N})");
                var input = Console.ReadLine();

                if (string.Equals(input, Y, StringComparison.InvariantCultureIgnoreCase))
                    return true;

                if (string.Equals(input, N, StringComparison.InvariantCultureIgnoreCase))
                    return false;
            } while (true);
        }

        private static string PokemonInfo(Pokemon pokemon)
        {
            return pokemon != null
                ? $"{pokemon.Name} => " +
                  $"Type: {GetFormattedTypes(pokemon)} | " +
                  $"Level: {pokemon.Level} | " +
                  $"Exp: {pokemon.Exp}"
                : "Unexpected error occurred. Pokémon is null.";
        }

        private static string GetFormattedTypes(Pokemon pokemon)
        {
            return string.Join(", ", pokemon.Type.Select(t => t.Name));
        }

        private static string DisplayOwnedPokemon()
        {
            return string.Join("\n", _playersCollection.GetCollection().Select(PokemonInfo).ToList());
        }

        private static string DisplayTeam(IEnumerable<Pokemon> team)
        {
            return string.Join("\n", team.Select(PokemonInfo).ToList());
        }

        private static void AddSingleDefaultPokemonToTeam(ICollection<Pokemon> team)
        {
            team.Add(_playersCollection.GetCollection().First());
        }

        private static void SetTeam(ICollection<Pokemon> team, int max)
        {
            var isValidPokemon = false;

            do
            {
                if (team.Count == max || team.Count == _playersCollection.GetCollection().Count)
                    break;

                if (_fightRival)
                    if (!ArePokemonWithValidLevelLeftInCollection())
                        break;

                if (team.Count > 0 && isValidPokemon)
                {
                    Console.WriteLine($"\nCurrent team:\n\n{DisplayTeam(team)}");

                    if (_fightRival)
                        if (!ArePokemonWithValidLevelLeftInCollection())
                            break;
                    if (!AddAnotherPokemonToTeam())
                        break;
                }

                do
                {
                    var chosenPokemon = ChosenPokemon(max);

                    isValidPokemon = IsChosenPokemonValid(chosenPokemon, team);
                    if (isValidPokemon) AddPokemonToTeam(chosenPokemon, team);
                } while (!isValidPokemon);
            } while (true);
        }

        private static string ChosenPokemon(int max)
        {
            Console.WriteLine(
                "\nType the name of a pokémon from your collection that you'd like to add to your team.");
            Console.WriteLine($"You must add between 1 and {max} pokémon.\n");

            var chosenPokemon = Console.ReadLine();

            if (string.IsNullOrWhiteSpace(chosenPokemon)) return "";

            chosenPokemon = FormatChosenPokemon(chosenPokemon);

            return chosenPokemon;
        }

        private static string FormatChosenPokemon(string chosenPokemon)
        {
            chosenPokemon = chosenPokemon.Trim().ToLowerInvariant();
            chosenPokemon = chosenPokemon.First().ToString().ToUpperInvariant() + chosenPokemon.Substring(1);
            return chosenPokemon;
        }

        private static bool IsChosenPokemonValid(string chosenPokemon, ICollection<Pokemon> team)
        {
            if (string.IsNullOrWhiteSpace(chosenPokemon))
                return false;

            if (_playersCollection.GetCollection().All(p => p.Name != chosenPokemon))
                return false;

            if (team.All(p => p.Name != chosenPokemon))
            {
                if (!_fightRival) return true;

                var pokemon = _playersCollection.GetCollection().FirstOrDefault(p => p.Name == chosenPokemon);

                if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

                var chosenPokemonLvl = pokemon.Level;
                if (chosenPokemonLvl >= _rivalsCollection.MinLevel)
                    return true;
                Console.WriteLine("\nThis pokémon's level is below Rival's level requirement.");
                return false;
            }

            Console.WriteLine($"\nYou already added {chosenPokemon}.");
            return false;
        }

        private static void AddPokemonToTeam(string chosenPokemon, ICollection<Pokemon> team)
        {
            if (chosenPokemon == null)
                throw new NullReferenceException("Unexpected error occurred. Null pokémon string given.");

            var chosenPokemonFromCollection = _playersCollection.GetCollection()
                .SingleOrDefault(p => p.Name == chosenPokemon);

            if (chosenPokemonFromCollection == null)
                throw new NullReferenceException("Unexpected error occurred. There is no such pokémon in World.");

            team.Add(chosenPokemonFromCollection);
        }

        private static bool AddAnotherPokemonToTeam()
        {
            return Confirm("\nDo you want to add another pokémon?");
        }
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ I need to ask you to revert your edit and put the improved version in a self-answer or another follow-up. Editing the code when there are already answers is not allowed... otherwise someone else (or I) will have to do it ;-) please also see What should I do when someone answers my question? \$\endgroup\$
    – t3chb0t
    Jul 16, 2017 at 10:14
  • \$\begingroup\$ Oh sorry didn't know. How come there are so many strange rules on this site hahah. \$\endgroup\$
    – user123850
    Jul 16, 2017 at 12:57
  • \$\begingroup\$ Done! :) So what do you think of my code now? What else can I improve? Are my access modifiers okay? \$\endgroup\$
    – user123850
    Jul 16, 2017 at 13:00

2 Answers 2

0
\$\begingroup\$

You have a single class for all your methods. This is not an optimal design. You should move members that are responsible for controlling the same thing into separate classes.

Every few methods you put comments like // *** MENU *** which are an indicator that a particual group of methods (or other members) should probably have their own class.

Currently everything is connected somehow with everything else so it's virtually impossible to test it. They are also all but one method private so they would not be even accessible to tests. You should strive to develop small units that are good at doing something and nothing more. Later you use these units to compose some larger units that can do more and more util you have a complete game.

Other then this I think you use very good names and your methods are nice and small. I didn't check every one of them but they look like they were responsible for doing only one thing, which is again very good. Now you just have to give them a few smaller classes so that you can either test them separately or exchange them if necessary or even reuse them in other projects. Maybe some classes will be so similar that you can use an interface, who knows. I think this is what you should practice next.

\$\endgroup\$
3
  • \$\begingroup\$ Thank you for your help! Separating the UI into classes totally makes sense, I don't know why I thought that it should all be in one single class lol. Just for clarification though, should I make all the fields and methods from the UI public? I thought the rule was that whatever can be private should be private, but I hadn't thought about testing (which is something I want to learn next as it seems important). I'm gonna update my OP with the separated classes, could you please see if this looks as you suggested now? Thanks! \$\endgroup\$
    – user123850
    Jul 16, 2017 at 10:05
  • \$\begingroup\$ @Evan with the current design it's perfectly ok that everything is private because no body is able to interact with this class and corrupt its state. If you however extract other classes from it then yes, you'll need to make something public so that you can use it. Here you are right about having only one public method. It wouldn't make sense to make public anything else. \$\endgroup\$
    – t3chb0t
    Jul 16, 2017 at 10:13
  • \$\begingroup\$ Updated! I see, but now that I've made them separated classes then I do need public methods right? Also for unit testing? I am always confused about when to use public or private tbh, I kind of go with "private until visual studio tells you otherwise" xD \$\endgroup\$
    – user123850
    Jul 16, 2017 at 10:18
0
\$\begingroup\$

Separation of UI into different classes as suggested, hopefully my code looks better and is more efficient now!

ConsoleUI.Menu.cs

namespace ConsoleUI
{
    public static class Menu
    {
        public static IPokemonGenerator PokemonGenerator;
        public static IPokemonLevelSystem LevelSystem;
        public static IPokemonWorld PokemonWorld;
        public static IGameState GameState;
        public static IRandomPokemonPicker PokemonPicker;
        public static IPlayersCollection Collection;
        public static IRivalsCollection RivalsCollection;

        public static CatchPokemon CatchPokemon;
        public static TrainPokemon TrainPokemon;
        public static FightRival FightRival;
        public static TeamHelper TeamHelper;

        public static MenuHelper MenuHelper;

        private static bool _gameIsOn;

        public static void Main()
        {
            GameSetup();
            Run();
        }

        public static void GameSetup()
        {
            PokemonWorld = new PokemonWorld();
            PokemonGenerator = new PokemonGenerator();
            LevelSystem = new PokemonLevelSystem();

            PokemonWorld.Populate(PokemonGenerator, PokemonGenerator.Generate().Count());

            PokemonPicker = new RandomPokemonPicker(PokemonWorld);

            RivalsCollection = new RivalsCollection(PokemonWorld);
            Collection = new PlayersCollection(PokemonWorld, PokemonPicker);

            MenuHelper = new MenuHelper(Collection, RivalsCollection, LevelSystem);
            TeamHelper = new TeamHelper(Collection, RivalsCollection);

            CatchPokemon = new CatchPokemon(Collection, PokemonPicker, TeamHelper);
            TrainPokemon = new TrainPokemon(Collection, LevelSystem, TeamHelper);
            FightRival = new FightRival(Collection, RivalsCollection, TeamHelper);

            _gameIsOn = true;

            GameState = new GameState();
            GameState.LoadGame(Collection, PokemonPicker);
        }

        public static void Run()
        {
            while (_gameIsOn)
            {
                MenuHelper.DisplayMenu();

                var choice = Console.ReadLine();

                while (MenuHelper.Choices.All(n => n.Value != choice))
                {
                    Console.WriteLine(
                        $"\nPlease type '{MenuHelper.CatchWildPokemon}', " +
                        $"'{MenuHelper.TrainPokemon}' " +
                        $"or '{MenuHelper.FightRival}', " +
                        $"or exit typing '{MenuHelper.Exit}'.\n");

                    choice = Console.ReadLine();
                }

                if (choice == MenuHelper.Exit)
                {
                    GameState.SaveGame(Collection.GetCollection(), PokemonPicker.GetCurrentPopulation());
                    _gameIsOn = false;
                    break;
                }

                PlayerChoice(choice);
            }
            Console.WriteLine("");
        }

        public static void PlayerChoice(string choice)
        {
            if (choice == MenuHelper.CatchWildPokemon)
            {
                if (MenuHelper.AreRequirementsMetToCatchPokemon())
                    CatchPokemon.ChoiceCatchWildPokemon();
            }

            else if (choice == MenuHelper.TrainPokemon)
            {
                if (MenuHelper.AreRequirementsMetToTrainPokemon())
                    TrainPokemon.ChoiceTrainPokemon();
            }

            else if (choice == MenuHelper.FightRival)
            {
                if (MenuHelper.AreRequirementsMetToFightRival())
                    FightRival.ChoiceFightRival();
            }
            else
            {
                throw new Exception("Unexpected error occurred. Player's choice is invalid.");
            }
        }
    }
}

MenuHelper

public class MenuHelper
    {
        public static Dictionary<string, string> Choices =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                {"CatchWildPokemon", "1"},
                {"TrainPokemon", "2"},
                {"FightRival", "3"},
                {"Exit", "4"}
            };

        public string CatchWildPokemon = Choices["CatchWildPokemon"];

        public IPlayersCollection Collection;
        public string Exit = Choices["Exit"];
        public string FightRival = Choices["FightRival"];
        public IPokemonLevelSystem LevelSystem;
        public IRivalsCollection RivalsCollection;
        public string TrainPokemon = Choices["TrainPokemon"];

        public MenuHelper(IPlayersCollection collection, IRivalsCollection rivalsCollection,
            IPokemonLevelSystem levelSystem)
        {
            Debug.Assert(collection != null, "Collection is null");
            Debug.Assert(levelSystem != null, "Level system is null");
            Debug.Assert(rivalsCollection != null, "Rival's collection is null");

            Collection = collection;
            LevelSystem = levelSystem;
            RivalsCollection = rivalsCollection;
        }

        public void DisplayMenu()
        {
            Console.WriteLine("\nWhat do you want to do?\n");
            Console.WriteLine($"{CatchWildPokemon}. Catch wild pokémon");
            Console.WriteLine($"{TrainPokemon}. Train your pokémon in gym");
            Console.WriteLine($"{FightRival}. Fight rival [Min level: {RivalsCollection.MinLevel}]");
            Console.WriteLine($"{Exit}. Exit");
            Console.WriteLine("");
        }

        public bool AreRequirementsMetToCatchPokemon()
        {
            if (!Collection.IsCompleted) return true;

            Console.WriteLine("\nYou've caught all wild pokémon!");
            return false;
        }

        public bool AreRequirementsMetToTrainPokemon()
        {
            if (Collection.IsEmpty)
            {
                Console.WriteLine("\nYou haven't caught any pokémon yet!");
                return false;
            }
            if (Collection.GetCollection().Any(p => p.Level < LevelSystem.MaxLevel)) return true;

            Console.WriteLine("\nAll your pokémon have reached max level!");
            return false;
        }

        public bool AreRequirementsMetToFightRival()
        {
            if (Collection.IsEmpty)
            {
                Console.WriteLine("\nYou haven't caught any pokémon yet!");
                return false;
            }
            if (Collection.GetCollection().Any(p => p.Level >= RivalsCollection.MinLevel)) return true;

            Console.WriteLine("\nAt least one of your pokémon must meet this rival's minimum level requirement.");
            Console.WriteLine("Try leveling up some pokémon at the gym first!");
            return false;
        }
    }

TeamHelper

public class TeamHelper
    {
        public IPlayersCollection Collection;
        public IRivalsCollection RivalsCollection;

        public TeamHelper(IPlayersCollection collection, IRivalsCollection rivalsCollection)
        {
            Debug.Assert(collection != null, "Collection is null.");
            Debug.Assert(rivalsCollection != null, "Rival's collection is null.");

            Collection = collection;
            RivalsCollection = rivalsCollection;
        }

        public void DisplayCollection()
        {
            Console.WriteLine($"\nPokémon in your collection:\n\n{DisplayOwnedPokemon()}");
        }

        public string PokemonInfo(Pokemon pokemon)
        {
            return pokemon != null
                ? $"{pokemon.Name} => " +
                  $"Type: {GetFormattedTypes(pokemon)} | " +
                  $"Level: {pokemon.Level} | " +
                  $"Exp: {pokemon.Exp}"
                : "Unexpected error occurred. Pokémon is null.";
        }

        public string DisplayTeam(IEnumerable<Pokemon> team)
        {
            if (team == null) throw new NullReferenceException("Unexpected error occurred. Team is null.");

            return string.Join("\n", team.Select(PokemonInfo).ToList());
        }

        public string GetFormattedTypes(Pokemon pokemon)
        {
            if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

            return string.Join(", ", pokemon.Type.Select(t => t.Name));
        }

        public string ChosenPokemon(int max)
        {
            if (max <= 1)
                throw new NullReferenceException("Unexpected error occurred. " +
                                                 "Maximum number of pokémon per team must be bigger than 1.");

            Console.WriteLine(
                "\nType the name of a pokémon from your collection that you'd like to add to your team.");
            Console.WriteLine($"You must add between 1 and {max} pokémon.\n");

            var chosenPokemon = Console.ReadLine();

            if (string.IsNullOrWhiteSpace(chosenPokemon)) return "";

            chosenPokemon = FormatChosenPokemon(chosenPokemon);

            return chosenPokemon;
        }

        public string FormatChosenPokemon(string chosenPokemon)
        {
            chosenPokemon = chosenPokemon?.Trim().ToLowerInvariant()
                            ?? throw new NullReferenceException("Unexpected error occurred. Chosen pokémon is null.");
            chosenPokemon = chosenPokemon.First().ToString().ToUpperInvariant() + chosenPokemon.Substring(1);
            return chosenPokemon;
        }

        public bool AddAnotherPokemonToTeam()
        {
            return UserInput.Confirm("\nDo you want to add another pokémon?");
        }

        public string DisplayOwnedPokemon()
        {
            return string.Join("\n", Collection.GetCollection().Select(PokemonInfo).ToList());
        }

        public void AddSingleDefaultPokemonToTeam(ICollection<Pokemon> team)
        {
            team.Add(Collection.GetCollection().First());
        }

        public void SetTeam(ICollection<Pokemon> team, int max, bool fightingRival = false,
            FightRival fightRival = null)
        {
            if (max < 1)
                throw new Exception("Unexpected error occurred." +
                                    "Maximum number of pokémon per team must be at least 1.");

            var isValidPokemon = false;

            do
            {
                if (team.Count == max || team.Count == Collection.GetCollection().Count)
                    break;

                if (fightingRival)
                    if (fightRival != null && !fightRival.ArePokemonWithValidLevelLeftInCollection())
                        break;

                if (team.Count > 0 && isValidPokemon)
                {
                    Console.WriteLine($"\nCurrent team:\n\n{DisplayTeam(team)}");

                    if (fightingRival)
                        if (fightRival != null && !fightRival.ArePokemonWithValidLevelLeftInCollection())
                            break;
                    if (!AddAnotherPokemonToTeam())
                        break;
                }

                do
                {
                    var chosenPokemon = ChosenPokemon(max);

                    isValidPokemon = IsChosenPokemonValid(chosenPokemon, team, fightingRival);
                    if (isValidPokemon) AddPokemonToTeam(chosenPokemon, team);
                } while (!isValidPokemon);
            } while (true);
        }

        public bool IsChosenPokemonValid(string chosenPokemon, ICollection<Pokemon> team, bool fightingRival = false)
        {
            if (string.IsNullOrWhiteSpace(chosenPokemon))
                return false;

            if (Collection.GetCollection().All(p => p.Name != chosenPokemon))
                return false;

            if (team.All(p => p.Name != chosenPokemon))
            {
                if (!fightingRival) return true;

                var pokemon = Collection.GetCollection().FirstOrDefault(p => p.Name == chosenPokemon);

                if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

                var chosenPokemonLvl = pokemon.Level;
                if (chosenPokemonLvl >= RivalsCollection.MinLevel)
                    return true;
                Console.WriteLine("\nThis pokémon's level is below Rival's level requirement.");
                return false;
            }

            Console.WriteLine($"\nYou already added {chosenPokemon}.");
            return false;
        }

        public void AddPokemonToTeam(string chosenPokemon, ICollection<Pokemon> team)
        {
            if (chosenPokemon == null)
                throw new NullReferenceException("Unexpected error occurred. Null pokémon string given.");

            var chosenPokemonFromCollection = Collection.GetCollection()
                .SingleOrDefault(p => p.Name == chosenPokemon);

            if (chosenPokemonFromCollection == null)
                throw new NullReferenceException("Unexpected error occurred. There is no such pokémon in World.");

            team.Add(chosenPokemonFromCollection);
        }
    }

UserInput

public static class UserInput
    {
        public static readonly Dictionary<string, string> YesOrNo =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                {"Yes", "Y"},
                {"No", "N"}
            };

        public static readonly string Y = YesOrNo["Yes"];
        public static readonly string N = YesOrNo["No"];

        public static bool Confirm(string prompt)
        {
            do
            {
                Console.WriteLine($"{prompt} ({Y}/{N})");
                var input = Console.ReadLine();

                if (string.Equals(input, Y, StringComparison.InvariantCultureIgnoreCase))
                    return true;

                if (string.Equals(input, N, StringComparison.InvariantCultureIgnoreCase))
                    return false;
            } while (true);
        }
    }

CatchPokemon

public class CatchPokemon
    {
        public IPlayersCollection Collection;
        public IRandomPokemonPicker PokemonPicker;
        public TeamHelper TeamHelper;

        public CatchPokemon(IPlayersCollection collection,
            IRandomPokemonPicker pokemonPicker,
            TeamHelper teamHelper)
        {
            Debug.Assert(pokemonPicker != null, "Pokemon picker is null.");
            Debug.Assert(collection != null, "Player's collection is null.");
            Debug.Assert(teamHelper != null, "Team helper is null.");

            PokemonPicker = pokemonPicker;
            Collection = collection;
            TeamHelper = teamHelper;
        }

        private static void CatchWildPokemonTextIntro()
        {
            Console.WriteLine("\nTime to catch some pokémon!");
            Console.WriteLine("Let's explore this area.");
        }

        public void ChoiceCatchWildPokemon()
        {
            CatchWildPokemonTextIntro();
            Console.ReadKey();

            while (true)
            {
                var wildPokemon = Collection.GetWildPokemon();

                Console.WriteLine($"\nYou find a wild pokémon. It's a {wildPokemon.Name}. Let's catch it!");
                Console.ReadKey();
                Console.WriteLine($"\nFighting {wildPokemon.Name}...");
                Console.ReadKey();

                if (IsCatchSuccessful())
                {
                    Collection.AddToCollection(wildPokemon);
                    PokemonPicker.RemoveFromCurrentPopulation();

                    Console.WriteLine($"\nAwesome! You caught {TeamHelper.PokemonInfo(wildPokemon)}");
                }
                else
                {
                    Console.WriteLine($"\nOh no! {wildPokemon.Name} escaped!");
                }

                if (Collection.GetCollection().Count > 0)
                    Console.WriteLine($"\nPokémon in your collection:\n\n{TeamHelper.DisplayOwnedPokemon()}");

                if (!UserInput.Confirm("\nDo you want to keep catching pokémons?"))
                    break;

                if (!Collection.IsCompleted) continue;

                Console.WriteLine("\nYou've caught all wild pokémon!");
                break;
            }
        }

        private static bool IsCatchSuccessful()
        {
            return new Random().Next(100) >= 50;
        }
    }

TrainPokemon

public class TrainPokemon
    {
        private bool _training;

        public IPlayersCollection Collection;
        public ICollection<Pokemon> GymTeam = new List<Pokemon>();
        public IPokemonLevelSystem LevelSystem;
        public TeamHelper TeamHelper;

        public TrainPokemon(IPlayersCollection collection, IPokemonLevelSystem levelSystem,
            TeamHelper teamHelper)
        {
            Debug.Assert(collection != null, "Collection is null.");
            Debug.Assert(levelSystem != null, "Level system is null.");
            Debug.Assert(teamHelper != null, "Team helper is null.");

            Collection = collection;
            LevelSystem = levelSystem;
            TeamHelper = teamHelper;
        }

        public void ChoiceTrainPokemon()
        {
            TrainPokemonTextIntro();
            _training = true;

            while (_training)
            {
                TeamHelper.DisplayCollection();

                if (Collection.GetCollection().Count == 1)
                {
                    if (!GymTeam.Any()) TeamHelper.AddSingleDefaultPokemonToTeam(GymTeam);
                }
                else
                {
                    TeamHelper.SetTeam(GymTeam, 6);
                }
                TrainChosenTeam();
                GymTeam.Clear();
            }

            GymTeam.Clear();
        }

        public void TrainChosenTeam()
        {
            do
            {
                TrainedTeamResults();

                if (TrainAgain())
                {
                    if (GymTeam.Count == 1 && Collection.GetCollection().Count == 1)
                        break;
                    if (!TrainSameTeam())
                        break;
                }
                else
                {
                    _training = false;
                    break;
                }
            } while (true);
        }

        public void TrainedTeamResults()
        {
            Console.WriteLine("\nTraining...\n");
            Console.ReadKey();

            foreach (var pokemon in GymTeam)
            {
                LevelSystem.IncreaseExp(pokemon);

                if (LevelSystem.HasReachedMaxLevel(pokemon))
                    Console.WriteLine($"{pokemon.Name} has reached max level! ");
                else
                    Console.WriteLine(LevelSystem.HasLeveledUp(pokemon)
                        ? $"{pokemon.Name} has leveled up!"
                        : $"{pokemon.Name} has gained experience!");
            }

            Console.WriteLine($"\n{TeamHelper.DisplayTeam(GymTeam)}");
        }

        public void TrainPokemonTextIntro()
        {
            Console.WriteLine("\nTime to head to pokémon gym!");
            Console.WriteLine("Let's level up some pokémon.");
        }

        public bool TrainAgain()
        {
            return UserInput.Confirm("\nDo you want to train again?");
        }

        public bool TrainSameTeam()
        {
            return UserInput.Confirm("\nTrain the same pokémon?");
        }
}

FightRival

public class FightRival
    {
        private static bool _fightingRival;
        private static int _wins;
        private static int _ties;
        private static int _losses;

        public readonly ICollection<Pokemon> FightingTeam = new List<Pokemon>();
        public readonly IList<Pokemon> RivalsTeam = new List<Pokemon>();

        public IPlayersCollection Collection;
        public IRivalsCollection RivalsCollection;
        public TeamHelper TeamHelper;

        public FightRival(IPlayersCollection collection, IRivalsCollection rivalsCollection,
            TeamHelper teamHelper)
        {
            Debug.Assert(collection != null, "Player's collection is null.");
            Debug.Assert(rivalsCollection != null, "Rival's collection is null.");
            Debug.Assert(teamHelper != null, "Team helper is null.");

            Collection = collection;
            RivalsCollection = rivalsCollection;
            TeamHelper = teamHelper;
        }

        private static void FightRivalTextIntro()
        {
            Console.WriteLine("\nTime to battle!");
            Console.WriteLine("Let's become a Pokémon Master.");
        }

        public void ChoiceFightRival()
        {
            FightRivalTextIntro();
            _fightingRival = true;

            while (_fightingRival)
            {
                TeamHelper.DisplayCollection();

                if (Collection.GetCollection().Count == 1)
                {
                    if (!FightingTeam.Any())
                        TeamHelper.AddSingleDefaultPokemonToTeam(FightingTeam);
                }
                else
                {
                    TeamHelper.SetTeam(FightingTeam, 4, _fightingRival, this);
                }

                FightRivalWithChosenTeam();
            }
            ResetFightRivalVariables();
            _fightingRival = false;
        }

        public void AssignOpponents()
        {
            foreach (var pokemon in RivalsCollection.GetTeam())
                RivalsTeam.Add(pokemon);

            var random = new Random();

            foreach (var pokemon in FightingTeam)
            {
                var opponentId = random.Next(RivalsTeam.Count);
                pokemon.Opponent = RivalsTeam[opponentId];
                RivalsTeam.RemoveAt(opponentId);
            }
        }

        public void SetTeamChanceAgainstTheirOpponents()
        {
            if (FightingTeam == null)
                throw new NullReferenceException("Unexpected error occurred. Fighting team is null.");

            var chanceByType = new SuccessChanceByPokemonTypes();

            foreach (var pokemon in FightingTeam)
                pokemon.SuccessChance = chanceByType.GetChance(pokemon.Type, pokemon.Opponent.Type);
        }

        public void FightRivalWithChosenTeam()
        {
            do
            {
                AssignOpponents();
                SetTeamChanceAgainstTheirOpponents();
                BattleStartText();
                BattleResults();

                if (FightRivalAgain())
                {
                    if (FightingTeam.Count == 1 && Collection.GetCollection().Count == 1)
                    {
                        ResetFightRivalVariables(true);
                        break;
                    }

                    if (FightingTeam.Count == 1 && !ArePokemonWithValidLevelLeftInCollection())
                    {
                        ResetFightRivalVariables(true);
                        break;
                    }

                    if (FightRivalWithSameTeam())
                    {
                        ResetFightRivalVariables(true);
                    }
                    else
                    {
                        ResetFightRivalVariables();
                        break;
                    }
                }
                else
                {
                    _fightingRival = false;
                    break;
                }
            } while (true);
        }

        public void BattleStartText()
        {
            Console.WriteLine("\nLet's battle!");
            Console.ReadKey();

            if (FightingTeam == null)
                throw new NullReferenceException("Unexpected error occurred. Fighting team is null.");

            foreach (var pokemon in FightingTeam)
            {
                Console.WriteLine($"\n{pokemon.Name} was matched against {pokemon.Opponent.Name}.");
                Console.WriteLine($"{pokemon.Name} is type {TeamHelper.GetFormattedTypes(pokemon)}, " +
                                  $"while {pokemon.Opponent.Name} is type {TeamHelper.GetFormattedTypes(pokemon.Opponent)}.");
                Console.ReadKey();
                DisplaySuccessChanceMessage(pokemon, pokemon.SuccessChance);
                Console.ReadKey();
            }
        }

        public void DisplaySuccessChanceMessage(Pokemon pokemon, int chance)
        {
            if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

            switch (chance)
            {
                case 50:
                    Console.WriteLine($"{pokemon.Name} will do average damage to {pokemon.Opponent.Name}.");
                    Console.WriteLine("It's a 50/50 match!");
                    break;
                case -1:
                    Console.WriteLine(
                        $"{pokemon.Name} and {pokemon.Opponent.Name} cannot do any damage to each other.");
                    Console.WriteLine("It's a tie!");
                    break;
                case 0:
                    Console.WriteLine($"{pokemon.Name} cannot do any damage to {pokemon.Opponent.Name}.");
                    Console.WriteLine($"{pokemon.Name} loses!");
                    break;
                case 20:
                    Console.WriteLine($"{pokemon.Name} is weak against {pokemon.Opponent.Name}.");
                    Console.WriteLine($"{pokemon.Name} has a small chance of winning.");
                    break;
                case 80:
                    Console.WriteLine($"{pokemon.Name} is super effective against {pokemon.Opponent.Name}.");
                    Console.WriteLine($"{pokemon.Name} has a big chance of winning.");
                    break;
                default:
                    throw new Exception("Unexpected error occurred. Pokémon's success chance is an invalid integer.");
            }
        }

        public void BattleResults()
        {
            if (IsMatchAutomaticallyOver())
            {
                DisplayAutomaticMatchResultMessage();
            }
            else
            {
                OngoingBattles();
                DisplayMatchResults();
                DisplayMatchResultMessage();
            }
        }

        // Automatic match result


        public void DisplayAutomaticMatchResultMessage()
        {
            if (IsMatchAutomaticallyATie())
                Console.WriteLine("\nYour match against Rival ended in a tie.");
            else if (IsMatchAutomaticallyALoss())
                Console.WriteLine("\nYou were defeated by Rival.");
        }

        // Random battles result

        public void OngoingBattles()
        {
            Console.WriteLine("\nFighting...\n");

            foreach (var pokemon in FightingTeam)
                if (IsDraw(pokemon))
                {
                    _ties++;
                }
                else if (IsWin(pokemon))
                {
                    Console.WriteLine($"Cool! {pokemon.Name} won!");
                    _wins++;
                }
                else
                {
                    Console.WriteLine($"Oh no! {pokemon.Name} lost!");
                    _losses++;
                }
        }

        public bool IsDraw(Pokemon pokemon)
        {
            if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

            return pokemon.SuccessChance == -1;
        }

        public bool IsWin(Pokemon pokemon)
        {
            if (pokemon == null) throw new NullReferenceException("Unexpected error occurred. Pokémon is null.");

            var random = new Random();
            return random.Next(100) < pokemon.SuccessChance;
        }

        // Match result

        public void DisplayMatchResults()
        {
            if (_wins <= 0 && _losses <= 0 && _ties <= 0)
                throw new Exception("Unexpected error occurred. Invalid battle results.");
            Console.WriteLine($"\nWins: {_wins}");
            Console.WriteLine($"Losses: {_losses}");
            if (_ties > 0)
                Console.WriteLine($"Ties: {_ties}");
        }

        public void DisplayMatchResultMessage()
        {
            Console.WriteLine(_wins == FightingTeam.Count
                ? "\nCongrats! You defeated Rival."
                : "\nYou did not defeat Rival.");
        }

        public void ResetFightRivalVariables(bool sameTeam = false)
        {
            if (!sameTeam)
                FightingTeam.Clear();

            foreach (var pokemon in FightingTeam)
            {
                pokemon.SuccessChance = 50;
                pokemon.Opponent = null;
            }
            RivalsTeam.Clear();
            _wins = 0;
            _losses = 0;
            _ties = 0;
        }

        public bool ArePokemonWithValidLevelLeftInCollection()
        {
            var pokemonLeftInCollection = Collection.GetCollection().Select(p => p)
                .Except(FightingTeam.Select(p => p));

            return pokemonLeftInCollection.Any(p => p.Level >= RivalsCollection.MinLevel);
        }

        public bool IsMatchAutomaticallyATie()
        {
            return FightingTeam.All(p => p.SuccessChance == -1);
        }

        public bool IsMatchAutomaticallyALoss()
        {
            return FightingTeam.All(p => p.SuccessChance == 0);
        }

        public bool IsMatchAutomaticallyOver()
        {
            return IsMatchAutomaticallyATie() || IsMatchAutomaticallyALoss();
        }

        public bool FightRivalAgain()
        {
            return UserInput.Confirm("\nDo you want to fight this rival again?");
        }

        public bool FightRivalWithSameTeam()
        {
            return UserInput.Confirm("\nFight with the same pokémon?");
        }
    }
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.