/// <summary>
 /// Produces an army with the given composition and a corresponding sprite by the given cellTypeId.
 /// </summary>
 private void InitializeCellById(byte cellTypeId, ArmyComposition armyComposition,
                                 out Army army, out Sprite sprite)
 {
     army   = null;
     sprite = null;
     if (cellTypeId == firstPlayerCellId)
     {
         army   = new UserArmy(PlayerType.FIRST, armyComposition);
         sprite = firstUserSprite;
     }
     else if (cellTypeId == secondPlayerCellId)
     {
         army   = new UserArmy(PlayerType.SECOND, armyComposition);
         sprite = secondUserSprite;
     }
     else if (cellTypeId == neutralFriendlyCellId)
     {
         army   = new NeutralFriendlyArmy(armyComposition);
         sprite = neutralFriendlySprite;
     }
     else if (cellTypeId == neutralAggressiveCellId)
     {
         army   = new NeutralAggressiveArmy(armyComposition);
         sprite = neutralAggressiveSprite;
     }
 }
        /// <summary>
        /// Checks that first army is more powerful than second.
        /// </summary>
        public static bool IsFirstWinner(ArmyComposition firstArmyComposition,
                                         ArmyComposition secondArmyComposition)
        {
            var firstArmyPower  = firstArmyComposition.ArmyPower();
            var secondArmyPower = secondArmyComposition.ArmyPower();

            return(firstArmyPower >= secondArmyPower);
        }
 protected Army(ArmyType armyType, PlayerType playerType, ArmyComposition armyComposition)
 {
     this.armyType   = armyType;
     PlayerType      = playerType;
     ArmyComposition = armyComposition;
     if (!CheckValidTypes())
     {
         throw new Exception("In Army constructor incompatible types were received");
     }
 }
 private void UpdateImbalance(ArmyComposition resultArmyComposition)
 {
     if (imbalance < 0)
     {
         imbalance += resultArmyComposition.TotalUnitQuantity();
     }
     else
     {
         imbalance -= resultArmyComposition.TotalUnitQuantity();
     }
 }
        /// <summary>
        /// Merges two army compositions.
        /// The old experience is uniformly distributed among the total number of units in each army.
        /// </summary>
        public static ArmyComposition Merge(ArmyComposition first, ArmyComposition second)
        {
            var newExperience = (first.TotalUnitQuantity() * first.Experience +
                                 second.TotalUnitQuantity() * second.Experience) /
                                (first.TotalUnitQuantity() + second.TotalUnitQuantity());

            return(new ArmyComposition(first.Spearmen + second.Spearmen,
                                       first.Archers + second.Archers,
                                       first.Cavalrymen + second.Cavalrymen,
                                       newExperience));
        }
        /// <summary>
        /// Performs a fight between two army compositions.
        /// Updates the experience of the winner army.
        /// </summary>
        /// <param name="winnerArmyComposition"></param>
        /// <param name="loserArmyComposition"></param>
        /// <returns></returns>
        public static ArmyComposition Fight(ArmyComposition winnerArmyComposition,
                                            ArmyComposition loserArmyComposition)
        {
            var powerDifference = winnerArmyComposition.ArmyPower() - loserArmyComposition.ArmyPower();

            //The losses have the square root dependency.
            var mortalityRate = Math.Sqrt(powerDifference / winnerArmyComposition.ArmyPower());

            //The experience increased quadratically, based on the relative power of armies.
            //Quadratic dependency mainly to decrease the huge role of the experience at the final part of the game.
            var experienceIncrease = 1 + Math.Pow(loserArmyComposition.ArmyPower() / winnerArmyComposition.ArmyPower(), 2);

            return(winnerArmyComposition.ArmyCompositionAfterFight(mortalityRate,
                                                                   winnerArmyComposition.Experience * experienceIncrease));
        }