Compile-driven bulk-copy loop (tools/engine-port/m1_copy_loop.py) pulled the precise reference closure of the battle-core roots, stopping at the classify god-object/View-VFX-UI boundary. 782 files; no re-explosion (M0 had estimated ~order 1000). Residual frontier = 52 shim-classified + 80 external (Unity/BCL) types to author next.
434 lines
15 KiB
C#
434 lines
15 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace Wizard;
|
||
|
||
public class AIPlayptnRecorder
|
||
{
|
||
private List<AISinglePlayptnRecord> _allPlayPtnList;
|
||
|
||
private List<AIVirtualField> _referenceFieldList;
|
||
|
||
private bool _isRegisteringPlayPtn;
|
||
|
||
private bool _isCalculatingPriority;
|
||
|
||
public List<AISinglePlayptnRecord> ValidPlayPtnList { get; private set; }
|
||
|
||
public AIPlayptnRecorder()
|
||
{
|
||
ValidPlayPtnList = new List<AISinglePlayptnRecord>();
|
||
_allPlayPtnList = new List<AISinglePlayptnRecord>();
|
||
_referenceFieldList = new List<AIVirtualField>();
|
||
_isRegisteringPlayPtn = false;
|
||
}
|
||
|
||
public static void BuildSinglePlayptnRecord(List<int> playPtn, AISinglePlayptnRecord currentRecord, AIVirtualField field, AIVirtualFieldRollBackBasicProcessor rollBackProcessor)
|
||
{
|
||
List<int> list = new List<int>();
|
||
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<Tuple<int, List<int>>> 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<int> 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<int> 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<int> 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<int> 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<int> playPtn, AISituationInfo situation, PlaySimulationType targetPlayType)
|
||
{
|
||
List<int> 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<int> playPtn, AISituationInfo situation, PlaySimulationType targetPlayType)
|
||
{
|
||
List<int> 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<int> 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<int> 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<int> 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<int> 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<int> list = new List<int>();
|
||
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;
|
||
}
|
||
}
|