Ejemplo n.º 1
0
        static public CombatResult GenerateForCombat(ICombat combat, Func <Guid, IEnumerable <UInt32> > randomNumberGenerator)
        {
            CombatResult result = new CombatResult(combat.CombatId);

            result.m_StartingArmies  = combat.InvolvedArmies;
            result.m_SurvivingArmies = (from army in combat.InvolvedArmies
                                        select new CombatArmy(army)).ToList();

            // Remove any armies with no troops (e.g. spoils of war, the defender is just here so we know what region's at stake!)
            result.m_SurvivingArmies.RemoveAll(army => army.NumberOfTroops == 0);

            while (result.m_SurvivingArmies.GroupBy(army => army.OwnerUserId).Count() > 1)
            {
                CombatRoundResult combatRound = CombatRoundResult.GenerateForCombat(combat.ResolutionType, result.m_SurvivingArmies, randomNumberGenerator);
                result.m_Rounds.Add(combatRound);

                // Remove armies with no troops left
                result.m_SurvivingArmies.RemoveAll(army => army.NumberOfTroops == 0);

                // Mass invasion has an early out when the defenders are all dead. Otherwise, fight to the last army standing!
                if (combat.ResolutionType == CombatType.MassInvasion)
                {
                    if (result.m_SurvivingArmies.Where(army => army.ArmyMode == CombatArmyMode.Defending).Count() == 0)
                    {
                        break;
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 2
0
        static public CombatRoundResult GenerateForCombat(CombatType resolutionMode, List <CombatArmy> armies, Func <Guid, IEnumerable <UInt32> > randomNumberGenerator)
        {
            CombatRoundResult roundResult = new CombatRoundResult();

            // Generate the results for each army
            foreach (CombatArmy army in armies)
            {
                roundResult.m_ArmyResults.Add(CombatArmyRoundResult.GenerateForCombat(army, randomNumberGenerator(army.OriginRegionId)));
            }

            switch (resolutionMode)
            {
            case CombatType.BorderClash:
            case CombatType.SpoilsOfWar:
            {
                for (int counter = 0; counter < 3; ++counter)
                {
                    var attackingDiceQuery = from armyResult in roundResult.m_ArmyResults
                                             where armyResult.RolledResults.Count() > counter
                                             join army in armies on armyResult.OriginRegionId equals army.OriginRegionId
                                             let armyDiceRoll = armyResult.RolledResults.ElementAt(counter)
                                                                orderby armyDiceRoll descending, army.NumberOfTroops ascending
                        select new { Army = army, Results = armyResult, AttackerRoll = armyDiceRoll };

                    var attackers = attackingDiceQuery.ToList();
                    for (int attackerIndex = 0; attackerIndex < attackers.Count; ++attackerIndex)
                    {
                        var attacker = attackers[attackerIndex];

                        // Compare against all remaining attackers (or until we run out of troops)
                        for (int defenderIndex = attackerIndex + 1; attacker.Results.TroopsLost < attacker.Army.NumberOfTroops && defenderIndex < attackers.Count; ++defenderIndex)
                        {
                            var defender = attackers[defenderIndex];
                            // Ensure defender has troops left and this wouldn't be friendly fire
                            if (defender.Army.OwnerUserId != attacker.Army.OwnerUserId && defender.Results.TroopsLost < defender.Army.NumberOfTroops)
                            {
                                // We've sorted out players by dice roll, so anyone in a lower index must either draw or be worse
                                if (attacker.AttackerRoll == defender.AttackerRoll)
                                {
                                    if (resolutionMode == CombatType.SpoilsOfWar)
                                    {
                                        // For a spoils of war, don't deduct troops on a draw. We don't want to be left with no one able to take the territory over
                                        continue;
                                    }
                                    attacker.Results.TroopsLost += 1;
                                }
                                defender.Results.TroopsLost += 1;
                            }
                        }
                    }
                }
                break;
            }

            case CombatType.MassInvasion:
            case CombatType.Invasion:
            {
                // Calculate troop loses. On a tie, the defenders lose
                var defendingDiceQuery = from armyResult in roundResult.m_ArmyResults
                                         join army in armies on armyResult.OriginRegionId equals army.OriginRegionId
                                         where army.ArmyMode == CombatArmyMode.Defending
                                         select new { Army = army, Results = armyResult, DefenderRolls = armyResult.RolledResults.OrderByDescending(diceRoll => diceRoll).ToList() };

                var attackingDiceQuery = from armyResult in roundResult.m_ArmyResults
                                         join army in armies on armyResult.OriginRegionId equals army.OriginRegionId
                                         where army.ArmyMode == CombatArmyMode.Attacking
                                         orderby army.NumberOfTroops ascending
                                         select new { Army = army, Results = armyResult, AttackerRolls = armyResult.RolledResults.OrderByDescending(diceRoll => diceRoll).ToList() };

                var defender = defendingDiceQuery.FirstOrDefault();
                for (int counter = 0; counter < defender.DefenderRolls.Count; ++counter)
                {
                    UInt32 defenderRoll = defender.DefenderRolls[counter];
                    foreach (var attacker in attackingDiceQuery)
                    {
                        // Check this attacker still has any dice left and both sides still have troops
                        if (counter < attacker.AttackerRolls.Count && attacker.Results.TroopsLost < attacker.Army.NumberOfTroops && defender.Results.TroopsLost < defender.Army.NumberOfTroops)
                        {
                            UInt32 attackerRoll = attacker.AttackerRolls[counter];
                            if (attackerRoll >= defenderRoll)
                            {
                                defender.Results.TroopsLost += 1;
                            }
                            else
                            {
                                attacker.Results.TroopsLost += 1;
                            }
                        }
                    }
                }
                break;
            }
            }

            // Apply troop loses to the armies
            var armyQuery = from armyResult in roundResult.m_ArmyResults
                            join army in armies on armyResult.OriginRegionId equals army.OriginRegionId
                            select new { Army = army, TroopsLost = armyResult.TroopsLost };

            foreach (var army in armyQuery)
            {
                army.Army.NumberOfTroops -= army.TroopsLost;
            }

            return(roundResult);
        }