Exemplo n.º 1
0
        /// <summary>
        /// Given an ActionBase and a selection position, gets the characters that
        /// action will target seperated by AI characters and player characters.
        /// </summary>
        /// <param name="action">The action to check the targets for.</param>
        /// <param name="selectionPosition">A number representing the position the action targets.</param>
        /// <returns>A struct containing two IReadOnlyList of Characters, one for AI characters and another for player characters.</returns>
        protected SelectionCharacters GetSelectionTargets(ActionBase action, int selectionPosition)
        {
            var myCharacters     = new List <Character>();
            var playerCharacters = new List <Character>();

            // If selection is in left column and something is in the middle or right column on the same row, can't select this position
            bool leftColumnBlocked = selectionPosition % 3 == 1 &&
                                     LivingPlayerCharacters.Where(
                character =>
                (selectionPosition + 1 == character.Position || selectionPosition + 2 == character.Position) &&
                character.CurrentHealth > 0).Any();

            // If selection is in middle column and something is in the right column on the same row, can't select this position
            bool middleColumnBlocked = selectionPosition % 3 == 2 &&
                                       LivingPlayerCharacters.Where(
                character =>
                (selectionPosition + 1 == character.Position && character.CurrentHealth > 0)).Any();

            if (!action.CanSwitchTargetPosition)
            {
                var targets = AITargets.GetModifiedTargets(action);
                myCharacters.AddRange(AICharacters.Where(character => targets.Contains(character.Position)));
                playerCharacters.AddRange(LivingPlayerCharacters.Where(character => targets.Contains(character.Position)));
                return(new SelectionCharacters()
                {
                    MyCharacters = myCharacters,
                    PlayerCharacters = playerCharacters
                });
            }
            // If the action can't target through units and the selection is on the player's field
            else if (!action.CanTargetThroughUnits && selectionPosition <= 9 &&
                     (leftColumnBlocked || middleColumnBlocked))
            {
                myCharacters.Clear();
                playerCharacters.Clear();
                return(new SelectionCharacters()
                {
                    MyCharacters = myCharacters,
                    PlayerCharacters = playerCharacters
                });
            }
            else
            {
                var modifiedSelection = AITargets.GetModifiedSelection(action, selectionPosition);

                foreach (var position in modifiedSelection)
                {
                    if (position >= 10)
                    {
                        Character selectedCharacter = AICharacters.FirstOrDefault(character => character.Position == position);
                        if (selectedCharacter != null)
                        {
                            myCharacters.Add(selectedCharacter);
                        }
                    }
                    else if (position <= 9)
                    {
                        Character selectedCharacter = LivingPlayerCharacters.FirstOrDefault(character => character.Position == position);
                        if (selectedCharacter != null)
                        {
                            playerCharacters.Add(selectedCharacter);
                        }
                    }
                }

                return(new SelectionCharacters()
                {
                    MyCharacters = myCharacters,
                    PlayerCharacters = playerCharacters
                });
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets all possible actions for the active character and splits them into offensive and defensive actions,
        /// giving each a priority based on the amount of healing, damage, and/or ai weight provided by the action.
        /// </summary>
        /// <returns>A struct providing the action priorities of offensive and defensive actions.</returns>
        protected virtual ActionPriorities EvaluateActions()
        {
            var defensiveActionsPoints    = new Dictionary <ActionBase, int>();
            var offensiveActionsPoints    = new Dictionary <ActionBase, int>();
            var defensiveActionPriorities = new Dictionary <ActionBase, int>();
            var offensiveActionPriorities = new Dictionary <ActionBase, int>();
            var allActions = new List <ActionBase>();

            allActions.AddRange(_activeCharacter.Attacks);
            allActions.AddRange(_activeCharacter.SpellList);
            allActions.AddRange(_activeCharacter.SkillList);
            var consumables = _activeCharacter.Inventory
                              .Where(item => item is Consumable)
                              .Select(item => ((Consumable)item).ItemSpell);

            allActions.AddRange(consumables);

            // Use average max health as basis for effectiveness of damage and healing
            int averageMaxHealth = 0;

            foreach (var character in AICharacters)
            {
                averageMaxHealth += character.CurrentMaxHealth;
            }
            averageMaxHealth /= AICharacters.Count();

            // Calculate total healing and damage and use it to determine if an action is offensive or defensive
            foreach (var action in allActions)
            {
                int damage         = DamageCalculator.GetDamageAsInt(_activeCharacter, action);
                int healing        = DamageCalculator.GetHealing(_activeCharacter, action);
                int percentHealing = DamageCalculator.GetHealingPercentage(_activeCharacter, action);

                int netDamage = damage - healing;

                if (netDamage < 0 || percentHealing > 0 || !action.IsOffensive)
                {
                    int maxPotential = -netDamage;
                    maxPotential += (percentHealing * averageMaxHealth / 100);
                    defensiveActionsPoints[action] = maxPotential;
                }
                else
                {
                    int maxPotential = netDamage;
                    offensiveActionsPoints[action] = maxPotential;
                }
            }

            int medianHealing = MathExtensions.GetMedian(defensiveActionsPoints.Values.ToList());
            int medianDamage  = MathExtensions.GetMedian(offensiveActionsPoints.Values.ToList());

            // Assign action priorities based on how an action performs on par with other actions

            foreach (var key in defensiveActionsPoints.Keys)
            {
                int healing = defensiveActionsPoints[key];
                defensiveActionPriorities[key] = key.AiWeight;
                if (medianHealing > 0)
                {
                    if (PercentageCalculator.GetPercentage(healing, medianHealing) >= 150)
                    {
                        defensiveActionPriorities[key] += 3;
                    }
                    else if (PercentageCalculator.GetPercentage(healing, medianHealing) >= 120)
                    {
                        defensiveActionPriorities[key] += 2;
                    }
                }
                else
                {
                    defensiveActionPriorities[key] += 1;
                }
            }

            foreach (var key in offensiveActionsPoints.Keys)
            {
                int damage = offensiveActionsPoints[key];
                offensiveActionPriorities[key] = key.AiWeight;
                if (medianDamage > 0)
                {
                    if (PercentageCalculator.GetPercentage(damage, medianDamage) >= 150)
                    {
                        offensiveActionPriorities[key] += 3;
                    }
                    else if (PercentageCalculator.GetPercentage(damage, medianDamage) >= 120)
                    {
                        offensiveActionPriorities[key] += 2;
                    }
                }
                else
                {
                    offensiveActionPriorities[key] += 1;
                }
            }

            return(new ActionPriorities()
            {
                DefensiveActionPriorities = defensiveActionPriorities,
                OffensiveActionPriorities = offensiveActionPriorities
            });
        }