예제 #1
0
    public static void AiCommandPhase(Faction ourFac, List <Commander> commandableCmders,
                                      CommandPhaseMan phaseScript)
    {
        Zone zoneCmderIsIn, moveDestZone, scoreCheckZone,
             fallbackMoveDestZone = null;

        List <Commander> ourCmders = ourFac.OwnedCommanders;

        List <Zone> emptyNewCmderZones = GameController.GetZonesForNewCmdersOfFaction(ourFac);

        bool curZoneIsContested;

        //how close to our max cmders?
        float factionCmderAmountRatio = ourCmders.Count / (float)ourFac.MaxCmders;

        float recruitChance, topMoveScore, scoreCheckScore, trainChance;
        bool  isInDangerousZone = false;

        bool factionHasEnemy = ourFac.GetDiplomaticEnemies().Count > 0;

        //use the same random values for all cmders for more cohesion
        float friendlyTooDangerousThreshold = GetRandomFriendlyTooDangerousThreshold(),
              moveScoreThreshold            = GetRandomMoveScoreThreshold(),
              allyNearbyInfluenceFactor     = GetRandomNearbyTroopInfluenceFactor(),
              enemyNearbyInfluenceFactor    = GetRandomNearbyTroopInfluenceFactor(),
              atkNeutralDiscouragement      = GetRandomAtkOnNeutralFactionDiscouragement();

        for (int i = commandableCmders.Count - 1; i >= 0; i--)
        {
            zoneCmderIsIn = GameController.GetZoneByID(commandableCmders[i].zoneIAmIn);

            curZoneIsContested = zoneCmderIsIn.IsContested();

            //recruit chance might be more than 100%,
            //but it's ok as it will do something else if it can't recruit
            recruitChance = curZoneIsContested ? 0.0f :
                            commandableCmders[i].GetPercentOfNewTroopsIfRecruitedComparedToCurrent() *
                            RECRUIT_CHANCE_ENCOURAGEMENT;

            trainChance = curZoneIsContested ? 0.0f :
                          commandableCmders[i].GetPercentOfTroopsUpgradedIfTrained();

            moveDestZone = zoneCmderIsIn;
            //if no zone beats this score, we stay
            topMoveScore = GetZoneDangerScore(zoneCmderIsIn, ourFac, false,
                                              allyNearbyInfluenceFactor, enemyNearbyInfluenceFactor);

            //but too much danger is bad and should reduce our chances of staying!
            //(reduce all scores so that the cmder may flee to safety)
            if (topMoveScore >= friendlyTooDangerousThreshold)
            {
                recruitChance    /= topMoveScore;
                trainChance      /= topMoveScore;
                topMoveScore      = moveScoreThreshold;
                isInDangerousZone = true;
            }

            //if our territories are full of cmders, also make it more likely to move around
            if (factionCmderAmountRatio < SHOULD_GET_MORE_CMDERS_THRESHOLD &&
                emptyNewCmderZones.Count == 0)
            {
                topMoveScore  *= factionCmderAmountRatio;
                recruitChance *= factionCmderAmountRatio;
                trainChance   *= factionCmderAmountRatio;
            }

            foreach (int nearbyZoneID in zoneCmderIsIn.linkedZones)
            {
                scoreCheckZone = GameController.GetZoneByID(nearbyZoneID);

                scoreCheckScore = GetZoneMoveScore(scoreCheckZone, ourFac, isInDangerousZone,
                                                   factionHasEnemy, allyNearbyInfluenceFactor, enemyNearbyInfluenceFactor,
                                                   atkNeutralDiscouragement, friendlyTooDangerousThreshold, moveScoreThreshold);

                //if we're low on commanders,
                //we should try to be more selective in our attacks...
                //make room for new cmders by stacking existing cmders in a friendly zone and stuff
                if (factionCmderAmountRatio < SHOULD_GET_MORE_CMDERS_THRESHOLD)
                {
                    if (scoreCheckZone.ownerFaction != ourFac.ID &&
                        ourFac.GetStandingWith(scoreCheckZone.ownerFaction) != GameFactionRelations.FactionStanding.ally)
                    {
                        scoreCheckScore *= factionCmderAmountRatio * factionCmderAmountRatio;
                    }
                    else
                    {
                        if (emptyNewCmderZones.Count == 1 &&
                            emptyNewCmderZones[0] == scoreCheckZone)
                        {
                            //better not move to this spot, it's the only place for a new cmder
                            scoreCheckScore *= factionCmderAmountRatio * factionCmderAmountRatio;
                        }
                        else if (emptyNewCmderZones.Count == 0)
                        {
                            //make it more likely to move to this spot then
                            scoreCheckScore += Mathf.Lerp(0.0f, MAX_MAKE_ROOM_SCORE_BONUS, (1 - factionCmderAmountRatio));
                        }
                    }
                }

                if (scoreCheckScore > topMoveScore)
                {
                    topMoveScore = scoreCheckScore;
                    moveDestZone = scoreCheckZone;
                }
            }

            if (topMoveScore <= SHOULD_GO_DEFENSIVE_THRESHOLD)
            {
                //Debug.Log("safe-landlocked! move score is " + topMoveScore);
                //we're "safe-landlocked"! none of the zones around are too interesting.
                //we should find a path to danger then
                if (fallbackMoveDestZone == null)
                {
                    //get a good destination zone for the faction
                    fallbackMoveDestZone = FindInterestingZone(ourFac);
                    //Debug.Log("Faction " + ourFac.name + " got " + fallbackMoveDestZone.name +
                    //	" as fallback moveDest zone");
                }

                moveDestZone = GetNextZoneInPathToZone(fallbackMoveDestZone, zoneCmderIsIn);
                topMoveScore = MAX_MOVE_SCORE_THRESHOLD;
                //Debug.Log("when trying to go from " + zoneCmderIsIn.name + " to " +
                //	fallbackMoveDestZone.name + ", cmder got " + moveDestZone.name + " as path");
            }

            //action time!
            bool hasActed = false;
            bool plansOnStayingInCurZone = moveDestZone.ID == zoneCmderIsIn.ID;

            if (trainChance > recruitChance &&
                (plansOnStayingInCurZone || trainChance > topMoveScore))
            {
                hasActed = commandableCmders[i].OrderTrainTroops();
            }

            if (!hasActed && (plansOnStayingInCurZone || recruitChance > topMoveScore))
            {
                hasActed = commandableCmders[i].OrderRecruitTroops();
            }

            if (!hasActed && topMoveScore > moveScoreThreshold)
            {
                if (!plansOnStayingInCurZone)
                {
                    phaseScript.MoveCommander(commandableCmders[i], moveDestZone.MyZoneSpot, false);
                    //refresh the empty zone list if we moved;
                    //that way, our other cmders may not "feel" the same need to move as this one did
                    emptyNewCmderZones = GameController.GetZonesForNewCmdersOfFaction(ourFac);
                    hasActed           = true;
                }
            }

            if (!hasActed && !curZoneIsContested)
            {
                //if we decided to do nothing else, train troops
                hasActed = commandableCmders[i].OrderTrainTroops();

                //try recruiting again if we can't train!
                if (!hasActed)
                {
                    commandableCmders[i].OrderRecruitTroops();
                }

                //do nothing then
                //Debug.Log("commander from " + ourFac.name + " at " + zoneCmderIsIn.name +
                //	" decided to do nothing. Move score: " + topMoveScore + ", rec score: " + recruitChance +
                //	", train score: " + trainChance);
            }



            commandableCmders.RemoveAt(i);
        }
    }