using System; using System.Collections; using System.Collections.Generic; using Cute; using UnityEngine; namespace Wizard; public class EnemyAI_Play { private class CalcMostValuableHandPtnObj { public AISinglePlayptnRecord PlayOutPlan; public PlayPtnWithToken[] BestPlayPtnCandidatesWithToken; } private EnemyAI _ai; private AIVirtualFieldRollBackStackProcessor _fieldRollBackProcessor; private bool _isOpenSpaceAttackCarryOut; public bool IsFusion { get; private set; } public AIFusionSituationInfo FusionPattern { get; private set; } public AIVirtualCard PriorityCard { get; private set; } public PlayedCardInfo PriorityCardPlayInfo { get; private set; } public PlayPtnWithToken BestPlayPtnWithToken { get; private set; } public AIVirtualActionInfo InstantAttackActionInfo { get; private set; } public EnemyAI_Play(EnemyAI ai) { _ai = ai; } public void InitOnIterationStart() { _isOpenSpaceAttackCarryOut = false; IsFusion = false; FusionPattern = null; PriorityCard = null; PriorityCardPlayInfo = null; BestPlayPtnWithToken = null; InstantAttackActionInfo = null; } public IEnumerator BattleAI_HandPlay() { if (_ai.CurrentVirtualField.AllyHandCards.Count <= 0) { _ai.BestPlayPtnRecord = _ai.PlayPtnRecorder.GetEmptyPlayPtnRecord(); _ai.cr_isOprPlay = false; yield break; } CalcMostValuableHandPtnObj obj = new CalcMostValuableHandPtnObj(); yield return CalcMostValuableHandPtnJob(obj); AISinglePlayptnRecord playOutPlan = obj.PlayOutPlan; PlayPtnWithToken[] bestPlayPtnCandidatesWithToken = obj.BestPlayPtnCandidatesWithToken; BestPlayPtnWithToken = null; InstantAttackActionInfo = null; if (_isOpenSpaceAttackCarryOut) { List allMovesForFullSimulation = AISimulationUtility.GetAllMovesForFullSimulation(_ai.CurrentVirtualField, doesUseEvo: false, null); if (allMovesForFullSimulation.Count <= AISimulationUtility.FULL_SIMULATION_MOVE_COUNT_TURESHOLD) { FullSimulationAI fullSimulationInstantAttack = new FullSimulationAI(_ai, allMovesForFullSimulation); yield return fullSimulationInstantAttack._CrSimulate(_ai.CurrentVirtualField, doesUseEvo: false, checkTimeOverLogic: true, bestPlayPtnCandidatesWithToken); if (!_ai.IsRunWeakLogic && fullSimulationInstantAttack.Cr_BestPlayPtnWithToken != null) { BestPlayPtnWithToken = fullSimulationInstantAttack.Cr_BestPlayPtnWithToken; InstantAttackActionInfo = fullSimulationInstantAttack.Cr_FirstActionInfo; } } else { BestOpenSpaceAttackAI instantAttack = new BestOpenSpaceAttackAI(_ai); yield return instantAttack._CrSimulate(_ai.CurrentVirtualField, bestPlayPtnCandidatesWithToken); if (!_ai.IsRunWeakLogic && instantAttack.Cr_BestPlayPtnWithToken != null) { BestPlayPtnWithToken = instantAttack.Cr_BestPlayPtnWithToken; InstantAttackActionInfo = instantAttack.Cr_FirstActionInfo; } } if (_ai.IsRunWeakLogic) { AITimeOverAttackSimulator timeOverLogic = new AITimeOverAttackSimulator(); yield return timeOverLogic._CrSimulate(_ai.CurrentVirtualField, doesUseEvo: false, checkTimeOverLogic: false, bestPlayPtnCandidatesWithToken); if (timeOverLogic.Cr_BestPlayPtnWithToken != null) { BestPlayPtnWithToken = timeOverLogic.Cr_BestPlayPtnWithToken; InstantAttackActionInfo = timeOverLogic.Cr_FirstActionInfo; } } } else { BestPlayPtnWithToken = bestPlayPtnCandidatesWithToken[0]; } List priorityList; if (BestPlayPtnWithToken == null) { priorityList = EnemyAI.EmptyPlayPtn; BestPlayPtnWithToken = null; _ai.BestPlayPtnRecord = _ai.PlayPtnRecorder.GetEmptyPlayPtnRecord(); } else { priorityList = BestPlayPtnWithToken.PlayPtn; _ai.BestPlayPtnRecord = BestPlayPtnWithToken.Record; } if (playOutPlan != null && playOutPlan.PlayPtnCount > 0) { AILethalSimulator aILethalSimulator = new AILethalSimulator(_ai); _ai.OutputLethalPlan = null; yield return EnemyAICoroutine.GetInstance().StartCoroutine(aILethalSimulator.SimulateByAISimulator(playOutPlan)); if (_ai.OutputLethalPlan != null && _ai.OutputLethalPlan.IsSuccess) { AISituationInfo action = _ai.OutputLethalPlan.ActionSequence[0]; if (_ai.OprLethalAction(action)) { _ai.cr_isOprPlay = true; yield break; } } } PriorityCard = null; PriorityCardPlayInfo = null; float priority = float.MinValue; AISinglePlayptnRecord bestPlayPtnRecord = _ai.BestPlayPtnRecord; if (priorityList != null && priorityList.Count > 0) { PriorityCard = GetPriorCard(priorityList, bestPlayPtnRecord, ref priority); if (bestPlayPtnRecord != null && PriorityCard != null) { PriorityCardPlayInfo = bestPlayPtnRecord.PlayedCardList.Find((PlayedCardInfo info) => PriorityCard.IsSameCard(info.Card)); } } IsFusion = false; FusionPattern = AIBestFusionPatternCalculator.CalculateBestFusionPattern(_ai.CurrentVirtualField, bestPlayPtnRecord); if (FusionPattern != null && FusionPattern.IsTargetExists(AIScriptTokenArgType.TARGET_SELECT)) { FusionPattern.UpdatePriority(priorityList); if (!EnemyAI.IsLargerThan(priority, FusionPattern.Priority)) { IsFusion = true; PriorityCard = FusionPattern.Actor; _ = FusionPattern.Priority; } } if (PriorityCard == null) { _ai.cr_isOprPlay = false; yield break; } AIVirtualTargetSelectAction situation = new AIVirtualTargetSelectAction(PriorityCard.FindRealActor(bestPlayPtnRecord), PriorityCard, AIOperationType.PLAY); if (!IsFusion) { _ai.PlaySkipInfo = PriorityCard.GetPlaySkipInformation(priorityList, _ai.PlaySkipInfo, situation); } for (int num = 0; num < _ai.CurrentVirtualField.CardListSet.BothClassAndInplayCards.Count; num++) { AIVirtualCard owner = _ai.CurrentVirtualField.CardListSet.BothClassAndInplayCards[num]; _ai.PlaySkipInfo = owner.GetPlaySkipInformation(priorityList, _ai.PlaySkipInfo, situation); } if (_ai.PlaySkipInfo != null) { _ai.cr_isOprPlay = false; yield break; } for (int num2 = 0; num2 < _ai.CurrentVirtualField.CardListSet.BothInplayCards.Count; num2++) { if (_ai.CurrentVirtualField.CardListSet.BothInplayCards[num2].IsBreakBeforePlay(priorityList)) { _ai.IsBreakBeforePlay = true; _ai.cr_isOprPlay = false; yield break; } } yield return _ai.HandCardAction(); } private IEnumerator CalcMostValuableHandPtnJob(CalcMostValuableHandPtnObj obj) { ParallelJob job = ParallelJob.Dispatch(delegate { try { AISinglePlayptnRecord playOutPlan; PlayPtnWithToken[] bestPlayPtnCandidatesWithToken = CalcMostValuableHandPtn(out playOutPlan); obj.PlayOutPlan = playOutPlan; obj.BestPlayPtnCandidatesWithToken = bestPlayPtnCandidatesWithToken; } catch (Exception) { } }); while (!job.isDone) { yield return null; } } public AIVirtualCard GetPriorCard(List priorityList, AISinglePlayptnRecord playptnRecord, ref float priority) { if (priorityList.Count <= 0) { return null; } AIVirtualCard result = null; for (int i = 0; i < priorityList.Count; i++) { int num = priorityList[i]; AIVirtualCard aIVirtualCard = _ai.CurrentVirtualField.AllyHandCards[num]; aIVirtualCard.FindRealActor(playptnRecord); if (aIVirtualCard.IsSpell ? aIVirtualCard.BaseCard.Movable() : aIVirtualCard.BaseCard.BaseMovable) { priority = EvaluateHandPriority(num, priorityList); result = aIVirtualCard; break; } } return result; } private PlayPtnWithToken[] CalcMostValuableHandPtn(out AISinglePlayptnRecord playOutPlan) { PlayPtnWithToken[] bestPlayPtnsWithToken = new PlayPtnWithToken[6]; float[] maxValues = new float[6]; for (int i = 0; i < 6; i++) { bestPlayPtnsWithToken[i] = null; maxValues[i] = float.MinValue; } playOutPlan = null; int num = 6 - _ai.CurrentVirtualField.CardListSet.AllyClassAndInplayCards.Count; int num2 = 0; AISinglePlayptnRecord aISinglePlayptnRecord = null; AIVirtualField aIVirtualField = new AIVirtualField(_ai.CurrentVirtualField); _fieldRollBackProcessor = new AIVirtualFieldRollBackStackProcessor(_ai.CurrentVirtualField); AIPlayptnRecorder playPtnRecorder = _ai.PlayPtnRecorder; for (int j = 0; j < playPtnRecorder.ValidPlayPtnList.Count; j++) { AISinglePlayptnRecord aISinglePlayptnRecord2 = playPtnRecorder.ValidPlayPtnList[j]; List playPtn = aISinglePlayptnRecord2.PlayPtn; if (!CheckPlayConditon(aIVirtualField, aISinglePlayptnRecord2)) { continue; } int num3 = Mathf.Max(aIVirtualField.CalculateHandPtnRequiredSpace(aISinglePlayptnRecord2) - num, 0); EvaluateHandPtn_Normal(playPtn, aISinglePlayptnRecord2, ref bestPlayPtnsWithToken, ref maxValues); if (_fieldRollBackProcessor.HasRecord) { AIConsoleUtility.LogError("EnemyAI_Play.CalcMostValuableHandPtn() error!! Called ForceResetVirtualField()"); _fieldRollBackProcessor.ResetVirtualFieldToStart(); } if (num3 <= 0) { int num4 = AIPlayOutChecker.CalculatePlayOutDamageProspected(_ai.ParamQuery, aIVirtualField, aISinglePlayptnRecord2, _ai); if (num4 > num2) { num2 = num4; aISinglePlayptnRecord = aISinglePlayptnRecord2; } else if (num4 == num2) { int num5 = aISinglePlayptnRecord?.PlayPtnCount ?? 0; if (playPtn.Count < num5) { aISinglePlayptnRecord = aISinglePlayptnRecord2; } } } if (_ai.IsRunWeakLogic) { break; } } if (num2 >= aIVirtualField.EnemyBattlePlayer.Class.Life) { playOutPlan = aISinglePlayptnRecord; } for (int k = 1; k < bestPlayPtnsWithToken.Length; k++) { PlayPtnWithToken playPtnWithToken = bestPlayPtnsWithToken[k]; if (playPtnWithToken != null && playPtnWithToken.PlayPtn != null && playPtnWithToken.PlayPtn.Count > 0) { _isOpenSpaceAttackCarryOut = true; break; } } return bestPlayPtnsWithToken; } private void EvaluateHandPtn_Normal(List handList, AISinglePlayptnRecord playPtnRecord, ref PlayPtnWithToken[] bestPlayPtnsWithToken, ref float[] maxValues) { float num = 2f; float num2 = 0f; float[] array = new float[handList.Count]; AIVirtualField currentVirtualField = _ai.CurrentVirtualField; bool isPlagueCity = _ai.IsPlagueCityTagged; AIVirtualFieldRollBackBasicProcessor aIVirtualFieldRollBackBasicProcessor = new AIVirtualFieldRollBackBasicProcessor(currentVirtualField); for (int i = 0; i < handList.Count; i++) { int index = handList[i]; PlayedCardInfo playedCardInfo = playPtnRecord.PlayedCardList[i]; AIVirtualCard aIVirtualCard = currentVirtualField.AllyHandCards[index]; AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(aIVirtualCard, aIVirtualCard, AIOperationType.PLAY); aIVirtualTargetSelectAction.SetDiscardInfo(playedCardInfo.DiscardInfo); AIPreprocessSimulationUtility.ExecuteRecordingToPlayedCardInfo(playedCardInfo, aIVirtualCard, currentVirtualField, aIVirtualTargetSelectAction, isPseudo: true); array[i] = EvaluateHandValue(aIVirtualCard, handList, isOnBattleSimulate: false, aIVirtualTargetSelectAction, ref isPlagueCity, playPtnRecord); currentVirtualField.UpdateVirtualFieldWhenEvaluation(aIVirtualCard, aIVirtualTargetSelectAction); } aIVirtualFieldRollBackBasicProcessor.ResetVirtualFieldToStart(); int dstHandCount = currentVirtualField.AllyHandCards.Count; float num3 = _ai.ParamQuery.CalcHandCardOverflowPenalty(_ai.CurrentVirtualField, handList, num, ref dstHandCount); num2 -= num3; if (currentVirtualField.AllyBattlePlayer.IsEvolve) { float num4 = 0f; for (int j = 0; j < handList.Count; j++) { int index2 = handList[j]; AIVirtualCard aIVirtualCard2 = currentVirtualField.AllyHandCards[index2]; if (!aIVirtualCard2.IsFollower(handList)) { continue; } AIVirtualTargetSelectAction situation = new AIVirtualTargetSelectAction(aIVirtualCard2, aIVirtualCard2, AIOperationType.EVOLVE, (AISelectedTargetInfoSet)null); int evoTokenCount = aIVirtualCard2.GetEvoTokenCount(currentVirtualField, handList, situation); if (0 < evoTokenCount && evoTokenCount > _ai.GetAllySpaceNum()) { continue; } float num5 = (float)Mathf.Max(aIVirtualCard2.GetEvoHandPlusCount(currentVirtualField, handList, situation) + dstHandCount - 8, 0) * num; float num6 = aIVirtualCard2.EvaluateAllEvoBonus(handList, situation) - num5; if (num6 > num4) { num4 = num6; } if (aIVirtualCard2.CreateAIVirtualSelectInfo(currentVirtualField, situation) != null) { float num7 = 0f - num5; if (num7 > num4) { num4 = num7; } } } num2 += num4; } num2 += AIEvaluateBonusFromOhterUtility.GetPlayPtnBonus(currentVirtualField, handList) + _ai.StyleQuery.GetPlayptnBonus(currentVirtualField, handList); List list = new List(); List list2 = new List(handList); if (list2.Count <= 0) { if (num2 > maxValues[0]) { bestPlayPtnsWithToken[0] = new PlayPtnWithToken(list2, playPtnRecord, list); maxValues[0] = num2; } return; } int currentSpace = 6 - currentVirtualField.CardListSet.AllyClassAndInplayCards.Count; List list3 = new List { 0f }; for (int k = 0; k < _ai.AllySuicideList.Count; k++) { AIVirtualCard aIVirtualCard3 = _ai.AllySuicideList[k]; float num8 = aIVirtualCard3.EvaluateValueOnField(list2, null, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true) - aIVirtualCard3.EvaluateBreakValue(handList, useIgnoreBreak: true) - aIVirtualCard3.EvaluateLeaveValue(handList, useIgnoreInBattle: true) - (float)aIVirtualCard3.Attack; list3.Add(list3[k] - num8); } EstimateMaxPlayPtnWithToken(playPtnRecord, list3, array, num2, isPlagueCity, 0, 0, currentSpace, list, 0f, ref bestPlayPtnsWithToken, ref maxValues); } private void EstimateMaxPlayPtnWithToken(AISinglePlayptnRecord playPtnRecord, List suicideList, float[] handValues, float optionValue, bool isPlagueCity, int playPtnIndex, int suicideIndex, int currentSpace, List currentPlayedCardsPattern, float currentValue, ref PlayPtnWithToken[] bestPlayPtnsWithToken, ref float[] maxValues) { List playPtn = playPtnRecord.PlayPtn; AIVirtualField currentVirtualField = _ai.CurrentVirtualField; int i = playPtnIndex; int num = 0; float num2 = currentValue; int num3 = 0; foreach (AIVirtualCard allyInplayCard in currentVirtualField.AllyInplayCards) { if (allyInplayCard.WhiteRitualCount > 0) { num3++; } } for (; i < playPtn.Count; i++) { int index = playPtn[i]; PlayedCardInfo playedCardInfo = playPtnRecord.PlayedCardList[i]; AIVirtualCard aIVirtualCard = currentVirtualField.AllyHandCards[index]; AIVirtualCard sourceCard = aIVirtualCard; if (playedCardInfo.TransformCard != null) { sourceCard = playedCardInfo.TransformCard; } AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(sourceCard, aIVirtualCard, AIOperationType.PLAY); aIVirtualTargetSelectAction.SetDiscardInfo(playedCardInfo.DiscardInfo); _fieldRollBackProcessor.RegisterRecord(); AIPreprocessSimulationUtility.ExecuteRecordingToPlayedCardInfo(playedCardInfo, aIVirtualCard, currentVirtualField, aIVirtualTargetSelectAction, isPseudo: true); int playSpaceRequired = currentVirtualField.GetPlaySpaceRequired(aIVirtualCard, playPtn, aIVirtualTargetSelectAction, needsTokenCount: false); AITokenIdCollection bothSideTokenIdsOfPlaySituation = AIPlayTokenSimulationUtility.GetBothSideTokenIdsOfPlaySituation(currentVirtualField, playPtn, aIVirtualTargetSelectAction); List allDiscardedTokenIds = AIDiscardUtility.GetAllDiscardedTokenIds(aIVirtualTargetSelectAction.DiscardInfo, currentVirtualField, playPtn, aIVirtualTargetSelectAction); List list = new List(); aIVirtualTargetSelectAction.SetActor(aIVirtualCard); currentVirtualField.UpdateVirtualFieldWhenEvaluation(aIVirtualCard, aIVirtualTargetSelectAction); bool flag = false; if (bothSideTokenIdsOfPlaySituation != null && bothSideTokenIdsOfPlaySituation.HasAllyToken) { List allyTokenIdList = bothSideTokenIdsOfPlaySituation.AllyTokenIdList; for (int j = 0; j < allyTokenIdList.Count; j++) { list.Add(allyTokenIdList[j]); if (num3 > 0) { AIVirtualCard tokenFromId = currentVirtualField.AI.tokenManager.GetTokenFromId(allyTokenIdList[j].TokenId, isAlly: true, currentVirtualField); if (tokenFromId != null && tokenFromId.IsStackWhiteRitual) { flag = true; } } } } if (allDiscardedTokenIds != null) { for (int k = 0; k < allDiscardedTokenIds.Count; k++) { list.Add(allDiscardedTokenIds[k]); } } int num4 = playSpaceRequired + list.Count; if (flag) { bool num5 = i == playPtn.Count - 1; bool flag2 = currentSpace - num4 < 0; num3 = ((!(num5 && flag2)) ? num3 : 0); num4 -= num3; } bool flag3 = _ai.StyleQuery.IsPlayBreak(aIVirtualCard, playPtn, aIVirtualTargetSelectAction); int num6 = 0; if (flag3) { num6 = aIVirtualCard.GetAllyLastwordTokenCount(playPtn); num4 += num6; num4 -= playSpaceRequired; } float num7 = 0f; if (bothSideTokenIdsOfPlaySituation != null && bothSideTokenIdsOfPlaySituation.HasOpponentToken) { List opponentTokenIdList = bothSideTokenIdsOfPlaySituation.OpponentTokenIdList; for (int l = 0; l < opponentTokenIdList.Count; l++) { int tokenId = opponentTokenIdList[l].TokenId; num7 += GetTokenValueFromId(tokenId, AITokenType.Default, playPtn, isAllyToken: false, isPlagueCity); } } if (num + num4 <= currentSpace) { num += num4; float num8 = 0f; for (int m = 0; m < list.Count; m++) { AITokenInformation aITokenInformation = list[m]; num8 += GetTokenValueFromId(aITokenInformation.TokenId, aITokenInformation.TokenType, playPtn, isAllyToken: true, isPlagueCity); } num8 -= num7; float num9 = handValues[i] + num8 + AIDiscardUtility.CalcAllDiscardedBonus(_ai.CurrentVirtualField, aIVirtualTargetSelectAction, playPtn); if (num9 < aIVirtualCard.GetPlayLimit(playPtn)) { _fieldRollBackProcessor.RollBackFieldWithIteration(i - playPtnIndex + 1); return; } num2 += num9; TokenPlayPattern item = new TokenPlayPattern(index, num8, list); currentPlayedCardsPattern.Add(item); continue; } currentSpace -= num; for (int n = suicideIndex; n < suicideList.Count; n++) { float num10 = num2; int num11 = currentSpace + (n - suicideIndex) - playSpaceRequired; if (num11 < 0) { continue; } bool flag4 = num11 >= list.Count; List list2 = (flag4 ? new List(list) : list.GetRange(0, num11)); num11 -= list2.Count; if (flag3) { num11 += playSpaceRequired; bool flag5 = num11 >= num6; flag4 = flag5 && flag4; num11 -= (flag5 ? num6 : num11); } float num12 = 0f; for (int num13 = 0; num13 < list2.Count; num13++) { AITokenInformation aITokenInformation2 = list2[num13]; num12 += GetTokenValueFromId(aITokenInformation2.TokenId, aITokenInformation2.TokenType, playPtn, isAllyToken: true, isPlagueCity); } num12 -= num7; float num14 = handValues[i] + num12 + AIDiscardUtility.CalcAllDiscardedBonus(currentVirtualField, aIVirtualTargetSelectAction, playPtn); if (num14 < aIVirtualCard.GetPlayLimit(playPtn)) { continue; } num10 += num14; TokenPlayPattern tokenPlayPattern = new TokenPlayPattern(index, num12, list2); currentPlayedCardsPattern.Add(tokenPlayPattern); EstimateMaxPlayPtnWithToken(playPtnRecord, suicideList, handValues, optionValue, isPlagueCity, i + 1, n, num11, currentPlayedCardsPattern, num10, ref bestPlayPtnsWithToken, ref maxValues); for (int num15 = currentPlayedCardsPattern.Count - 1; num15 >= 0; num15--) { TokenPlayPattern tokenPlayPattern2 = currentPlayedCardsPattern[num15]; currentPlayedCardsPattern.Remove(tokenPlayPattern2); if (tokenPlayPattern2 == tokenPlayPattern) { break; } } if (flag4) { break; } } _fieldRollBackProcessor.RollBackFieldWithIteration(i - playPtnIndex + 1); return; } _fieldRollBackProcessor.RollBackFieldWithIteration(i - playPtnIndex); if (i == playPtn.Count) { float num16 = num2 + suicideList[suicideIndex] + optionValue; if (bestPlayPtnsWithToken[suicideIndex] == null || num16 >= maxValues[suicideIndex]) { PlayPtnWithToken playPtnWithToken = new PlayPtnWithToken(playPtn, playPtnRecord, new List(currentPlayedCardsPattern)); bestPlayPtnsWithToken[suicideIndex] = playPtnWithToken; maxValues[suicideIndex] = num16; } } } private float GetTokenValueFromId(int id, AITokenType tokenType, List playPtn, bool isAllyToken, bool isPlagueCity) { AIVirtualCard aIVirtualCard = _ai.tokenManager.GetTokenFromId(id, isAllyToken, _ai.CurrentVirtualField); if (aIVirtualCard == null) { AIConsoleUtility.LogError("CalculateMaxTokenPatternValue: Could not get a token from the tokenPool."); return 0f; } if (isPlagueCity && aIVirtualCard.IsUnit) { aIVirtualCard = _ai.tokenManager.GetZombieToken(isAlly: true, _ai.CurrentVirtualField); } float num = aIVirtualCard.EvaluateValueOnField(playPtn, null, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true) + (aIVirtualCard.EvaluateBreakValue(playPtn, useIgnoreBreak: false) + aIVirtualCard.EvaluateLeaveValue(playPtn, useIgnoreInBattle: false)) * EnemyAI.BREAKBONUS_RATE_IN_HAND; if (tokenType == AITokenType.Reanimate) { num += aIVirtualCard.GetReanimateBonus(playPtn); } return num; } public float EvaluateHandValue(AIVirtualCard handCard, List handList, bool isOnBattleSimulate, AIVirtualTargetSelectAction play, ref bool isPlagueCity, AISinglePlayptnRecord playptnRecord) { if (isPlagueCity && handCard.IsUnit) { handCard = _ai.tokenManager.GetZombieToken(isAlly: true, _ai.CurrentVirtualField); } else if (!isPlagueCity && handCard.IsPlagueCity(_ai.CurrentVirtualField, handList)) { isPlagueCity = true; } AIVirtualCard aIVirtualCard = new AIVirtualCard(handCard, _ai.CurrentVirtualField); AIPlayptnBaseStatsRateUtility.Execute(_ai.CurrentVirtualField.CardListSet.AllyClassAndInplayCards, new List { aIVirtualCard }, EnemyAI.EmptyPlayPtn); AIPlayptnBaseStatsRateUtility.Execute(_ai.CurrentVirtualField.CardListSet.EnemyClassAndInplayCards, new List { aIVirtualCard }, EnemyAI.EmptyPlayPtn); return EvaluateHandValue(aIVirtualCard, handList, play, isOnBattleSimulate, playptnRecord); } public float EvaluateHandValue(AIVirtualCard card, List handList, AIVirtualTargetSelectAction play, bool isOnBattleSimulate, AISinglePlayptnRecord playptnRecord) { if (AITargetSelectFilteringUtility.IsOnlyIgnoreTarget(card, _ai.CurrentVirtualField, handList, playptnRecord)) { return 0f; } if (card.IsSpell || card.IsAccelerated(_ai.CurrentVirtualField, handList) || card.IsCrystalize(_ai.CurrentVirtualField, handList)) { return card.EvaluatePlayValue(handList, play) * _ai.StyleQuery.GetAllyPlayBonusRate(card, handList, play); } float num = 0f; if (_ai.StyleQuery.IsPlayBreak(card, handList, play)) { num = card.EvaluatePlayValue(handList, play) + card.EvaluateBreakValue(handList, useIgnoreBreak: true) + card.EvaluateLeaveValue(handList, useIgnoreInBattle: true); } else { num = card.EvaluatePlayValue(handList, play); num += card.EvaluateValueOnField(handList, null, useStyle: true); num += (card.EvaluateBreakValue(handList, useIgnoreBreak: false) + card.EvaluateLeaveValue(handList, useIgnoreInBattle: false)) * EnemyAI.BREAKBONUS_RATE_IN_HAND; } return num * _ai.StyleQuery.GetAllyPlayBonusRate(card, handList, play); } public float EvaluateHandPriority(int handIndex, List playPtn) { return _ai.CurrentVirtualField.AllyHandCards[handIndex].GetPriority(playPtn); } private bool CheckPlayConditon(AIVirtualField field, AISinglePlayptnRecord playPtnRecord) { List playPtn = playPtnRecord.PlayPtn; if (CalcHandPtnLifeCost(field, playPtn) >= field.AllyBattlePlayer.Class.Life) { return false; } if (!field.IsPlayableHandList(playPtnRecord, field.AI.AllySuicideList)) { return false; } return true; } private int CalcHandPtnLifeCost(AIVirtualField field, List handList) { int num = 0; EnemyAI aI = field.AI; for (int i = 0; i < handList.Count; i++) { int index = handList[i]; AIVirtualCard aIVirtualCard = field.AllyHandCards[index]; num += AIPlayOnSkillUtility.GetLifePenaltyOnPlay(aIVirtualCard.BaseCard, aI); } return num; } }