using System.Collections.Generic; using UnityEngine; namespace Wizard; public class AIPlayptnRecorder { private List _allPlayPtnList; private List _referenceFieldList; private bool _isRegisteringPlayPtn; private bool _isCalculatingPriority; public List ValidPlayPtnList { get; private set; } public AIPlayptnRecorder() { ValidPlayPtnList = new List(); _allPlayPtnList = new List(); _referenceFieldList = new List(); _isRegisteringPlayPtn = false; } public static void BuildSinglePlayptnRecord(List playPtn, AISinglePlayptnRecord currentRecord, AIVirtualField field, AIVirtualFieldRollBackBasicProcessor rollBackProcessor) { List list = new List(); int num = 0; for (int i = 0; i < currentRecord.PlayedCardList.Count; i++) { if (!currentRecord.PlayedCardList[i].IsProcessed) { num = i; break; } list.Add(playPtn[i]); } for (int j = num; j < playPtn.Count; j++) { int num2 = playPtn[j]; list.Add(num2); PlayedCardInfo playedCardInfo = currentRecord.PlayedCardList[j]; AIVirtualCard aIVirtualCard = field.AllyHandCards[num2]; AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(aIVirtualCard, aIVirtualCard, AIOperationType.PLAY); PlaySimulationType playType; int num3 = (playedCardInfo.UsedCost = aIVirtualCard.GetUseCost(currentRecord.LastRestPp, list, aIVirtualTargetSelectAction, out playType)); if (num3 >= 0) { int num4 = currentRecord.LastRestPp - num3; playedCardInfo.PlayType = playType; num4 += AIEvaluateBonusFromOhterUtility.GetTotalRecoverPp(aIVirtualCard, playPtn, aIVirtualTargetSelectAction); playedCardInfo.RestPp = num4; playedCardInfo.DrawCount = aIVirtualCard.GetPlayDrawCount(list, aIVirtualTargetSelectAction); SetTransformCardToPlayedInfo(playedCardInfo, aIVirtualCard, field, list, aIVirtualTargetSelectAction, num3, playType); } else { playedCardInfo.RestPp = -1; playedCardInfo.PlayType = PlaySimulationType.Undefined; } if (num == 0) { playedCardInfo.IsPassedPlayCondition = aIVirtualCard.BaseCard.BaseMovable; } else { playedCardInfo.IsPassedPlayCondition = true; } currentRecord.UpdatePlayPtnRecord(playedCardInfo); if (!currentRecord.IsValid) { break; } AIPreprocessSimulationUtility.SimulatePreprocess(aIVirtualTargetSelectAction.Actor, aIVirtualTargetSelectAction, field, AIScriptTokenArgType.WHEN_PLAY, isPseudo: true); currentRecord.RegisterPreprocess(playedCardInfo, aIVirtualTargetSelectAction, field); PseudoExecuteCardPlayProcess(field, currentRecord, playedCardInfo, aIVirtualTargetSelectAction); } rollBackProcessor.ResetVirtualFieldToStart(); } public void CreateValidPlayPtnList(AIVirtualField field) { AIVirtualFieldRollBackBasicProcessor rollBackProcessor = new AIVirtualFieldRollBackBasicProcessor(field); int fieldIndex = RegisterFieldAndGetFieldIndex(field); List>> list = AIHandPtnCalculator.CreateSortedPlayPtnList(field.AI); _isRegisteringPlayPtn = true; for (int i = 0; i < list.Count; i++) { AISinglePlayptnRecord aISinglePlayptnRecord = new AISinglePlayptnRecord(list[i].second, field, fieldIndex); _allPlayPtnList.Add(aISinglePlayptnRecord); ProcessPlayPtnRecord(aISinglePlayptnRecord, field, rollBackProcessor); } _isRegisteringPlayPtn = false; } private void ProcessPlayPtnRecord(AISinglePlayptnRecord currentRecord, AIVirtualField field, AIVirtualFieldRollBackBasicProcessor rollBackProcessor) { List playPtn = currentRecord.PlayPtn; AISinglePlayptnRecord aISinglePlayptnRecord = FindMostlyMatchedPlayPtn(currentRecord); if (aISinglePlayptnRecord != null) { if (!aISinglePlayptnRecord.IsValid) { _allPlayPtnList.Remove(currentRecord); return; } currentRecord = RegisterMatchedRecordToNewRecord(aISinglePlayptnRecord, field, currentRecord); } if (!currentRecord.IsValid) { rollBackProcessor.ResetVirtualFieldToStart(); return; } BuildSinglePlayptnRecord(playPtn, currentRecord, field, rollBackProcessor); if (currentRecord.IsToBeRegister() && currentRecord.IsValid && !CheckSimilarValidPlayPtnRecord(currentRecord.PlayPtnHash)) { ValidPlayPtnList.Add(currentRecord); } } public AISinglePlayptnRecord FindMatchedPlayPtnRecord(List playPtn, AIVirtualField playPtnField) { ulong hash = playPtnField.GetHash(); int num = GetFieldIndex(hash); for (int i = 0; i < _allPlayPtnList.Count; i++) { AISinglePlayptnRecord aISinglePlayptnRecord = _allPlayPtnList[i]; if (aISinglePlayptnRecord.PlayPtn.Count != playPtn.Count || num != aISinglePlayptnRecord.ReferenceFieldIndex) { continue; } bool flag = true; for (int j = 0; j < playPtn.Count; j++) { if (!playPtnField.AllyHandCards[playPtn[j]].IsSameCard(aISinglePlayptnRecord.PlayedCardList[j].Card)) { flag = false; break; } } if (flag) { return aISinglePlayptnRecord; } } if (_isRegisteringPlayPtn) { AIConsoleUtility.LogError("FindMatchedPlayPtnRecordで無限ループが発生しそうです!!!!!"); return null; } _isRegisteringPlayPtn = true; if (num < 0) { _referenceFieldList.Add(playPtnField); num = _referenceFieldList.Count - 1; } AISinglePlayptnRecord aISinglePlayptnRecord2 = new AISinglePlayptnRecord(playPtn, playPtnField, num); _allPlayPtnList.Add(aISinglePlayptnRecord2); AIVirtualFieldRollBackBasicProcessor rollBackProcessor = new AIVirtualFieldRollBackBasicProcessor(playPtnField); ProcessPlayPtnRecord(aISinglePlayptnRecord2, playPtnField, rollBackProcessor); _isRegisteringPlayPtn = false; return aISinglePlayptnRecord2; } public void StartCalculatingPriority() { _isCalculatingPriority = true; } public void StopCalculatingPriority() { _isCalculatingPriority = false; } public int GetRestPp(List playPtn, AIVirtualField field) { if (_isCalculatingPriority) { AIConsoleUtility.LogWarning("AIPlayptnRecorder.GetRestPp() warning!! Calling GetRestPp() during calculating priority!!!!!"); return 0; } int allyPp = field.AllyPp; if (playPtn == null || playPtn.Count <= 0) { return allyPp; } AISinglePlayptnRecord playptnRecordOnSim = field.GetPlayptnRecordOnSim(playPtn); if (playptnRecordOnSim == null) { return allyPp; } allyPp = playptnRecordOnSim.LastRestPp; return Mathf.Max(0, allyPp); } public int GetFixedCostWithCheckingPlayType(AIVirtualCard card, AIVirtualField field, List playPtn, out PlaySimulationType playType) { int restPp = (card.IsAlly ? field.AllyPp : field.EnemyPp); if (playPtn == null || playPtn.Count <= 0 || !card.IsAlly) { return card.GetUseCost(restPp, playPtn, null, out playType); } int cardPlayPtnIndex = GetCardPlayPtnIndex(card, field, playPtn); if (cardPlayPtnIndex == -1) { return card.GetUseCost(restPp, playPtn, null, out playType); } return GetCardCostAndTypeFromPlayPtnRecord(card, cardPlayPtnIndex, field, playPtn, out playType); } public bool IsCardPlayingSimulationType(AIVirtualCard card, AIVirtualField field, List playPtn, AISituationInfo situation, PlaySimulationType targetPlayType) { List list = (card.IsAlly ? playPtn : null); int restPp = (card.IsAlly ? field.AllyPp : field.EnemyPp); int num = -1; if (card.IsAlly && list != null && list.Count > 0) { num = field.AI.PlayPtnRecorder.GetCardPlayPtnIndex(card, field, list); } if (num != -1) { field.AI.PlayPtnRecorder.GetCardCostAndTypeFromPlayPtnRecord(card, num, field, list, out var playType); return playType == targetPlayType; } return card.IsPlayingSimulationType(restPp, playPtn, situation, targetPlayType); } public int GetCardPlaySimulationTypeCost(AIVirtualCard card, AIVirtualField field, List playPtn, AISituationInfo situation, PlaySimulationType targetPlayType) { List list = (card.IsAlly ? playPtn : null); int restPp = (card.IsAlly ? field.AllyPp : field.EnemyPp); int num = -1; if (card.IsAlly && list != null && list.Count > 0) { num = field.AI.PlayPtnRecorder.GetCardPlayPtnIndex(card, field, list); } if (num != -1) { PlaySimulationType playType; int cardCostAndTypeFromPlayPtnRecord = field.AI.PlayPtnRecorder.GetCardCostAndTypeFromPlayPtnRecord(card, num, field, list, out playType); if (playType != targetPlayType) { return -1; } return cardCostAndTypeFromPlayPtnRecord; } return card.GetPlaySimulationTypeCost(restPp, playPtn, situation, targetPlayType); } public int GetCardPlayPtnIndex(AIVirtualCard card, AIVirtualField field, List playPtn) { int item = -1; for (int i = 0; i < field.AllyHandCards.Count; i++) { if (field.AllyHandCards[i].IsSameCard(card)) { item = i; break; } } int num = playPtn.IndexOf(item); if (num < 0) { AIConsoleUtility.LogError("AIPlayPtnRecorder.GetFixedCostWithCheckingPlayType() error!! card is not in playPtn!!!!!"); } return num; } public int GetCardCostAndTypeFromPlayPtnRecord(AIVirtualCard card, int playPtnIndex, AIVirtualField field, List playPtn, out PlaySimulationType playType) { AISinglePlayptnRecord aISinglePlayptnRecord = FindMatchedPlayPtnRecord(playPtn, field); playType = PlaySimulationType.Undefined; if (aISinglePlayptnRecord != null) { PlayedCardInfo playedCardInfo = aISinglePlayptnRecord.PlayedCardList[playPtnIndex]; if (playedCardInfo.Card.IsSameCard(card)) { playType = playedCardInfo.PlayType; return playedCardInfo.UsedCost; } AIConsoleUtility.LogError("AIPlayPtnRecorder.GetCardCostAndTypeInPlayPtnRecord() error!! Cannot find same card from matched playPtn record!!!!!"); return -1; } AIConsoleUtility.LogError("AIPlayPtnRecorder.GetCardCostAndTypeInPlayPtnRecord() error!! Cannot find record!!!!!"); return -1; } private AISinglePlayptnRecord RegisterMatchedRecordToNewRecord(AISinglePlayptnRecord matched, AIVirtualField field, AISinglePlayptnRecord newRecord) { for (int i = 0; i < matched.PlayedCardList.Count; i++) { PlayedCardInfo playedCardInfo = newRecord.PlayedCardList[i]; playedCardInfo.CloneFromPartlyMatchedInfo(matched.PlayedCardList[i]); AIVirtualCard card = playedCardInfo.Card; AIVirtualCard obj = ((playedCardInfo.TransformCard == null) ? card : playedCardInfo.TransformCard); AIVirtualTargetSelectAction situation = new AIVirtualTargetSelectAction(obj, card, AIOperationType.PLAY); AIPreprocessSimulationUtility.SimulatePreprocess(obj, situation, field, AIScriptTokenArgType.WHEN_PLAY, isPseudo: true); newRecord.RegisterPreprocess(playedCardInfo, situation, field); newRecord.UpdatePlayPtnRecord(playedCardInfo); PseudoExecuteCardPlayProcess(field, newRecord, playedCardInfo, situation); if (!newRecord.IsValid) { break; } } return newRecord; } private AISinglePlayptnRecord FindMostlyMatchedPlayPtn(AISinglePlayptnRecord record) { AISinglePlayptnRecord result = null; int num = 0; List playPtn = record.PlayPtn; for (int i = 0; i < _allPlayPtnList.Count; i++) { AISinglePlayptnRecord aISinglePlayptnRecord = _allPlayPtnList[i]; int count = aISinglePlayptnRecord.PlayPtn.Count; if (record.ReferenceFieldIndex == aISinglePlayptnRecord.ReferenceFieldIndex && playPtn.Count > count && aISinglePlayptnRecord.IsMatchedPattern(playPtn) && count > num) { num = count; result = aISinglePlayptnRecord; } } return result; } private static void SetTransformCardToPlayedInfo(PlayedCardInfo info, AIVirtualCard playedCard, AIVirtualField field, List playPtn, AIVirtualTargetSelectAction situation, int usedCost, PlaySimulationType type) { if (AIPlayCardSimulationUtility.SetRealActorToPlaySituation(situation, field, usedCost, type)) { info.SetTransformCard(situation.Actor); } } private static void PseudoExecuteCardPlayProcess(AIVirtualField field, AISinglePlayptnRecord record, PlayedCardInfo playedCardInfo, AIVirtualTargetSelectAction situation) { AIVirtualCard card = playedCardInfo.Card; if (card.IsSpell || card.IsAccelerated(field, null, situation)) { AIPlayCardSimulationUtility.UpdateFieldWhenEvaluateSpellCard(card, field); } if (card.IsUnit) { record.FirstSummonedAllyFollower = card; } field.PlayedCardContainer.AddPlayedCard(card); card.PseudoExecuteWhenPlayTags(field, record, playedCardInfo, situation); field.AllActivateCountHolderIncrement(situation, AIPlayTagType.PlayActivateCount, card); field.IsNoInstantAttackRecheck(); } private bool CheckSimilarValidPlayPtnRecord(ulong currentRecordHash) { for (int i = 0; i < ValidPlayPtnList.Count; i++) { if (ValidPlayPtnList[i].PlayPtnHash == currentRecordHash) { return true; } } return false; } private int RegisterFieldAndGetFieldIndex(AIVirtualField field) { ulong hash = field.GetHash(); for (int i = 0; i < _referenceFieldList.Count; i++) { if (_referenceFieldList[i].GetHash() == hash) { return i; } } _referenceFieldList.Add(field); return _referenceFieldList.Count - 1; } private int GetFieldIndex(ulong fieldHash) { for (int i = 0; i < _referenceFieldList.Count; i++) { if (fieldHash == _referenceFieldList[i].GetHash()) { return i; } } return -1; } public AISinglePlayptnRecord GetEmptyPlayPtnRecord() { AISinglePlayptnRecord aISinglePlayptnRecord = ValidPlayPtnList[0]; if (aISinglePlayptnRecord.PlayedCardList.Count > 0) { AIConsoleUtility.LogError("AIPlayPtnRecorder.GetEmptyPlayPtnRecord() error!! first record is not empty!!!!!"); } return aISinglePlayptnRecord; } public AISinglePlayptnRecord CreateRecordForNextPlayTargetSelectSimulation(AIVirtualTargetSelectAction action, AISinglePlayptnRecord previousRecord, AIVirtualField field) { bool num = action.ActionType == AIOperationType.PLAY; int fieldIndex = RegisterFieldAndGetFieldIndex(field); List list = new List(); for (int i = (num ? 1 : 0); i < previousRecord.PlayedCardList.Count; i++) { AIVirtualCard card = previousRecord.PlayedCardList[i].Card; AIVirtualCard aIVirtualCard = field.SearchVirtualCard(card); if (aIVirtualCard == null) { AIConsoleUtility.LogError("AIPlayptnRecorder.CreateRecordForNextPlayTargetSelectSimulation() error!! Cannot find play card!!!!!"); } else if (aIVirtualCard.IsInHand) { int num2 = field.AllyHandCards.IndexOf(aIVirtualCard); if (num2 < 0 || field.AllyHandCards.Count <= num2) { AIConsoleUtility.LogError($"CreateRecordForNextPlayTargetSelectSimulation() error!! handIndex: {num2}, CardName: {aIVirtualCard.CardName}"); return null; } list.Add(num2); } } AISinglePlayptnRecord aISinglePlayptnRecord = new AISinglePlayptnRecord(list, field, fieldIndex); _isRegisteringPlayPtn = true; _allPlayPtnList.Add(aISinglePlayptnRecord); AIVirtualFieldRollBackBasicProcessor rollBackProcessor = new AIVirtualFieldRollBackBasicProcessor(field); ProcessPlayPtnRecord(aISinglePlayptnRecord, field, rollBackProcessor); _isRegisteringPlayPtn = false; return aISinglePlayptnRecord; } }