Files
SVSimServer/SVSim.BattleEngine/Engine/Wizard/AIPlayptnRecorder.cs
gamer147 0d9d8acae0 feat(battle-engine): M1 auto-copy closure (782 battle-logic files)
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.
2026-06-05 16:57:20 -04:00

434 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}