/// <summary> /// Engages the unit in combat with an enemy. /// </summary> /// <param name="defender">The enemy to engage in combat with.</param> /// <returns>a <see cref="CombatResult"/> enumeration representing the results of the /// fight.</returns> protected virtual CombatResult Combat(Unit defender) { if (defender == null) { throw new ArgumentNullException("defender"); } int defendersDefensivePower; int chanceToWin; int randNum; bool combatOver; CombatResult retval = CombatResult.Unresolved; OnCombatStarted(new CombatEventArgs(defender)); defendersDefensivePower = defender.CalculateDefensivePower(); //calculate the chance to win. (will be between 1 and 100) chanceToWin = CalcAttackersChanceToWin(this.OffensivePower, defendersDefensivePower); combatOver = false; do { randNum = RandomNumber.Between(1, 100); if (randNum <= chanceToWin) { //attacker wins round defender.LoseHitPoint(); if (defender.HitPoints == 1 && defender.Fast && !this.Fast) { combatOver = defender.Retreat(); if (combatOver) { retval = CombatResult.Unresolved; } } else if (defender.HitPoints <= 0) { combatOver = true; retval = CombatResult.Win; } } else { //defender wins round LoseHitPoint(); if (this.HitPoints == 1 && this.Fast && !defender.Fast) { //attempt to retreat. combatOver = Retreat(); if (combatOver) { retval = CombatResult.Unresolved; } } else if (this.HitPoints <= 0) { combatOver = true; retval = CombatResult.Killed; } } } while (!combatOver); return(retval); }
/// <summary> /// Attempts to get a foreign city to defect to the parent country by /// spreading propaganda. Cities in anarchy are immune to proaganda. /// </summary> /// <param name="foreignCity"></param> /// <returns></returns> public EspionageResult SpreadPropaganda(City foreignCity) { if (!this.hasEmbassy) { throw new InvalidOperationException(ServerResources.EmbassyRequired); } if (!this.hasSpy) { throw new InvalidOperationException(ServerResources.SpyRequired); } //TODO: add code to account for continued resistance. //TODO: add code to account for more advanced governments. if (foreignCity == null) { throw new ArgumentNullException("foreignCity"); } CulturalPerception perception; EspionageResult result = EspionageResult.Failure; bool propogandaSpread; int chanceForPropaganda = 0; int chanceForResistance = 0; int chanceForContinuedResistance = 0; //a quick check: if the foreign city is in anarchy, //the proganda campaign will automatically fail //(although there is no chance the spy will be caught). if (this.foreignCountry.Government.Fallback) { result = EspionageResult.Failure; return(result); } //there are 2 steps to taking over a city with propaganda. The //first step is successfully spreading propaganda, and the second //step is not having that proaganda resisted. These two taken //together make it very difficult for overall proaganda to succeed. perception = this.foreignCountry.GetCulturalPerception(this.parentCountry); switch (perception) { case CulturalPerception.InAwe: chanceForPropaganda = 30; chanceForResistance = 40; chanceForContinuedResistance = 30; break; case CulturalPerception.Admirer: chanceForPropaganda = 25; chanceForResistance = 50; chanceForContinuedResistance = 40; break; case CulturalPerception.Impressed: chanceForPropaganda = 20; chanceForResistance = 60; chanceForContinuedResistance = 50; break; case CulturalPerception.Unimpressed: chanceForPropaganda = 10; chanceForResistance = 70; chanceForContinuedResistance = 60; break; case CulturalPerception.Dismissive: chanceForPropaganda = 5; chanceForResistance = 80; chanceForContinuedResistance = 70; break; case CulturalPerception.Disdainful: chanceForPropaganda = 3; chanceForResistance = 90; chanceForContinuedResistance = 80; break; } int randNum = RandomNumber.Between(1, 100); if (randNum <= chanceForPropaganda) { propogandaSpread = true; } else { propogandaSpread = false; result = EspionageResult.Failure; } if (propogandaSpread) { randNum = RandomNumber.Between(1, 100); if (randNum <= chanceForResistance) { result = EspionageResult.Failure; } else { //the propaganda was successfull. The city now belongs //to the parent. result = EspionageResult.Success; this.parentCountry.Cities.Add(foreignCity); this.foreignCountry.Cities.Remove(foreignCity); foreignCity.ParentCountry = this.parentCountry; } } if (result == EspionageResult.Failure) { //spy caught? randNum = RandomNumber.Between(1, 100); if (randNum >= 50) { result = EspionageResult.SpyCaught; this.foreignCountry.CaptureSpy(this, EspionageAction.SpreadPropaganda, false, foreignCity); this.hasSpy = false; } } return(result); }
/// <summary> /// Bombards the given cell. /// </summary> /// <remarks>Not all bombardment attempts are successfull. To determine the /// outcome of an attempt, review the <i>BombardmentResult</i> return value.</remarks> /// <param name="cell"></param> public BombardmentResult Bombard(GridCell cell) { if (cell == null) { throw new ArgumentNullException("cell"); } if (!this.CanBombard) { throw new InvalidOperationException(ServerResources.UnitCannotBombard); } bool success = IsBombardmentSuccessfull(); if (!success) { return(BombardmentResult.Failed); } if (cell.HasCity) { City city = cell.City; if (city.Improvements.Count > 0) { //which improvement was destroyed? int bound = city.Improvements.Count - 1; int idx = RandomNumber.Between(0, bound); Improvement destroyed = city.Improvements[idx]; city.DestroyImprovement(destroyed, this.country); return(BombardmentResult.SucceededDestroyingCityImprovement); } else if (cell.Units.Count > 0) { int bound = cell.Units.Count - 1; int idx = RandomNumber.Between(0, bound); cell.Units[idx].LoseHitPoint(); return(BombardmentResult.SucceededInjuredUnit); } else if (city.Population > 1) { city.BombardPopulation(this.country); return(BombardmentResult.SucceededKilledCitizens); } } else { if (cell.IsIrrigated) { cell.IsIrrigated = false; return(BombardmentResult.SucceededDestroyingCellImprovement); } else if (cell.HasMine) { cell.HasMine = false; return(BombardmentResult.SucceededDestroyingCellImprovement); } else if (cell.HasRailroad) { cell.HasRailroad = false; cell.HasRoad = true; return(BombardmentResult.SucceededDestroyingCellImprovement); } else if (cell.HasRoad) { cell.HasRoad = false; return(BombardmentResult.SucceededDestroyingCellImprovement); } } return(BombardmentResult.Failed); }
/// <summary> /// Gets a random land-based cell on the map. /// </summary> /// <returns></returns> public GridCell FindRandomDryCell() { int idx = RandomNumber.UpTo(this.dryCells.Count - 1); return(this.dryCells[idx]); }