static public CombatArmyRoundResult GenerateForCombat(CombatArmy army, IEnumerable <UInt32> randomNumberGenerator) { CombatArmyRoundResult armyRoundResult = new CombatArmyRoundResult(army.OriginRegionId, army.OwnerUserId); int maximumDicePoolSize = (army.ArmyMode == CombatArmyMode.Attacking) ? 3 : 2; int dicePoolSize = (maximumDicePoolSize < army.NumberOfTroops) ? maximumDicePoolSize : (int)army.NumberOfTroops; armyRoundResult.m_RolledResults.AddRange(randomNumberGenerator.Take(dicePoolSize)); return(armyRoundResult); }
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); }