Ejemplo n.º 1
0
        /// <summary>
        /// Handles pre-turn claculations, like building and research completitions, and income.
        /// Returns the <see cref="CountryModifierBuilder"/> containing the modifications for the country.
        /// </summary>
        /// <param name="context">The <see cref="UnderSeaDatabaseContext"/> that is used to access the database.</param>
        /// <param name="country">The country to handle. The following must be included: Buildings, In progress buildings,
        /// researches, in progress researches, the buildings and researches of these, events, and the corresponding effects, commands, divisions and units.</param>
        /// <param name="globals">The <see cref="GlobalValue"/>s to use.</param>
        /// <param name="allEvents">The collection of all events that may occur.</param>
        /// <param name="cancel">The <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
        /// <exception cref="ArgumentNullException">Thrown if an argument was null.</exception>
        public void HandlePreCombat(UnderSeaDatabaseContext context, Model.Entities.Country country,
                                    GlobalValue globals, IList <RandomEvent> allEvents)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (country == null)
            {
                throw new KeyNotFoundException();
            }

            if (globals == null)
            {
                throw new ArgumentNullException(nameof(globals));
            }

            // #1: Add a random event
            if (country.CreatedRound + globals.RandomEventGraceTimer <= globals.Round &&
                rng.NextDouble() <= globals.RandomEventChance)
            {
                country.CurrentEvent = allEvents[rng.Next(allEvents.Count)];
            }
            else if (country.CurrentEvent != null)
            {
                country.CurrentEvent = null;
            }

            // Apply permanent effects here
            var builder = country.ParseAllEffectForCountry(context, globals, Parsers, true);

            if (builder.WasEventIgnored)
            {
                country.CurrentEvent = null;
            }

            // #2: Tax
            country.Pearls += (long)Math.Round(builder.Population * globals.BaseTaxation * builder.TaxModifier
                                               + builder.PearlProduction);

            // #3: Coral (harvest)
            country.Corals += (long)Math.Round(builder.CoralProduction * builder.HarvestModifier);

            // #4: Pay soldiers
            DesertUnits(country);

            // #5: Add buildings that are completed
            CheckAddCompleted(country);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Handles post-combat calculations for a country, like calculating the score, and merging commands into the defense command.
        /// </summary>
        /// <param name="context">The <see cref="UnderSeaDatabaseContext"/> that is used to access the database.</param>
        /// <param name="country">The country to handle. The commands, their divisions and units, buildings and researches, events, and their effects must be loaded.</param>
        /// <param name="globals">The <see cref="GlobalValue"/>s to use.</param>
        /// <exception cref="ArgumentNullException">Thrown if an argument was null.</exception>
        public void HandlePostCombat(UnderSeaDatabaseContext context, Model.Entities.Country country, GlobalValue globals)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (country == null)
            {
                throw new ArgumentNullException(nameof(country));
            }

            if (globals == null)
            {
                throw new ArgumentNullException(nameof(globals));
            }

            var builder = country.ParseAllEffectForCountry(context, globals, Parsers, false);

            long divisionScore = 0;

            foreach (var comm in country.Commands)
            {
                divisionScore += comm.Divisions.Sum(d => d.Count);
            }

            country.Score = (long)Math.Round(
                builder.Population * globals.ScorePopulationMultiplier
                + country.Buildings.Count * globals.ScoreBuildingMultiplier
                + divisionScore * globals.ScoreUnitMultiplier
                + country.Researches.Count * globals.ScoreResearchMultiplier);

            // Merge all attacking commands into the defense command, delete attacking commands, and add the loot
            var defenders = country.GetAllDefending();

            foreach (var attack in country.Attacks.Where(x => x.DidAttackerWin && x.Round == globals.Round))
            {
                country.Pearls += attack.PearlLoot;
                country.Corals += attack.CoralLoot;
            }

            foreach (var attack in country.Commands.Where(c => c.Id != defenders.Id).ToList())
            {
                attack.MergeInto(defenders, context);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Handles combat calculations for all incoming attacks of a country. The order of the attacks is randomized.
        /// </summary>
        /// <param name="context">The <see cref="UnderSeaDatabaseContext"/> that is used to access the database.</param>
        /// <param name="country">The country to handle. The commands, incoming attacks, the attack's divisions, parent country,
        /// parent country builidings, researches, events, and effects must be loaded.</param>
        /// <param name="globals">The <see cref="GlobalValue"/>s to use.</param>
        /// <exception cref="ArgumentNullException">Thrown if an argument was null.</exception>
        public void HandleCombat(UnderSeaDatabaseContext context, Model.Entities.Country country, GlobalValue globals)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (country == null)
            {
                throw new ArgumentNullException(nameof(country));
            }

            if (globals == null)
            {
                throw new ArgumentNullException(nameof(globals));
            }

            // Randomize the incoming attacks, excluding the defending forces
            var incomingAttacks = country.IncomingAttacks
                                  .Where(c => !c.ParentCountry.Equals(country))
                                  .Select(c => new { Order = rng.Next(), Command = c })
                                  .OrderBy(x => x.Order)
                                  .Select(x => x.Command)
                                  .ToList();

            var defenders = country.GetAllDefending();
            var builder   = country.ParseAllEffectForCountry(context, globals, Parsers, false);

            foreach (var attack in incomingAttacks)
            {
                (double attackPower, double attackMods, double attackBase) = GetCurrentUnitPower(attack, globals, true,
                                                                                                 attack.ParentCountry.ParseAllEffectForCountry(context, globals, Parsers, false));
                (double defensePower, double defenseMods, double defenseBase) = GetCurrentUnitPower(defenders, globals,
                                                                                                    false, builder);

                var losses = attackPower > defensePower
                    ? CullUnits(defenders, globals.UnitLossOnLostBatle)
                    : CullUnits(attack, globals.UnitLossOnLostBatle);

                var report = new CombatReport
                {
                    Attacker  = attack.ParentCountry,
                    Defender  = country,
                    Attackers = attack.Divisions.Select(d => new Division
                    {
                        Count = d.Count, Unit = d.Unit
                    }).ToList(),
                    Defenders = defenders.Divisions.Select(d => new Division
                    {
                        Count = d.Count, Unit = d.Unit
                    }).ToList(),
                    TotalAttackPower  = attackPower,
                    TotalDefensePower = defensePower,
                    AttackModifier    = attackMods,
                    DefenseModifier   = defenseMods,
                    BaseAttackPower   = attackBase,
                    BaseDefensePower  = defenseBase,
                    Round             = globals.Round,
                    PearlLoot         = 0,
                    CoralLoot         = 0,
                    Losses            = losses
                };

                if (attackPower > defensePower)
                {
                    var pearlLoot = (long)Math.Round(country.Pearls * globals.LootPercentage);
                    var coralLoot = (long)Math.Round(country.Corals * globals.LootPercentage);
                    country.Pearls  -= pearlLoot;
                    country.Corals  -= coralLoot;
                    report.CoralLoot = coralLoot;
                    report.PearlLoot = pearlLoot;
                }

                context.Reports.Add(report);
            }
        }