private async Task DoEvolveAsync(ulong userId, SQLiteDatabase database, IEnumerable <Gotchi> userGotchis)
        {
            // Gotchi evolution (time-based)

            foreach (Gotchi gotchi in userGotchis)
            {
                if (gotchi.CanEvolve)
                {
                    await database.EvolveAndUpdateGotchiAsync(gotchi);
                }
            }
        }
        public static async Task <BattleGotchi> GenerateGotchiAsync(this SQLiteDatabase database, GotchiGenerationParameters parameters)
        {
            BattleGotchi result = new BattleGotchi();

            if (!(parameters.Base is null))
            {
                // If a base gotchi was provided, copy over some of its characteristics.

                result.Gotchi.BornTimestamp    = parameters.Base.BornTimestamp;
                result.Gotchi.DiedTimestamp    = parameters.Base.DiedTimestamp;
                result.Gotchi.EvolvedTimestamp = parameters.Base.EvolvedTimestamp;
                result.Gotchi.FedTimestamp     = parameters.Base.FedTimestamp;
            }

            // Select a random base species to start with.

            ISpecies species = parameters.Species;

            if (species is null)
            {
                IEnumerable <ISpecies> base_species_list = await database.GetBaseSpeciesAsync();

                if (base_species_list.Count() > 0)
                {
                    species = base_species_list.ElementAt(NumberUtilities.GetRandomInteger(0, base_species_list.Count()));
                }
            }

            if (species != null)
            {
                result.Gotchi.SpeciesId = (long)species.Id;
            }

            // Evolve it the given number of times.

            for (int i = 0; i < parameters.MaxEvolutions; ++i)
            {
                if (!await database.EvolveAndUpdateGotchiAsync(result.Gotchi))
                {
                    break;
                }
            }

            // Generate stats (if applicable).

            if (parameters.GenerateStats)
            {
                result.Gotchi.Experience = GotchiExperienceCalculator.ExperienceToLevel(result.Stats.ExperienceGroup, NumberUtilities.GetRandomInteger(parameters.MinLevel, parameters.MaxLevel + 1));

                result.Stats = await new GotchiStatsCalculator(database, Global.GotchiContext).GetStatsAsync(result.Gotchi);
            }

            // Generate moveset (if applicable).

            if (parameters.GenerateMoveset)
            {
                result.Moves = await Global.GotchiContext.MoveRegistry.GetMoveSetAsync(database, result.Gotchi);
            }

            // Generate types.
            result.Types = await Global.GotchiContext.TypeRegistry.GetTypesAsync(database, result.Gotchi);

            // Generate a name for the gotchi.

            result.Gotchi.Name = (species is null ? "Wild Gotchi" : species.GetShortName()) + string.Format(" (Lv. {0})", result.Stats is null ? 1 : result.Stats.Level);

            return(result);
        }
 public static async Task <bool> EvolveAndUpdateGotchiAsync(this SQLiteDatabase database, Gotchi gotchi)
 {
     return(await database.EvolveAndUpdateGotchiAsync(gotchi, string.Empty));
 }
        private async Task _endBattle(ICommandContext context)
        {
            PlayerState winner = player1.Gotchi.Stats.Hp <= 0.0 ? player2 : player1;
            PlayerState loser  = player1.Gotchi.Stats.Hp <= 0.0 ? player1 : player2;

            // Calculate the amount of EXP awarded to the winner.
            // The loser will get 50% of the winner's EXP.

            double exp = _getExpEarned(winner.Gotchi.Gotchi, loser.Gotchi.Gotchi, won: true);

            double exp1 = player2.Gotchi.Stats.Hp <= 0.0 ? exp : exp * .5;
            double exp2 = player1.Gotchi.Stats.Hp <= 0.0 ? exp : exp * .5;

            long levels1 = player1.Gotchi.Stats.AddExperience((int)exp1);
            long levels2 = player2.Gotchi.Stats.AddExperience((int)exp2);

            StringBuilder sb = new StringBuilder();

            sb.AppendLine(battleText);

            // Show the winner's accomplishments, then the loser's.

            if (!IsCpuGotchi(winner.Gotchi.Gotchi))
            {
                double winner_exp    = winner.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? exp1 : exp2;
                long   winner_levels = winner.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? levels1 : levels2;
                long   winner_g      = (long)Math.Round(loser.Gotchi.Stats.Level * (NumberUtilities.GetRandomInteger(150, 200) / 100.0));

                sb.AppendLine(string.Format("🏆 **{0}** won the battle! Earned **{1} EXP** and **{2}G**.",
                                            winner.Gotchi.Gotchi.Name,
                                            winner_exp,
                                            winner_g));

                if (winner_levels > 0)
                {
                    sb.AppendLine(string.Format("🆙 **{0}** leveled up to level **{1}**!", winner.Gotchi.Gotchi.Name, winner.Gotchi.Stats.Level));
                }

                if (((winner.Gotchi.Stats.Level - winner_levels) / 10) < (winner.Gotchi.Stats.Level / 10))
                {
                    if (await database.EvolveAndUpdateGotchiAsync(winner.Gotchi.Gotchi))
                    {
                        ISpecies sp = await database.GetSpeciesAsync(winner.Gotchi.Gotchi.SpeciesId);

                        sb.AppendLine(string.Format("🚩 Congratulations, **{0}** evolved into **{1}**!", winner.Gotchi.Gotchi.Name, sp.GetShortName()));
                    }
                }

                // Update the winner's G.

                GotchiUserInfo user_data = await database.GetUserInfoAsync(winner.Gotchi.Gotchi.OwnerId);

                user_data.G += winner_g;

                await database.UpdateUserInfoAsync(user_data);

                sb.AppendLine();
            }

            if (!IsCpuGotchi(loser.Gotchi.Gotchi))
            {
                double loser_exp    = loser.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? exp1 : exp2;
                long   loser_levels = loser.Gotchi.Gotchi.Id == player1.Gotchi.Gotchi.Id ? levels1 : levels2;

                sb.AppendLine(string.Format("💀 **{0}** lost the battle... Earned **{1} EXP**.", loser.Gotchi.Gotchi.Name, loser_exp));

                if (loser_levels > 0)
                {
                    sb.AppendLine(string.Format("🆙 **{0}** leveled up to level **{1}**!", loser.Gotchi.Gotchi.Name, loser.Gotchi.Stats.Level));
                }

                if (((loser.Gotchi.Stats.Level - loser_levels) / 10) < (loser.Gotchi.Stats.Level / 10))
                {
                    if (await database.EvolveAndUpdateGotchiAsync(loser.Gotchi.Gotchi))
                    {
                        ISpecies sp = await database.GetSpeciesAsync(loser.Gotchi.Gotchi.SpeciesId);

                        sb.AppendLine(string.Format("🚩 Congratulations, **{0}** evolved into **{1}**!", loser.Gotchi.Gotchi.Name, sp.GetShortName()));
                    }
                }
            }

            // Update exp in the database.

            using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET level=$level, exp=$exp WHERE id=$id;")) {
                cmd.Parameters.AddWithValue("$id", player1.Gotchi.Gotchi.Id);
                cmd.Parameters.AddWithValue("$level", DBNull.Value);
                cmd.Parameters.AddWithValue("$exp", player1.Gotchi.Stats.Experience);

                await database.ExecuteNonQueryAsync(cmd);
            }

            if (!IsCpuGotchi(player2.Gotchi.Gotchi))
            {
                using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET level=$level, exp=$exp WHERE id=$id;")) {
                    cmd.Parameters.AddWithValue("$id", player2.Gotchi.Gotchi.Id);
                    cmd.Parameters.AddWithValue("$level", DBNull.Value);
                    cmd.Parameters.AddWithValue("$exp", player2.Gotchi.Stats.Experience);

                    await database.ExecuteNonQueryAsync(cmd);
                }
            }

            // Deregister the battle state.

            DeregisterBattle(context.User.Id);

            battleText = sb.ToString();
        }