using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Wizard; public static class AIVirtualTargetSelectSimulator { public static IEnumerator ExecuteTargetSelect(AIVirtualTargetSelectSimulationInfo simulationInfo, AIVirtualField field, AISinglePlayptnRecord playPtnRecord) { SimulationResult result = new SimulationResult(); yield return EnemyAICoroutine.GetInstance().StartCoroutine(SimulateTargetSelect(simulationInfo, field, playPtnRecord, result, isBattleSim: false)); AIVirtualCard originalActor = simulationInfo.OriginalActor; AIOperationType operationType = simulationInfo.OperationType; field.AI.OprTargetSelect(originalActor, result.SelectedTargets, operationType); } public static IEnumerator SimulateTargetSelect(AIVirtualTargetSelectSimulationInfo simulationInfo, AIVirtualField field, AISinglePlayptnRecord playPtnRecord, SimulationResult result, bool isBattleSim) { List selectInfoList = simulationInfo.SelectInfoList; if (selectInfoList == null || selectInfoList.Count <= 0) { simulationInfo.ForceStopNextPlay(); AIConsoleUtility.LogError("SimulateTargetSelect error!! no candidates!!!!!"); yield break; } AIVirtualTargetSelectAction action = simulationInfo.CreateSituationForTargetSelectSimulation(); AISelectedTargetInfoSet preDecidedTargets = field.AI.PreDecidedTargets; List allTargetPattern = GetAllTargetSelectSimulationPattern(selectInfoList, preDecidedTargets, action, field, playPtnRecord); if (allTargetPattern == null || allTargetPattern.Count <= 0) { simulationInfo.ForceStopNextPlay(); yield break; } bool isSecondTargetForbbidenSelectedTarget = selectInfoList.Count > 1 && selectInfoList[1].IsForbiddenSelectedTarget; for (int i = 0; i < allTargetPattern.Count; i++) { AISelectedTargetInfoSet currentPattern = allTargetPattern[i]; AISelectedTargetInfoSet previousBestPattern; if (simulationInfo.IsFirstAction) { simulationInfo.FirstActionTargetTemp = currentPattern; previousBestPattern = result.SelectedTargets; } else { previousBestPattern = simulationInfo.CurrentSimulationBestTargetTemp; } if (!IsAbleToReplaceDummyTarget(currentPattern, previousBestPattern, isSecondTargetForbbidenSelectedTarget)) { continue; } if (!currentPattern.IsTargetExist(0) && currentPattern.IsTargetExist(1)) { AIConsoleUtility.LogError("currentPattern.firstTarget is null & secondTaget is not null"); continue; } AIVirtualField aIVirtualField = new AIVirtualField(field) { BestPlayPtn = new List(playPtnRecord.PlayPtn) }; AIVirtualCard aIVirtualCard = aIVirtualField.SearchVirtualCard(action.OriginalCard); AIVirtualCard actor = action.Actor; AIVirtualTargetSelectAction action2 = new AIVirtualTargetSelectAction(actor.IsSameCard(aIVirtualCard) ? aIVirtualCard : new AIVirtualCard(actor, aIVirtualField), selectedTargetList: currentPattern.GetSimilarTargetInfoSet(aIVirtualField), original: aIVirtualCard, operationType: action.ActionType); yield return SimulateSinglePattern(action2, simulationInfo, aIVirtualField, result, playPtnRecord, isBattleSim); if (result.IsRecentlyUpdated) { result.SelectedTargets = simulationInfo.FirstActionTargetTemp; simulationInfo.CurrentSimulationBestTargetTemp = currentPattern; if (result.IsLethalPlan) { break; } } else if (simulationInfo.IsRecentlyUpdatedCurrentSimulationBestTargetTempValue) { simulationInfo.CurrentSimulationBestTargetTemp = currentPattern; } } } private static IEnumerator SimulateSinglePattern(AIVirtualTargetSelectAction action, AIVirtualTargetSelectSimulationInfo simulationInfo, AIVirtualField field, SimulationResult result, AISinglePlayptnRecord playPtnRecord, bool isBattleSim) { AIVirtualTargetSelectAction aIVirtualTargetSelectAction = null; switch (action.ActionType) { case AIOperationType.EVOLVE: if (!isBattleSim) { AIVirtualEvolutionSimulator.ManualEvolve(action, field); } else { aIVirtualTargetSelectAction = action; } break; case AIOperationType.PLAY: { PlaySimulationInfo playInfo = AIPlayCardSimulationUtility.CreatePlaySimulationInfo(action.OriginalCard, action, field); AIVirtualPlaySimulator.PlayCard(action, field, playInfo); break; } default: throw new NotImplementedException(); } float removalBonus = GetRemovalBonus(action.SelectedTargets) + simulationInfo.PrevRemovalBonus; if (!isBattleSim && field.EnemyClass.Life <= 0) { result.MaxFieldValue = EnemyAI_Skill.PLAYOUT_VALUE; result.IsLethalPlan = true; result.MaxFieldValueAtSelfTurnEnd = result.MaxFieldValue; result.MaxFieldValueFirstSkill = result.MaxFieldValue; result.IsRecentlyUpdated = true; result.FirstActionInfo = new AIVirtualTargetSelectAction(action.Actor, action.OriginalCard, action.ActionType, action.SelectedTargets); result.BestResultField = field; yield break; } EnemyAI ai = field.AI; result.IsRecentlyUpdated = false; SimulationAdditionalActionInfoSet additionalActionInfoSet = new SimulationAdditionalActionInfoSet { ForceEvoAction = aIVirtualTargetSelectAction, ExtraActionBaseList = null, PlayPtnRecord = playPtnRecord }; AIBattleSimulationLauncher battleSimLauncher = new AIBattleSimulationLauncher(field, ai, aIVirtualTargetSelectAction == null, null, additionalActionInfoSet); yield return battleSimLauncher.ExecuteBattleSimulationAI(null, checkTimeOverLogic: true); IBattleSimulationAI battleSimulationAI = battleSimLauncher.BattleSimAI; float valueWithBonusPoint = battleSimulationAI.Cr_MaxFieldValue + removalBonus; AIVirtualTargetSelectSimulationInfo nextPlayCardSimulationInfo = (field.AI.IsRunWeakLogic ? null : simulationInfo.CreateNextPlayCardTargetSelectSimulationInfo(field, removalBonus)); if (nextPlayCardSimulationInfo != null) { nextPlayCardSimulationInfo.FieldValueAfterFirstSelectCardPlay = valueWithBonusPoint; AISinglePlayptnRecord aISinglePlayptnRecord = ai.PlayPtnRecorder.CreateRecordForNextPlayTargetSelectSimulation(action, playPtnRecord, field); if (aISinglePlayptnRecord == null) { simulationInfo.IsCurrentSimulationBestTargetTempNeedsToUpdated(valueWithBonusPoint); yield break; } yield return SimulateTargetSelect(nextPlayCardSimulationInfo, field, aISinglePlayptnRecord, result, isBattleSim: false); if (nextPlayCardSimulationInfo.IsInterruptedNextPlay) { UpdateSimulationResultAfterBattle(result, battleSimulationAI, valueWithBonusPoint, simulationInfo); } else { simulationInfo.IsCurrentSimulationBestTargetTempNeedsToUpdated(valueWithBonusPoint); } } else { UpdateSimulationResultAfterBattle(result, battleSimulationAI, valueWithBonusPoint, simulationInfo); } } private static void UpdateSimulationResultAfterBattle(SimulationResult result, IBattleSimulationAI battleSimulationAI, float valueWithBonus, AIVirtualTargetSelectSimulationInfo simulationInfo) { if (IsBetterThanCurrentBestResult(valueWithBonus, simulationInfo.FieldValueAfterFirstSelectCardPlay, battleSimulationAI, result)) { result.IsLethalPlan = battleSimulationAI.Cr_MaxField.EnemyClass.IsDead; result.MaxFieldValue = valueWithBonus; result.MaxFieldValueAtSelfTurnEnd = battleSimulationAI.Cr_MaxFieldValueAtSelfTurnEnd; result.MaxFieldValueFirstSkill = simulationInfo.FieldValueAfterFirstSelectCardPlay; result.FirstActionInfo = battleSimulationAI.Cr_FirstActionInfo; result.BestResultField = battleSimulationAI.Cr_MaxField; result.IsRecentlyUpdated = true; } simulationInfo.IsCurrentSimulationBestTargetTempNeedsToUpdated(valueWithBonus); } private static bool IsBetterThanCurrentBestResult(float finalValue, float valueAfterFirstCardPlay, IBattleSimulationAI simulator, SimulationResult bestRecord) { if (EnemyAI.IsLargerThan(finalValue, bestRecord.MaxFieldValue)) { return true; } if (EnemyAI.IsSameValue(finalValue, bestRecord.MaxFieldValue) && (EnemyAI.IsLargerThan(valueAfterFirstCardPlay, bestRecord.MaxFieldValueFirstSkill) || EnemyAI.IsLargerThan(simulator.Cr_MaxFieldValueAtSelfTurnEnd, bestRecord.MaxFieldValueAtSelfTurnEnd))) { return true; } return false; } public static List GetAllTargetSelectSimulationPattern(List selectInfoList, AISelectedTargetInfoSet preDecidedTargetSet, AIVirtualTargetSelectAction situation, AIVirtualField field, AISinglePlayptnRecord playPtnRecord) { if (selectInfoList.Count > 2) { throw new Exception("GetAllTargetSelectSimulationPattern error!! selectInfoList.Count == " + selectInfoList.Count); } if (selectInfoList.Count == 1) { return GetAllSingleTargetSelectSimulationPattern(selectInfoList[0], preDecidedTargetSet, situation, field, playPtnRecord); } return GetAllMultipleTargetSelectSimulationpattern(selectInfoList[0], selectInfoList[1], preDecidedTargetSet, situation, field, playPtnRecord); } private static List GetAllSingleTargetSelectSimulationPattern(AIVirtualTargetSelectInfo selectInfo, AISelectedTargetInfoSet preDecidedTargetSet, AIVirtualTargetSelectAction situation, AIVirtualField field, AISinglePlayptnRecord playPtnRecord) { List list = new List(); if (preDecidedTargetSet != null && preDecidedTargetSet.IsAnyTargetExists() && CheckWhenBurialRiteIsDefault(preDecidedTargetSet, selectInfo)) { list.Add(preDecidedTargetSet); } else { List allTargetPatternList = GetAllTargetPatternList(selectInfo, situation, field, playPtnRecord); if (allTargetPatternList == null || allTargetPatternList.Count <= 0) { return null; } bool isReplacedFirstInfoByBurialOrChoice = selectInfo.Type == TargetSelectType.BurialRite || selectInfo.Type == TargetSelectType.Choice; for (int i = 0; i < allTargetPatternList.Count; i++) { AISelectedTargetInfoSet item = CreateTargetInfoSet(allTargetPatternList[i], null, isReplacedFirstInfoByBurialOrChoice); list.Add(item); } } return list; } private static bool CheckWhenBurialRiteIsDefault(AISelectedTargetInfoSet targetInfo, AIVirtualTargetSelectInfo selectInfo) { if (targetInfo.PreprocessTarget != null && targetInfo.PreprocessTarget.Type == TargetSelectType.BurialRite && selectInfo.Type == TargetSelectType.Default) { return false; } return true; } private static List GetAllMultipleTargetSelectSimulationpattern(AIVirtualTargetSelectInfo firstSelectInfo, AIVirtualTargetSelectInfo secondSelectInfo, AISelectedTargetInfoSet preDecidedTargetSet, AIVirtualTargetSelectAction situation, AIVirtualField field, AISinglePlayptnRecord playPtnRecord) { List list = null; List list2 = null; bool flag = false; if (preDecidedTargetSet != null) { if (firstSelectInfo.Type == TargetSelectType.BurialRite && preDecidedTargetSet.PreprocessTarget != null && preDecidedTargetSet.PreprocessTarget.HasTarget) { list = AIParamQuery.AddElementToList(preDecidedTargetSet.PreprocessTarget, list); flag = true; } if (preDecidedTargetSet.HasChoiceTarget) { list = AIParamQuery.AddElementToList(preDecidedTargetSet.ChoiceTarget, list); flag = true; } if (preDecidedTargetSet.IsTargetExist(0)) { AISelectedTargetInfo element = preDecidedTargetSet.Get(0); if (flag) { list2 = AIParamQuery.AddElementToList(element, list2); } else { list = AIParamQuery.AddElementToList(element, list); if (preDecidedTargetSet.IsTargetExist(1)) { list2 = AIParamQuery.AddElementToList(preDecidedTargetSet.Get(1), list2); } } } } if (list == null) { list = GetAllTargetPatternList(firstSelectInfo, situation, field, playPtnRecord); } if (list2 == null) { list2 = GetAllTargetPatternList(secondSelectInfo, situation, field, playPtnRecord); } if (list == null || list.Count <= 0 || list2 == null || list2.Count <= 0) { return null; } List list3 = new List(); AISelectedTargetInfo aISelectedTargetInfo = list2[0]; List list4 = new List(); for (int i = 0; i < list.Count; i++) { AISelectedTargetInfo aISelectedTargetInfo2 = list[i]; if (secondSelectInfo.IsForbiddenSelectedTarget && aISelectedTargetInfo2.IsSelectedSameTarget(aISelectedTargetInfo)) { list4.Add(aISelectedTargetInfo2); continue; } AISelectedTargetInfoSet item = CreateTargetInfoSet(aISelectedTargetInfo2, aISelectedTargetInfo, flag); list3.Add(item); } for (int j = 1; j < list2.Count; j++) { AISelectedTargetInfo aISelectedTargetInfo3 = list2[j]; AISelectedTargetInfoSet item2 = CreateTargetInfoSet(null, aISelectedTargetInfo3, flag); list3.Add(item2); if (list4.Count <= 0) { continue; } for (int k = 0; k < list4.Count; k++) { AISelectedTargetInfo aISelectedTargetInfo4 = list4[k]; if (!secondSelectInfo.IsForbiddenSelectedTarget || !aISelectedTargetInfo4.IsSelectedSameTarget(aISelectedTargetInfo3)) { AISelectedTargetInfoSet item3 = CreateTargetInfoSet(aISelectedTargetInfo4, aISelectedTargetInfo3, flag); list3.Add(item3); } } } return list3; } private static List ConvertTargetPatternArrayToInfoList(List targetPatternArray, TargetSelectType targetSelectType, AIRemovalType removalType) { List list = new List(); for (int i = 0; i < targetPatternArray.Count; i++) { AISelectedTargetInfo aISelectedTargetInfo = new AISelectedTargetInfo(targetSelectType, removalType); AIVirtualCard[] array = targetPatternArray[i]; foreach (AIVirtualCard target in array) { aISelectedTargetInfo.AddTarget(target); } list.Add(aISelectedTargetInfo); } return list; } private static List GetAllTargetPatternList(AIVirtualTargetSelectInfo selectInfo, AIVirtualTargetSelectAction situation, AIVirtualField field, AISinglePlayptnRecord playPtnRecord) { AIVirtualCard actor = situation.Actor; List playPtn = ((playPtnRecord == null) ? EnemyAI.EmptyPlayPtn : playPtnRecord.PlayPtn); List list = new List(); switch (selectInfo.Type) { case TargetSelectType.Choice: { AISelectedTargetInfo choiceTargets = selectInfo.GetChoiceTargets(actor, field, playPtn, situation); if (choiceTargets != null) { list.Add(choiceTargets); } break; } case TargetSelectType.BurialRite: { bool isBreakPlayptn; AISelectedTargetInfo burialSelectTargets = selectInfo.GetBurialSelectTargets(situation, field, selectInfo, playPtnRecord, out isBreakPlayptn); if (burialSelectTargets != null) { list.Add(burialSelectTargets); } break; } case TargetSelectType.NormalRuleBase: { AISelectedTargetInfo ruleBaseTargets = selectInfo.GetRuleBaseTargets(situation, field); if (ruleBaseTargets != null) { list.Add(ruleBaseTargets); } break; } case TargetSelectType.Default: { List list2 = AIMathematicsLibrary.EnumerateCombinations(selectInfo.Candidates, selectInfo.Count).ToList(); if (list2 != null && list2.Count > 0) { list = ConvertTargetPatternArrayToInfoList(list2, selectInfo.Type, selectInfo.RemovalType); } break; } } return list; } private static AISelectedTargetInfoSet CreateTargetInfoSet(AISelectedTargetInfo firstTarget, AISelectedTargetInfo secondTarget, bool isReplacedFirstInfoByBurialOrChoice) { AISelectedTargetInfoSet aISelectedTargetInfoSet = new AISelectedTargetInfoSet(); if (isReplacedFirstInfoByBurialOrChoice) { if (firstTarget != null) { if (firstTarget.Type == TargetSelectType.BurialRite) { aISelectedTargetInfoSet.SetPreprocessTarget(firstTarget); } else if (firstTarget.Type == TargetSelectType.Choice) { aISelectedTargetInfoSet.SetChoiceTarget(firstTarget); } } aISelectedTargetInfoSet.Set(secondTarget, 0); } else { aISelectedTargetInfoSet.Set(firstTarget, 0); aISelectedTargetInfoSet.Set(secondTarget, 1); } return aISelectedTargetInfoSet; } public static bool IsAbleToReplaceDummyTarget(AISelectedTargetInfoSet currentPattern, AISelectedTargetInfoSet previousBestPattern, bool isSecondTargetForbbidenSelectedTarget) { if (previousBestPattern == null) { return true; } if (previousBestPattern.PreprocessTarget != null && currentPattern.PreprocessTarget == null) { currentPattern.SetPreprocessTarget(previousBestPattern.PreprocessTarget); return true; } if (previousBestPattern.ChoiceTarget != null && currentPattern.ChoiceTarget == null) { currentPattern.SetChoiceTarget(previousBestPattern.ChoiceTarget); return true; } if (!currentPattern.IsTargetExist(0)) { AISelectedTargetInfo aISelectedTargetInfo = previousBestPattern.Get(0); if (!isSecondTargetForbbidenSelectedTarget || !currentPattern.Get(1).IsSelectedSameTarget(aISelectedTargetInfo)) { currentPattern.Set(aISelectedTargetInfo, 0); return true; } return false; } return true; } private static float GetRemovalBonus(AISelectedTargetInfoSet selectedTargetInfoSet) { float num = 0f; for (int i = 0; i < AISelectedTargetInfoSet.LENGTH; i++) { AISelectedTargetInfo aISelectedTargetInfo = selectedTargetInfoSet.Get(i); if (aISelectedTargetInfo != null) { AIRemovalType removalType = aISelectedTargetInfo.RemovalType; List targets = aISelectedTargetInfo.Targets; for (int j = 0; j < targets.Count; j++) { num += GetTargetRemovalBonus(targets[j], removalType); } } } return num; } private static float GetTargetRemovalBonus(AIVirtualCard target, AIRemovalType removalType) { float num = 0f; List emptyPlayPtn = EnemyAI.EmptyPlayPtn; switch (removalType) { case AIRemovalType.Banish: num += (float)((!target.IsAlly) ? 1 : (-1)) * (target.EvaluateBreakValue(emptyPlayPtn, useIgnoreBreak: true) - target.GetAllBanishBonus(emptyPlayPtn, useIgnoreInBattle: true) - target.EvaluateLeaveValue(emptyPlayPtn, useIgnoreInBattle: true)); break; case AIRemovalType.Bounce: num += (float)(target.IsAlly ? 1 : (-1)) * (target.GetBounceBonus() + target.EvaluateLeaveValue(emptyPlayPtn, useIgnoreInBattle: true)); break; case AIRemovalType.Metamorphose: num += (float)((!target.IsAlly) ? 1 : (-1)) * (target.EvaluateBreakValue(emptyPlayPtn, useIgnoreBreak: true) + target.GetAllBanishBonus(emptyPlayPtn, useIgnoreInBattle: true)); break; } return num; } }