예제 #1
0
 /// <summary>
 /// If two civilizations spawn in the same area, they must fight to
 /// determine who may settle there.
 /// </summary>
 /// <param name="newLair">the challenger to the conflict</param>
 /// <returns>Battle object holds the state results of the conflict. If
 /// the spot is not challenged at all, then null is returned.
 /// </returns>
 private Battle ResolveSettlementConflicts(Lair newLair)
 {
     foreach (var lair in LairList)
     {
         if (newLair.SubhexIndex != lair.SubhexIndex)
         {
             continue;
         }
         var battle = new Battle(_worldMap);
         battle.ResolveBattle(this, this, newLair, lair);
         return(battle);
     }
     return(null);
 }
예제 #2
0
        /// <summary>
        /// New monsters move in from the edge of the map.
        /// </summary>
        /// <param name="hex"></param>
        public void ResolveOutsideSingleHexMigration(HexData hex)
        {
            // only for edge chances
            int numEdges = _worldMap.NumberOutsideEdges(hex);

            if (numEdges <= 0)
            {
                return;
            }

            // "5% chance per edge"
            int chance = numEdges * 5;
            int roll   = _dice.Roll(1, 100);

            if (roll > chance)
            {
                return;
            }

            // Are they invaders, or settlers?
            var invaders = new Civilization();

            invaders.InitializeAsRandomCiv(hex.Tier);

            // Depends on where they land:
            int subHexLoc = _dice.Roll(1, HexData.SUB_HEXES);
            var results   = ResolveInvasionConflicts(hex, invaders, subHexLoc);

            if (results is null)
            {
                // no battle. settle in unclaimed land.
                var lair = new Lair();
                lair.InitializeAsSettlerLair(invaders, subHexLoc, hex);
                lair.Treasure = 1;
                hex.LairList.Add(lair);
                return;
            }
            if (
                (results.AttackerState
                 == Battle.CombatantState.COMBATANT_STATE_ELIMINATED) ||
                (results.AttackerState
                 == Battle.CombatantState.COMBATANT_STATE_ROUTED)
                )
            {
                // invaders have been dealt with.
                return;
            }
            // else the invaders win, and have been moved into their new lair.
        }
예제 #3
0
        private void _recordBattleReport(string record, Civilization attacker,
                                         Civilization defender, Lair defenderBase)
        {
            record += " Battle lasted " + NumRounds + " rounds. "
                      + attacker.GetFullName() + " survivors: "
                      + (_attackerStartingForces - _defenderScore) + ". "
                      + defender.GetFullName() + " survivors: "
                      + (_defenderStartingForces - _attackerScore)
                      + ". Final tally: "
                      + attacker.GetFullName() + ": " + attacker.Patricians.Members
                      + " vs "
                      + defender.GetFullName() + ": " + defender.Patricians.Members;

            attacker.History.addRecord(record);
            defender.History.addRecord(record, isLogged: false);
            defenderBase.History.addRecord(record, isLogged: false);
        }
예제 #4
0
        private void _doMigration(Lair lair, HexData hex)
        {
            if (lair.IsRuins())
            {
                return;
            }

            string record = "The " + lair.HomeCiv.GetPluralName()
                            + " are migrating to a new home.";

            lair.HomeCiv.History.addRecord(record);

            HexData targetHex;

            do
            {
                int migrationDirection = _dice.Roll(1, 6);
                var neighborLocation   =
                    hex.FindNeighborByIndex(migrationDirection);
                targetHex =
                    _worldMap.GetHexByCoordinates(neighborLocation);
            } while (targetHex is null);

            int subHexIndex  = _dice.Roll(1, HexData.SUB_HEXES);
            var existingLair = targetHex.GetLairAtLocation(subHexIndex);

            if (existingLair is null)
            {
                // Free real estate!
                var newLair = new Lair();
                newLair.InitializeAsSettlerLair(lair.HomeCiv, subHexIndex,
                                                targetHex);
                targetHex.LairList.Add(newLair);
                lair.ForceAbandon();

                // move the treasure
                newLair.Treasure = lair.Treasure;
                lair.Treasure    = 0;

                return;
            }
            // Going to have to fight for the space.
            var battle = new Battle(_worldMap);

            battle.ResolveBattle(hex, targetHex, lair, existingLair);
        }
예제 #5
0
        /// <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();
        }
예제 #6
0
        /// <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();
        }
예제 #7
0
        /// <summary>
        /// Sets this hex up with random components
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void InitializeAsRandomHex(int x, int y, Tuple <int, int> origin,
                                          int tierWidth)
        {
            var nameGen = new RandomName();

            Name = nameGen.CreateWord();

            XCoord = x;
            YCoord = y;

            _setTier(origin.Item1, origin.Item2, tierWidth);

            var creatureSource = AncestryIndex.Instance;

            creatureSource.LoadAllSources();
            // init nature
            int numNatural = _dice.Roll(2, 4) + 1;

            for (int i = 0; i < numNatural; ++i)
            {
                var naturalCreature =
                    creatureSource.GetRandomNaturalAncestry(Tier);
                var tier = Tier;
                while (naturalCreature is null && tier > 0)
                {
                    --tier;
                    naturalCreature = creatureSource.GetRandomAncestry(tier);
                }
                if (naturalCreature is null)
                {
                    break;
                }
                NaturalEncounterPool.Add(naturalCreature.Name);
            }

            // init dungeons
            int numMonsters = _dice.Roll(2, 4) + 1;

            for (int i = 0; i < numMonsters; ++i)
            {
                var dungeonLurkers =
                    creatureSource.GetRandomDungeonAncestry(Tier);
                var tier = Tier;
                while (dungeonLurkers is null && tier > 0)
                {
                    --tier;
                    dungeonLurkers =
                        creatureSource.GetRandomDungeonAncestry(tier);
                }
                if (dungeonLurkers is null)
                {
                    break;
                }
                DungeonEcologyPool.Add(dungeonLurkers.Name);
            }

            // init lairs
            int numLairs = _dice.Roll(1, 6) - 1;

            for (int i = 0; i < numLairs; ++i)
            {
                var lair = new Lair();
                lair.InitializeAsRandomLair(this);
                // resolve any conflicting locations
                Battle results = ResolveSettlementConflicts(lair);
                if (results is null)
                {
                    // there was no battle. Just add the new lair.
                    LairList.Add(lair);
                    continue;
                }
                if (
                    (results.AttackerState
                     == Battle.CombatantState.COMBATANT_STATE_ELIMINATED) ||
                    (results.AttackerState
                     == Battle.CombatantState.COMBATANT_STATE_ROUTED)
                    )
                {
                    // dont even save the lair.
                    continue;
                }
                // attackers win, and are moved into existing lair.
            }

            string record = Name + " (" + x + ", " + y
                            + ") has been discovered.";

            if (LairList.Count > 0)
            {
                record += " The following lairs are found within: ";
                for (int i = 0; i < LairList.Count; ++i)
                {
                    var lair              = LairList[i];
                    int lastIndex         = LairList.Count - 1;
                    int secondToLastIndex = lastIndex - 1;
                    record += lair.GetFullName();
                    if (i == secondToLastIndex)
                    {
                        record += ", and ";
                        continue;
                    }
                    if (i == lastIndex)
                    {
                        continue;
                    }
                    record += ", ";
                }
            }
            History.addRecord(record);
        }