Example #1
0
        /// <summary>
        /// Display the results of a siege (that has been resolved due to a battle) in a human readable format
        /// </summary>
        /// <param name="battle">Results of battle</param>
        /// <returns>String describing battle</returns>
        public static String DisplaySiegeResults(ProtoBattle battle)
        {
            Contract.Requires(battle != null);
            string siegeDescription = "";

            if (battle.attackerVictorious || battle.retreatedArmies.Contains(battle.attackerOwner))
            {
                siegeDescription  = "On this day of Our Lord the forces of ";
                siegeDescription += battle.siegeDefender;
                siegeDescription += " have defeated the forces of " + battle.siegeBesieger;
                siegeDescription += ", relieving the siege of " + Globals_Game.fiefMasterList[battle.battleLocation].name + ".";
                siegeDescription += " " + battle.siegeDefender;
                siegeDescription += " retains ownership of the fief.";
            }
            if (battle.DefenderDeadNoHeir)
            {
                // construct event description to be passed into siegeEnd
                siegeDescription  = "On this day of Our Lord the forces of ";
                siegeDescription += battle.siegeBesieger;
                siegeDescription += " attacked the forces of " + battle.siegeDefender;
                siegeDescription += ", who was killed during the battle.";
                siegeDescription += "  Thus, despite losing the battle, " + battle.siegeBesieger;
                siegeDescription += " has succeeded in relieving the siege of " + Globals_Game.fiefMasterList[battle.battleLocation].name + ".";
                siegeDescription += " " + battle.siegeDefender;
                siegeDescription += " retains ownership of the fief.";
            }
            return(siegeDescription);
        }
Example #2
0
 public void DisplayAttack(ProtoBattle battleResults)
 {
     Console.WriteLine("-----------------------------");
     Console.WriteLine("Battle Overview");
     Console.WriteLine("-----------------------------");
     Console.WriteLine("Attacker leader: " + battleResults.attackerLeader);
     Console.WriteLine("Defender leader: " + battleResults.defenderLeader);
     Console.WriteLine("Attacker victorious:" + battleResults.attackerVictorious);
     Console.WriteLine("Attacker calsualties: " + battleResults.attackerCasualties);
     Console.WriteLine("Defender Casualties: " + battleResults.defenderCasualties);
     Console.WriteLine("Attacker stature change: " + battleResults.statureChangeAttacker);
     Console.WriteLine("Defender stature change: " + battleResults.statureChangeDefender);
     if (battleResults.attackerAllies.Count > 0 && battleResults.attackerAllies != null)
     {
         Console.WriteLine("Attacker allies participating in the battle: ");
         for (int i = 0; i < battleResults.attackerAllies.Count; i++)
         {
             Console.Write(battleResults.attackerAllies[i]);
             if (i != battleResults.attackerAllies.Count - 1)
             {
                 Console.Write(", ");
             }
             else
             {
                 Console.WriteLine();
             }
         }
     }
     if (battleResults.defenderAllies.Count > 0 && battleResults.defenderAllies != null)
     {
         Console.WriteLine("Defender allies participating in the battle: ");
         for (int i = 0; i < battleResults.defenderAllies.Count; i++)
         {
             Console.Write(battleResults.defenderAllies[i]);
             if (i != battleResults.defenderAllies.Count - 1)
             {
                 Console.Write(", ");
             }
             else
             {
                 Console.WriteLine();
             }
         }
     }
     Console.WriteLine("-----------------------------");
 }
Example #3
0
        /// <summary>
        /// Implements the processes involved in a battle between two armies in the field
        /// </summary>
        /// <returns>bool indicating whether attacking army is victorious</returns>
        /// <remarks>
        /// Predicate: assumes attacker has sufficient days
        /// Predicate: assumes attacker has leader
        /// Predicate: assumes attacker in same fief as defender
        /// Predicate: assumes defender not besieged in keep
        /// Predicate: assumes attacker and defender not same army
        /// </remarks>
        /// <param name="attacker">The attacking army</param>
        /// <param name="defender">The defending army</param>
        /// <param name="circumstance">string indicating circumstance of battle</param>
        public static bool GiveBattle(Army attacker, Army defender, out ProtoBattle battleResults, string circumstance = "battle")
        {
            Contract.Requires(attacker != null && defender != null && circumstance != null);
            battleResults = new ProtoBattle();
            bool attackerVictorious = false;
            bool battleHasCommenced = false;
            bool attackerLeaderDead = false;
            bool defenderLeaderDead = false;
            // check if losing army has disbanded
            bool attackerDisbanded = false;
            bool defenderDisbanded = false;

            bool siegeRaised = false;

            uint[]   battleValues      = new uint[2];
            double[] casualtyModifiers = new double[2];
            double   statureChange     = 0;

            // if applicable, get siege
            Siege  thisSiege   = null;
            string thisSiegeID = defender.CheckIfBesieger();

            if (!String.IsNullOrWhiteSpace(thisSiegeID))
            {
                // get siege
                thisSiege = Globals_Game.siegeMasterList[thisSiegeID];
            }

            // get starting troop numbers
            uint attackerStartTroops = attacker.CalcArmySize();
            uint defenderStartTroops = defender.CalcArmySize();
            uint attackerCasualties  = 0;
            uint defenderCasualties  = 0;

            // get leaders
            Character attackerLeader = attacker.GetLeader();
            Character defenderLeader = defender.GetLeader();

            // if(attackerLeader!=null) {
            battleResults.attackerLeader = attackerLeader.firstName + " " + attackerLeader.familyName;
            //  }
            //  if(defenderLeader!=null) {
            battleResults.defenderLeader = defenderLeader.firstName + " " + defenderLeader.familyName;
            //   }

            battleResults.attackerOwner  = attacker.GetOwner().firstName + "  " + attacker.GetOwner().familyName;
            battleResults.defenderOwner  = defender.GetOwner().firstName + " " + defender.GetOwner().familyName;
            battleResults.battleLocation = attacker.GetLocation().id;
            // introductory text for message
            switch (circumstance)
            {
            case "pillage":
                battleResults.circumstance = 1;
                break;

            case "siege":
                battleResults.circumstance = 2;
                break;

            default:
                battleResults.circumstance = 0;
                break;
            }

            // get battle values for both armies
            battleValues = attacker.CalculateBattleValues(defender);

            // check if attacker has managed to bring defender to battle
            // case 1: defending army sallies during siege to attack besieger = battle always occurs
            if (circumstance.Equals("siege"))
            {
                battleHasCommenced = true;
            }
            // case 2: defending militia attacks pillaging army during pollage = battle always occurs
            else if (circumstance.Equals("pillage"))
            {
                battleHasCommenced = true;
            }
            // case 3: defender aggression and combatOdds allows battle
            else if (defender.aggression != 0)
            {
                if (defender.aggression == 1)
                {
                    // get odds
                    int battleOdds = Battle.GetBattleOdds(attacker, defender);

                    // if odds OK, give battle
                    if (battleOdds <= defender.combatOdds)
                    {
                        battleHasCommenced = true;
                    }

                    // if not, check for battle
                    else
                    {
                        battleHasCommenced = Battle.BringToBattle(battleValues[0], battleValues[1], circumstance);

                        if (!battleHasCommenced)
                        {
                            defender.ProcessRetreat(1);
                        }
                    }
                }

                else
                {
                    battleHasCommenced = true;
                }
            }

            // otherwise, check to see if the attacker can bring the defender to battle
            else
            {
                battleHasCommenced = Battle.BringToBattle(battleValues[0], battleValues[1], circumstance);
                if (!battleHasCommenced)
                {
                    defender.ProcessRetreat(1);
                }
            }
            battleResults.battleTookPlace = battleHasCommenced;
            if (battleHasCommenced)
            {
                List <string> disbandedArmies = new List <string>();
                List <string> retreatedArmies = new List <string>();
                List <string> deadCharacters  = new List <string>();
                // WHO HAS WON?
                // calculate if attacker has won
                attackerVictorious = Battle.DecideBattleVictory(battleValues[0], battleValues[1]);

                // UPDATE STATURE
                if (attackerVictorious)
                {
                    statureChange = 0.8 * (defender.CalcArmySize() / Convert.ToDouble(10000));
                    battleResults.statureChangeAttacker = statureChange;
                    attacker.GetOwner().AdjustStatureModifier(statureChange);
                    statureChange = -0.5 * (attacker.CalcArmySize() / Convert.ToDouble(10000));
                    battleResults.statureChangeDefender = statureChange;
                    defender.GetOwner().AdjustStatureModifier(statureChange);
                }
                else
                {
                    statureChange = 0.8 * (attacker.CalcArmySize() / Convert.ToDouble(10000));
                    battleResults.statureChangeDefender = statureChange;
                    defender.GetOwner().AdjustStatureModifier(statureChange);
                    statureChange = -0.5 * (defender.CalcArmySize() / Convert.ToDouble(10000));
                    battleResults.statureChangeAttacker = statureChange;
                    attacker.GetOwner().AdjustStatureModifier(statureChange);
                }

                // CASUALTIES
                // calculate troop casualties for both sides
                casualtyModifiers = Battle.CalculateBattleCasualties(attackerStartTroops, defenderStartTroops, battleValues[0], battleValues[1], attackerVictorious);


                uint totalAttackTroopsLost = 0;
                uint totalDefendTroopsLost = 0;

                // if losing side sustains >= 50% casualties, disbands
                if (attackerVictorious)
                {
                    // either indicate losing army to be disbanded
                    if (casualtyModifiers[1] >= 0.5)
                    {
                        defenderDisbanded = true;
                        disbandedArmies.Add(defender.owner);
                        totalDefendTroopsLost = defender.CalcArmySize();
                    }
                    // OR apply troop casualties to losing army
                    else
                    {
                        totalDefendTroopsLost = defender.ApplyTroopLosses(casualtyModifiers[1]);
                    }

                    // apply troop casualties to winning army
                    totalAttackTroopsLost = attacker.ApplyTroopLosses(casualtyModifiers[0]);
                }
                else
                {
                    if (casualtyModifiers[0] >= 0.5)
                    {
                        attackerDisbanded = true;
                        disbandedArmies.Add(attacker.owner);
                        totalAttackTroopsLost = attacker.CalcArmySize();
                    }
                    else
                    {
                        totalAttackTroopsLost = attacker.ApplyTroopLosses(casualtyModifiers[0]);
                    }

                    totalDefendTroopsLost = defender.ApplyTroopLosses(casualtyModifiers[1]);
                }
                battleResults.attackerCasualties = totalAttackTroopsLost;
                battleResults.defenderCasualties = totalDefendTroopsLost;
                // UPDATE TOTAL SIEGE LOSSES, if appropriate
                // NOTE: the defender in this battle is the attacker in the siege and v.v.
                if (thisSiege != null)
                {
                    // update total siege attacker (defender in this battle) losses
                    thisSiege.totalCasualtiesAttacker += Convert.ToInt32(totalDefendTroopsLost);

                    // update total siege defender (attacker in this battle) losses
                    if (circumstance.Equals("siege"))
                    {
                        thisSiege.totalCasualtiesDefender += Convert.ToInt32(totalAttackTroopsLost);
                    }
                }

                // get casualty figures (for message)
                if (!attackerDisbanded)
                {
                    // get attacker casualties
                    attackerCasualties = totalAttackTroopsLost;
                }
                if (!defenderDisbanded)
                {
                    // get defender casualties
                    defenderCasualties = totalDefendTroopsLost;
                }

                // DAYS
                // adjust days
                // NOTE: don't adjust days if is a siege (will be deducted elsewhere)
                if (!circumstance.Equals("siege"))
                {
                    if (attackerLeader != null)
                    {
                        attackerLeader.AdjustDays(1);
                    }
                    // need to check for defender having no leader
                    if (defenderLeader != null)
                    {
                        defenderLeader.AdjustDays(1);
                    }
                    else
                    {
                        defender.days -= 1;
                    }
                }

                // RETREATS
                // create array of armies (for easy processing)
                Army[] bothSides = { attacker, defender };

                // check if either army needs to retreat
                int[] retreatDistances = Battle.CheckForRetreat(attacker, defender, casualtyModifiers[0], casualtyModifiers[1], attackerVictorious);

                // if is pillage or siege, attacking army (the fief's army) doesn't retreat
                // if is pillage, the defending army (the pillagers) always retreats if has lost
                if (circumstance.Equals("pillage") || circumstance.Equals("siege"))
                {
                    retreatDistances[0] = 0;
                }

                if (circumstance.Equals("pillage"))
                {
                    if (attackerVictorious)
                    {
                        retreatDistances[1] = 1;
                    }
                }

                // if have retreated, perform it
                for (int i = 0; i < retreatDistances.Length; i++)
                {
                    if (retreatDistances[i] > 0)
                    {
                        bothSides[i].ProcessRetreat(retreatDistances[i]);
                    }
                }
                // If attacker has retreated add to retreat list
                if (retreatDistances[0] > 0)
                {
                    retreatedArmies.Add(battleResults.attackerOwner);
                }
                // If defender retreated add to retreat list
                if (retreatDistances[1] > 0)
                {
                    retreatedArmies.Add(battleResults.defenderOwner);
                }
                // PC/NPC INJURIES/DEATHS
                // check if any PCs/NPCs have been wounded or killed
                bool characterDead = false;

                // 1. ATTACKER
                uint friendlyBV = battleValues[0];
                uint enemyBV    = battleValues[1];

                // if army leader a PC, check entourage
                if (attackerLeader is PlayerCharacter)
                {
                    for (int i = 0; i < (attackerLeader as PlayerCharacter).myNPCs.Count; i++)
                    {
                        if ((attackerLeader as PlayerCharacter).myNPCs[i].inEntourage)
                        {
                            characterDead = (attackerLeader as PlayerCharacter).myNPCs[i].CalculateCombatInjury(casualtyModifiers[0]);
                        }

                        // process death, if applicable
                        if (characterDead)
                        {
                            (attackerLeader as PlayerCharacter).myNPCs[i].ProcessDeath("injury");
                        }
                    }
                }

                // check army leader
                if (attackerLeader != null)
                {
                    attackerLeaderDead = attackerLeader.CalculateCombatInjury(casualtyModifiers[0]);
                }


                // process death, if applicable
                if (attackerLeaderDead)
                {
                    deadCharacters.Add(attackerLeader.firstName + " " + attackerLeader.familyName);
                    Character newLeader = null;

                    // if is pillage, do NOT elect new leader for attacking army
                    if (!circumstance.Equals("pillage"))
                    {
                        // if possible, elect new leader from entourage
                        if (attackerLeader is PlayerCharacter)
                        {
                            if ((attackerLeader as PlayerCharacter).myNPCs.Count > 0)
                            {
                                // get new leader
                                newLeader = (attackerLeader as PlayerCharacter).ElectNewArmyLeader();
                            }
                        }

                        // assign newLeader (can assign null leader if none found)
                        attacker.AssignNewLeader(newLeader);
                    }
                }
                else
                {
                    // if pillage, if fief's army loses, make sure bailiff always returns to keep
                    if (circumstance.Equals("pillage"))
                    {
                        if (!attackerVictorious)
                        {
                            attackerLeader.inKeep = true;
                        }
                    }
                }

                // 2. DEFENDER

                // need to check if defending army had a leader
                if (defenderLeader != null)
                {
                    // if army leader a PC, check entourage
                    if (defenderLeader is PlayerCharacter)
                    {
                        for (int i = 0; i < (defenderLeader as PlayerCharacter).myNPCs.Count; i++)
                        {
                            if ((defenderLeader as PlayerCharacter).myNPCs[i].inEntourage)
                            {
                                characterDead = (defenderLeader as PlayerCharacter).myNPCs[i].CalculateCombatInjury(casualtyModifiers[1]);
                            }

                            // process death, if applicable
                            if (characterDead)
                            {
                                (defenderLeader as PlayerCharacter).myNPCs[i].ProcessDeath("injury");
                            }
                        }
                    }

                    // check army leader
                    defenderLeaderDead = defenderLeader.CalculateCombatInjury(casualtyModifiers[1]);

                    // process death, if applicable
                    if (defenderLeaderDead)
                    {
                        deadCharacters.Add(defenderLeader.firstName + " " + defenderLeader.familyName);
                        Character newLeader = null;

                        // if possible, elect new leader from entourage
                        if (defenderLeader is PlayerCharacter)
                        {
                            if ((defenderLeader as PlayerCharacter).myNPCs.Count > 0)
                            {
                                // get new leader
                                newLeader = (defenderLeader as PlayerCharacter).ElectNewArmyLeader();
                            }
                        }

                        // assign newLeader (can assign null leader if none found)
                        defender.AssignNewLeader(newLeader);
                    }
                }

                battleResults.deaths          = deadCharacters.ToArray();
                battleResults.retreatedArmies = retreatedArmies.ToArray();

                battleResults.attackerVictorious = attackerVictorious;

                // check for SIEGE RELIEF
                if (thisSiege != null)
                {
                    battleResults.isSiege       = true;
                    battleResults.siegeBesieger = thisSiege.GetBesiegingPlayer().firstName + " " + thisSiege.GetBesiegingPlayer().familyName;
                    battleResults.siegeDefender = thisSiege.GetDefendingPlayer().firstName + " " + thisSiege.GetDefendingPlayer().familyName;
                    // attacker (relieving army) victory or defender (besieging army) retreat = relief
                    if ((attackerVictorious) || (retreatDistances[1] > 0))
                    {
                        // indicate siege raised
                        siegeRaised = true;
                        battleResults.siegeRaised = true;
                    }

                    // check to see if siege raised due to death of siege owner with no heir
                    else if ((defenderLeaderDead) && ((defenderLeader as PlayerCharacter) == thisSiege.GetBesiegingPlayer()))
                    {
                        // get siege owner's heir
                        Character thisHeir = (defenderLeader as PlayerCharacter).GetHeir();

                        if (thisHeir == null)
                        {
                            battleResults.DefenderDeadNoHeir = true;
                            // indicate siege raised
                            siegeRaised = true;
                        }
                    }
                }
            }

            // =================== construct and send JOURNAL ENTRY
            // ID
            uint entryID = Globals_Game.GetNextJournalEntryID();

            // personae
            // personae tags vary depending on circumstance
            string attackOwnTag  = "|attackerOwner";
            string attackLeadTag = "|attackerLeader";
            string defendOwnTag  = "|defenderOwner";
            string defendLeadTag = "|defenderLeader";

            if ((circumstance.Equals("pillage")) || (circumstance.Equals("siege")))
            {
                attackOwnTag  = "|sallyOwner";
                attackLeadTag = "|sallyLeader";
                defendOwnTag  = "|defenderAgainstSallyOwner";
                defendLeadTag = "|defenderAgainstSallyLeader";
            }
            List <string> tempPersonae = new List <string>();

            tempPersonae.Add(defender.GetOwner().charID + defendOwnTag);
            if (attackerLeader != null)
            {
                tempPersonae.Add(attackerLeader.charID + attackLeadTag);
            }
            if (defenderLeader != null)
            {
                tempPersonae.Add(defenderLeader.charID + defendLeadTag);
            }
            tempPersonae.Add(attacker.GetOwner().charID + attackOwnTag);
            tempPersonae.Add(attacker.GetLocation().owner.charID + "|fiefOwner");
            if ((!circumstance.Equals("pillage")) && (!circumstance.Equals("siege")))
            {
                tempPersonae.Add("all|all");
            }
            string[] battlePersonae = tempPersonae.ToArray();

            // location
            string battleLocation = attacker.GetLocation().id;


            // put together new journal entry
            JournalEntry battleResult = new JournalEntry(entryID, Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, battlePersonae, "battle", battleResults, loc: battleLocation);

            // add new journal entry to pastEvents
            Globals_Game.AddPastEvent(battleResult);

            // display pop-up informational message
            battleResults.ActionType   = Actions.Update;
            battleResults.ResponseType = DisplayMessages.BattleResults;
            if (battleHasCommenced)
            {
                Globals_Game.UpdatePlayer(defender.GetOwner().playerID, DisplayMessages.BattleBringSuccess, new string[] { battleResults.attackerOwner });
            }
            else
            {
                Globals_Game.UpdatePlayer(defender.GetOwner().playerID, DisplayMessages.BattleBringFail, new string[] { battleResults.attackerOwner });
            }

            // end siege if appropriate
            if (siegeRaised)
            {
                //HACK
                thisSiege.SiegeEnd(false, DisplayMessages.BattleResults, new string[] { DisplaySiegeResults(battleResults) });
                thisSiege = null;

                // ensure if siege raised correct value returned to Form1.siegeReductionRound method
                if (circumstance.Equals("siege"))
                {
                    attackerVictorious = true;
                }
            }

            // process leader deaths
            if (defenderLeaderDead)
            {
                defenderLeader.ProcessDeath("injury");
            }
            else if (attackerLeaderDead)
            {
                attackerLeader.ProcessDeath("injury");
            }


            // DISBANDMENT

            // if is pillage, attacking (temporary) army always disbands after battle
            if (circumstance.Equals("pillage"))
            {
                attackerDisbanded = true;
            }

            // process army disbandings (after all other functions completed)
            if (attackerDisbanded)
            {
                attacker.DisbandArmy();
                attacker = null;
            }

            if (defenderDisbanded)
            {
                defender.DisbandArmy();
                defender = null;
            }

            return(attackerVictorious);
        }
Example #4
0
        /// <summary>
        /// Return a string describing the results of a battle
        /// </summary>
        /// <param name="battle">Results of battle</param>
        /// <returns>String description</returns>
        public static String DisplayBattleResults(ProtoBattle battle)
        {
            Contract.Requires(battle != null);
            // Battle introduction
            string toDisplay = "The fief garrison and militia";

            if (battle.attackerLeader != null)
            {
                toDisplay += ", led by " + battle.attackerLeader + ",";
            }
            switch (battle.circumstance)
            {
            // Normal battle
            case 0:
            {
                toDisplay += " moved to attack ";
            }
            break;

            // Pillage
            case 1:
            {
                toDisplay += " sallied forth to bring the pillaging army,";
            }
            break;

            // Siege
            case 2:
            {
                toDisplay += ", sallied forth to bring the besieging army, ";
            }
            break;

            default:
                toDisplay = "Unrecognised circumstance";
                break;
            }
            if (battle.defenderLeader != null)
            {
                toDisplay += " led by " + battle.defenderLeader + " and";
            }
            toDisplay += " owned by " + battle.defenderOwner
                         + ", to battle in the fief of " + Globals_Game.fiefMasterList[battle.battleLocation].name + "."
                         + "\r\n\r\nOutcome: ";
            if (battle.battleTookPlace)
            {
                if (battle.attackerVictorious)
                {
                    toDisplay += battle.attackerOwner;
                }
                else
                {
                    toDisplay += battle.defenderOwner;
                }

                // Victory status
                toDisplay += "'s army was victorious.\r\n\r\n";

                // Casualties
                toDisplay += battle.attackerOwner + "'s army suffered " + battle.attackerCasualties +
                             " troop casualties.\n";
                toDisplay += battle.defenderLeader + "'s army suffered " + battle.defenderCasualties +
                             " troop casualties.\n";

                // Retreats
                foreach (var retreater in battle.retreatedArmies)
                {
                    toDisplay += retreater + "'s army retreated from the fief.\n";
                }

                // Disbands
                foreach (var disbander in battle.disbandedArmies)
                {
                    toDisplay += disbander + "'s army disbanded due to heavy casualties.\n";
                }

                toDisplay += string.Join(", ", battle.deaths) + " all died due to injuries received.\n";
                if (battle.circumstance == 1)
                {
                    toDisplay += "The pillage in " + Globals_Game.fiefMasterList[battle.battleLocation].name +
                                 " has been prevented";
                }

                // Siege results
                if (battle.circumstance == 2)
                {
                    if (battle.attackerVictorious || battle.retreatedArmies.Contains(battle.attackerOwner))
                    {
                        toDisplay += battle.attackerOwner + "'s defenders have defeated the forces of " +
                                     battle.defenderOwner + ", relieving the siege of " +
                                     Globals_Game.fiefMasterList[battle.battleLocation].name
                                     + ". " + battle.defenderOwner +
                                     " retains ownership of the fief. The siege has been raised.\n";
                    }
                    else if (battle.DefenderDeadNoHeir)
                    {
                        // add to message
                        toDisplay += "The siege in " + Globals_Game.fiefMasterList[battle.battleLocation].name + " has been raised";
                        toDisplay += " due to the death of the besieging party, ";
                        toDisplay += battle.siegeBesieger + ".";
                    }
                }
            }
            else
            {
                if (battle.circumstance > 0)
                {
                    toDisplay += battle.attackerOwner + "'s forces failed to bring their aggressors to battle.\n";
                }
                else
                {
                    toDisplay += battle.defenderOwner +
                                 "'s forces successfully refused battle and retreated from the fief.";
                }
            }
            return(toDisplay);
        }