/// <summary> /// Defenders gather any like allied forces they can muster in the hex /// </summary> /// <param name="defender"></param> /// <param name="defenderHome"></param> public void GatherDefenders(Civilization defender, HexData defenderHome, string attackerFullName) { DefenderList.Add(defender); foreach (var lair in defenderHome.LairList) { if (lair.IsRuins()) { continue; } if (lair.HomeCiv.GetFullName() == defender.GetFullName()) { continue; } if (lair.HomeCiv.GetFullName() == attackerFullName) { continue; } if (lair.HomeCiv.Patricians.BaseAncestry.Name != defender.Patricians.BaseAncestry.Name) { continue; } if (defender.LeaderCompetency <= _dice.Roll(1, 12)) { continue; } DefenderList.Add(lair.HomeCiv); string record = "The " + defender.GetPluralName() + " have convinced the " + lair.HomeCiv.GetPluralName() + " to come to their defense."; defender.History.addRecord(record); lair.HomeCiv.History.addRecord(record, isLogged: false); } }
/// <summary> /// Losers of a battle will try to search their home hex for a like /// race to join, or and adjacent hex if that fails. /// If that fails, they are eliminated. /// </summary> /// <param name="losers"></param> /// <param name="loserHome"></param> /// <param name="baseName">The name of the home base that the refugees /// just left. They can't go back here.</param> void MoveLosers(Civilization losers, HexData loserHome, string baseName) { bool isFoundHex = RefugeesSearchHex(losers, loserHome, baseName); if (isFoundHex) { return; } int nextIndex = _dice.Roll(1, 6); bool isFound = false; for (int i = 0; i < 6; ++i) { ++nextIndex; if (nextIndex > 6) { nextIndex = 1; } var nextCoords = loserHome.FindNeighborByIndex(nextIndex); var nextHex = _worldMap.GetHexByCoordinates(nextCoords.Item1, nextCoords.Item2); if (nextHex is null) { continue; } isFound = RefugeesSearchHex(losers, nextHex, baseName); if (isFound) { break; } } if (isFound) { return; } // no available place to go! string report = "The " + losers.GetPluralName() + " could not find refuge."; losers.History.addRecord(report); losers.DissolvePopulation(); }
/// <summary> /// The main battle resolution /// Combatants must come from a lair in a hex. /// </summary> /// <param name="attackerLands"></param> /// <param name="defenderLands"></param> /// <param name="attackerBase"></param> /// <param name="defenderBase"></param> public void ResolveBattle(HexData attackerLands, HexData defenderLands, Lair attackerBase, Lair defenderBase) { if (attackerBase.IsRuins()) { // no attackers! do not pass! AttackerState = CombatantState.COMBATANT_STATE_ELIMINATED; return; } Civilization attacker = attackerBase.HomeCiv; string record; if (defenderBase.IsRuins()) { record = (defenderBase.GetFullName() + " is found abandoned by the " + attacker.GetPluralName()); defenderBase.History.addRecord(record); attacker.History.addRecord(record, isLogged: false); defenderBase.MoveCivIn(attacker); attackerBase.ForceAbandon(); defenderBase.Treasure += attackerBase.Treasure; attackerBase.Treasure = 0; DefenderState = CombatantState.COMBATANT_STATE_ELIMINATED; return; } Civilization defender = defenderBase.HomeCiv; // since this method is only called on initial spawn, then the // rule is to merge if two of the same race spawn in the same // hex area. if (attacker.Patricians.BaseAncestry.Name == defender.Patricians.BaseAncestry.Name) { defender.JoinOurCivilization(attacker.GetFullName()); defender.Patricians.Members += attacker.Patricians.Members; attacker.DissolvePopulation(); return; } record = "The " + attacker.GetPluralName() + " are attacking the " + defender.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; attacker.History.addRecord(record); defender.History.addRecord(record, isLogged: false); defenderBase.History.addRecord(record, isLogged: false); GatherAttackers(attacker, attackerLands, defender.GetFullName()); GatherDefenders(defender, defenderLands, attacker.GetFullName()); _attackerStartingForces = GetTotalCombatants(AttackerList); _defenderStartingForces = GetTotalCombatants(DefenderList); _executeMainBattleLoop(); // recover from battle ResolveSurvivors(_attackerStartingForces, AttackerList); ResolveSurvivors(_defenderStartingForces, DefenderList); // determine outcome of battle. bool isAttackerLost = (AttackerState == CombatantState.COMBATANT_STATE_ELIMINATED) || (AttackerState == CombatantState.COMBATANT_STATE_ROUTED); bool isDefenderLost = (DefenderState == CombatantState.COMBATANT_STATE_ELIMINATED) || (DefenderState == CombatantState.COMBATANT_STATE_ROUTED); bool isBothLost = isAttackerLost && isDefenderLost; bool isMutualDestruction = (DefenderState == CombatantState.COMBATANT_STATE_ELIMINATED && AttackerState == CombatantState.COMBATANT_STATE_ELIMINATED); if (isMutualDestruction) { // mutual destruction is highly unlikely, but not impossible. record = "The " + attacker.GetPluralName() + " and the " + defender.GetPluralName() + " have achieved mutual destruction at " + defenderBase.GetFullName() + "!"; attacker.DissolvePopulation(); defender.DissolvePopulation(); } else if (isBothLost) { if (DefenderState == CombatantState.COMBATANT_STATE_ELIMINATED) { // defenders lose record = "The " + defender.GetPluralName() + " have been defeated by the " + attacker.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; string defenderBaseName = defenderBase.Name; MoveLosers(defender, defenderLands, defenderBaseName); defenderBase.MoveCivIn(attacker); attackerBase.ForceAbandon(); defenderBase.Treasure += attackerBase.Treasure; attackerBase.Treasure = 0; } else { record = "The " + attacker.GetPluralName() + " have been repelled by the " + defender.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; string attackerBaseName = attackerBase.Name; // It's interesting that attackers don't go back home. MoveLosers(attacker, attackerLands, attackerBaseName); attackerBase.ForceAbandon(); } } else if (isDefenderLost) { // defender loses! record = "The " + defender.GetPluralName() + " have been defeated by the " + attacker.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; string defenderBaseName = defenderBase.Name; MoveLosers(defender, defenderLands, defenderBaseName); defenderBase.MoveCivIn(attacker); attackerBase.ForceAbandon(); defenderBase.Treasure += attackerBase.Treasure; attackerBase.Treasure = 0; } else // attacker lost { // attacker loses! record = "The " + attacker.GetPluralName() + " have been repelled by the " + defender.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; string attackerBaseName = attackerBase.Name; // It's interesting that attackers don't go back home. MoveLosers(attacker, attackerLands, attackerBaseName); attackerBase.ForceAbandon(); } _recordBattleReport(record, attacker, defender, defenderBase); // any lingering civs with zero population are removed. _worldMap.CleanOutRuins(); }
/// <summary> /// Overloaded function for determining battles started by outside /// or homeless invaders. /// </summary> /// <param name="attacker"></param> /// <param name="defenderLands"></param> /// <param name="defenderBase"></param> public void ResolveBattle(Civilization attacker, HexData defenderLands, Lair defenderBase) { string record; if (defenderBase.IsRuins()) { record = (defenderBase.GetFullName() + " is found abandoned by the " + attacker.GetPluralName()); defenderBase.History.addRecord(record); attacker.History.addRecord(record, isLogged: false); defenderBase.MoveCivIn(attacker); defenderBase.Treasure += 1; DefenderState = CombatantState.COMBATANT_STATE_ELIMINATED; return; } Civilization defender = defenderBase.HomeCiv; record = "The " + attacker.GetPluralName() + " are attacking the " + defender.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; attacker.History.addRecord(record); defender.History.addRecord(record, isLogged: false); defenderBase.History.addRecord(record, isLogged: false); AttackerList.Add(attacker); GatherDefenders(defender, defenderLands, attacker.GetFullName()); _attackerStartingForces = GetTotalCombatants(AttackerList); _defenderStartingForces = GetTotalCombatants(DefenderList); _executeMainBattleLoop(); // recover from battle ResolveSurvivors(_attackerStartingForces, AttackerList); ResolveSurvivors(_defenderStartingForces, DefenderList); // determine outcome of battle. bool isAttackerLost = (AttackerState == CombatantState.COMBATANT_STATE_ELIMINATED) || (AttackerState == CombatantState.COMBATANT_STATE_ROUTED); bool isDefenderLost = (DefenderState == CombatantState.COMBATANT_STATE_ELIMINATED) || (DefenderState == CombatantState.COMBATANT_STATE_ROUTED); bool isBothLost = isAttackerLost && isDefenderLost; bool isMutualDestruction = (DefenderState == CombatantState.COMBATANT_STATE_ELIMINATED && AttackerState == CombatantState.COMBATANT_STATE_ELIMINATED); if (isMutualDestruction) { // mutual destruction is highly unlikely, but not impossible. record = "The " + attacker.GetPluralName() + " and the " + defender.GetPluralName() + " have achieved mutual destruction at " + defenderBase.GetFullName() + "!"; attacker.DissolvePopulation(); defender.DissolvePopulation(); } else if (isBothLost) { if (DefenderState == CombatantState.COMBATANT_STATE_ELIMINATED) { // defender loses! record = "The " + defender.GetPluralName() + " have been defeated by the " + attacker.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; string defenderBaseName = defenderBase.Name; MoveLosers(defender, defenderLands, defenderBaseName); defenderBase.MoveCivIn(attacker); defenderBase.Treasure += 1; } else { // attacker loses! record = "The " + attacker.GetPluralName() + " have been repelled by the " + defender.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; // In this case, the attackers seek to allign themselves // possibly where they landed. MoveLosers(attacker, defenderLands, baseName: ""); } } else if (isDefenderLost) { // defender loses! record = "The " + defender.GetPluralName() + " have been defeated by the " + attacker.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; string defenderBaseName = defenderBase.Name; MoveLosers(defender, defenderLands, defenderBaseName); defenderBase.MoveCivIn(attacker); defenderBase.Treasure += 1; } else // attacker lost { // attacker loses! record = "The " + attacker.GetPluralName() + " have been repelled by the " + defender.GetPluralName() + " at " + defenderBase.GetFullName() + "!"; // In this case, the attackers seek to allign themselves // possibly where they landed. MoveLosers(attacker, defenderLands, baseName: ""); } _recordBattleReport(record, attacker, defender, defenderBase); // any lingering civs with zero population are removed. _worldMap.CleanOutRuins(); }