/// <summary> /// Given an action, a dictionary of character priorities, and whether or not an action is considered an /// offensive action, gets the maximum possible priority of the action and it's target. /// </summary> /// <param name="action">The action to get the max priority target for.</param> /// <param name="priorities">A dictionary containing the priorities for each character target.</param> /// <param name="isOffensive">Whether or not an action is considered an offensive action.</param> /// <returns>A struct containing the max priority and it's target position.</returns> protected virtual MaxPriorityTarget GetMaxPriorityTarget(ActionBase action, Dictionary <Character, int> priorities, bool isOffensive = false) { int maxPriority = 0; int maxPotentialTarget = 0; if (!action.CanSwitchTargetPosition) { var characterTargets = GetSelectionTargets(action, action.CenterOfTargetsPosition); maxPotentialTarget = AITargets.GetModifiedCenter(action.CenterOfTargetsPosition); foreach (var character in characterTargets.MyCharacters) { maxPriority += isOffensive ? -priorities[character] : priorities[character]; } foreach (var character in characterTargets.PlayerCharacters) { maxPriority += isOffensive ? priorities[character] : -priorities[character]; } } else { // Loops through all possible target positions and find the highest priority for this action for (int i = 0; i <= 18; i++) { int totalPriority = 0; var characterTargets = GetSelectionTargets(action, i); foreach (var character in characterTargets.MyCharacters) { totalPriority += isOffensive ? -priorities[character] : priorities[character]; } foreach (var character in characterTargets.PlayerCharacters) { totalPriority += isOffensive ? priorities[character] : -priorities[character]; } // If the current target's total priority is greater than the previous highest priority, or if equal, // change highest priority with 50% chance if (totalPriority > maxPriority || (totalPriority == maxPriority && _rand.Next(0, 2) == 1)) { maxPriority = totalPriority; maxPotentialTarget = i; } } } return(new MaxPriorityTarget() { TotalPriority = maxPriority, TargetPosition = maxPotentialTarget }); }
/// <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 }); } }