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.
356 lines
12 KiB
C#
356 lines
12 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Wizard;
|
|
|
|
public class EnemyAI_Attack
|
|
{
|
|
private class PlaySkipExecutingInfo
|
|
{
|
|
public bool IsEvolutionPermitted;
|
|
|
|
public List<AIVirtualActionInfo> SimulationExtraActionBaseList;
|
|
|
|
public PlaySkipExecutingInfo()
|
|
{
|
|
IsEvolutionPermitted = false;
|
|
SimulationExtraActionBaseList = null;
|
|
}
|
|
|
|
public void AddExtraAction(AIVirtualActionInfo action)
|
|
{
|
|
SimulationExtraActionBaseList = AIParamQuery.AddElementToList(action, SimulationExtraActionBaseList);
|
|
}
|
|
}
|
|
|
|
private EnemyAI _ai;
|
|
|
|
private IBattleSimulationAI _simulationResultWithEmptyPlayPtn;
|
|
|
|
public bool IsLethalAttackPlan { get; private set; }
|
|
|
|
public EnemyAI_Attack(EnemyAI ai)
|
|
{
|
|
_ai = ai;
|
|
_simulationResultWithEmptyPlayPtn = null;
|
|
}
|
|
|
|
public void InitOnTurnStart()
|
|
{
|
|
_simulationResultWithEmptyPlayPtn = null;
|
|
}
|
|
|
|
public void InitOnIterationStart()
|
|
{
|
|
_simulationResultWithEmptyPlayPtn = null;
|
|
}
|
|
|
|
public IEnumerator BattleAI_UseHighSimu()
|
|
{
|
|
AIVirtualField currentVirtualField = _ai.CurrentVirtualField;
|
|
AISinglePlayptnRecord playPtnRecord = _ai.BestPlayPtnRecord;
|
|
PlaySkipExecutingInfo playSkipExecutingInfo = CreatePlaySkipExecutingInfo(playPtnRecord);
|
|
bool flag = playSkipExecutingInfo?.IsEvolutionPermitted ?? true;
|
|
bool isEvol = _ai.IsEvoPermissionOnSimu && flag && !_ai.IsBreakBeforePlay;
|
|
float fastEvoMaxValue = float.MinValue;
|
|
AIVirtualCard evolveFollower = null;
|
|
AIVirtualActionInfo firstAction = null;
|
|
bool isLethalByEvo = false;
|
|
if (isEvol)
|
|
{
|
|
int allyIndex = 0;
|
|
while (allyIndex < currentVirtualField.AllyInplayCards.Count)
|
|
{
|
|
AIVirtualCard inplayTemp = currentVirtualField.AllyInplayCards[allyIndex];
|
|
if (inplayTemp.IsAbleEvolution())
|
|
{
|
|
AIVirtualTargetSelectAction situation = new AIVirtualTargetSelectAction(inplayTemp, inplayTemp, AIOperationType.EVOLVE, (AISelectedTargetInfoSet)null);
|
|
SimulationResult ref_skillSim = new SimulationResult();
|
|
List<AIVirtualTargetSelectInfo> list = inplayTemp.CreateAIVirtualSelectInfo(currentVirtualField, situation);
|
|
if (list != null)
|
|
{
|
|
AIVirtualTargetSelectSimulationInfo simulationInfo = new AIVirtualTargetSelectSimulationInfo
|
|
{
|
|
OriginalActor = inplayTemp,
|
|
RealActor = inplayTemp,
|
|
SelectInfoList = list,
|
|
OperationType = AIOperationType.EVOLVE,
|
|
NextPlayCardInfo = null,
|
|
IsFirstAction = true
|
|
};
|
|
yield return EnemyAICoroutine.GetInstance().StartCoroutine(AIVirtualTargetSelectSimulator.SimulateTargetSelect(simulationInfo, _ai.CurrentVirtualField, playPtnRecord, ref_skillSim, isBattleSim: true));
|
|
if (IsTargetSelectEvolutionValid(ref_skillSim, inplayTemp, fastEvoMaxValue))
|
|
{
|
|
isLethalByEvo = ref_skillSim.IsLethalPlan;
|
|
fastEvoMaxValue = ref_skillSim.MaxFieldValue;
|
|
firstAction = ref_skillSim.FirstActionInfo;
|
|
evolveFollower = inplayTemp;
|
|
}
|
|
}
|
|
}
|
|
int num = allyIndex + 1;
|
|
allyIndex = num;
|
|
}
|
|
}
|
|
AIVirtualField field = new AIVirtualField(_ai.CurrentVirtualField)
|
|
{
|
|
BestPlayPtn = _ai.BestPlayPtn
|
|
};
|
|
SimulationAdditionalActionInfoSet additionalActionInfoSet = new SimulationAdditionalActionInfoSet
|
|
{
|
|
ForceEvoAction = null,
|
|
ExtraActionBaseList = playSkipExecutingInfo?.SimulationExtraActionBaseList,
|
|
PlayPtnRecord = playPtnRecord
|
|
};
|
|
AIBattleSimulationLauncher battleSimLauncher = new AIBattleSimulationLauncher(field, _ai, isEvol, _simulationResultWithEmptyPlayPtn, additionalActionInfoSet);
|
|
yield return battleSimLauncher.ExecuteBattleSimulationAI(null, checkTimeOverLogic: true);
|
|
IBattleSimulationAI battleSimAI = battleSimLauncher.BattleSimAI;
|
|
if (_ai.IsBreakBeforePlay && battleSimAI.Cr_MaxField != null && !battleSimAI.Cr_MaxField.IsBreakBeforePlayKilled)
|
|
{
|
|
_ai.cr_isOprAtk = false;
|
|
yield break;
|
|
}
|
|
if (battleSimAI.Cr_MaxFieldValue > fastEvoMaxValue)
|
|
{
|
|
if (battleSimAI.Cr_FirstActionInfo != null && !(battleSimAI.Cr_FirstActionInfo is AIVirtualTurnEndInfo))
|
|
{
|
|
firstAction = battleSimAI.Cr_FirstActionInfo;
|
|
evolveFollower = battleSimAI.Cr_MaxField.EvoUsedCard;
|
|
IsLethalAttackPlan = battleSimAI.Cr_MaxField.EnemyClass.IsDead;
|
|
}
|
|
else
|
|
{
|
|
firstAction = null;
|
|
IsLethalAttackPlan = isLethalByEvo;
|
|
evolveFollower = null;
|
|
}
|
|
}
|
|
if (firstAction == null)
|
|
{
|
|
_ai.cr_isOprAtk = false;
|
|
}
|
|
else if (!IsPlaySkipPermitted(evolveFollower))
|
|
{
|
|
_ai.cr_isOprAtk = false;
|
|
}
|
|
else if (firstAction.ActionType == AIOperationType.PLAY)
|
|
{
|
|
foreach (PlayedCardInfo playedCard in _ai.BestPlayPtnRecord.PlayedCardList)
|
|
{
|
|
if (playedCard.PreDecidedSelectTargets != null && firstAction.OriginalCard.IsSameCard(playedCard.Card))
|
|
{
|
|
_ai.SetPreDecidedTargets(playedCard.PreDecidedSelectTargets);
|
|
break;
|
|
}
|
|
}
|
|
_ai.OprPlay(firstAction.OriginalCard, _ai.BestPlayPtnRecord);
|
|
_ai.cr_isOprAtk = true;
|
|
}
|
|
else if (firstAction.ActionType == AIOperationType.EVOLVE)
|
|
{
|
|
_ai.CurrentBattleBeforeSimEvoEvolCount = _ai.PlayerPair.Self.CurrentEpCount;
|
|
_ai.OprEvolution(firstAction.Actor);
|
|
_ai.CurrentBattleSimEvoCard = evolveFollower;
|
|
_ai.cr_isOprAtk = true;
|
|
}
|
|
else if (firstAction.ActionType == AIOperationType.ATTACK)
|
|
{
|
|
_ai.OprAttack(firstAction);
|
|
_ai.cr_isOprAtk = true;
|
|
}
|
|
else
|
|
{
|
|
_ai.cr_isOprAtk = false;
|
|
}
|
|
}
|
|
|
|
public bool IsPlaySkipPermitted(AIVirtualCard evolveFollower)
|
|
{
|
|
if (_ai.PlaySkipInfo == null || !_ai.PlaySkipInfo.Any())
|
|
{
|
|
return true;
|
|
}
|
|
bool result = false;
|
|
for (int i = 0; i < _ai.PlaySkipInfo.Count; i++)
|
|
{
|
|
if (_ai.PlaySkipInfo[i].IsEvoCardLegal(evolveFollower))
|
|
{
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private PlaySkipExecutingInfo CreatePlaySkipExecutingInfo(AISinglePlayptnRecord playPtnRecord)
|
|
{
|
|
List<PlaySkipInformation> playSkipInfo = _ai.PlaySkipInfo;
|
|
if (playSkipInfo == null || playSkipInfo.Count <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
PlaySkipExecutingInfo playSkipExecutingInfo = new PlaySkipExecutingInfo();
|
|
List<AIScriptTokenArgType> checkedActionTypeList = null;
|
|
for (int i = 0; i < playSkipInfo.Count; i++)
|
|
{
|
|
PlaySkipInformation playSkipInformation = playSkipInfo[i];
|
|
if (playSkipInformation.IsEvolutionPermittedTag)
|
|
{
|
|
playSkipExecutingInfo.IsEvolutionPermitted = true;
|
|
}
|
|
AIVirtualActionInfo aIVirtualActionInfo = null;
|
|
if (!(playSkipInformation is PlaySkipWithActionInformation playSkipWithActionInformation))
|
|
{
|
|
if (playSkipInformation is PlaySkipWithActionIfEvoInformation playSkipWithActionIfEvoInformation)
|
|
{
|
|
aIVirtualActionInfo = playSkipWithActionIfEvoInformation.GetExtraActionBase(playPtnRecord, ref checkedActionTypeList);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aIVirtualActionInfo = playSkipWithActionInformation.GetExtraActionBase(playPtnRecord, ref checkedActionTypeList);
|
|
}
|
|
if (aIVirtualActionInfo != null)
|
|
{
|
|
playSkipExecutingInfo.AddExtraAction(aIVirtualActionInfo);
|
|
}
|
|
}
|
|
return playSkipExecutingInfo;
|
|
}
|
|
|
|
private bool IsTargetSelectEvolutionValid(SimulationResult result, AIVirtualCard targetSelectEvoOwner, float valueForComparing)
|
|
{
|
|
if (result.BestResultField == null)
|
|
{
|
|
return false;
|
|
}
|
|
AIVirtualCard evoUsedCard = result.BestResultField.EvoUsedCard;
|
|
if (evoUsedCard == null || !evoUsedCard.IsSameCard(targetSelectEvoOwner))
|
|
{
|
|
return false;
|
|
}
|
|
if (result.MaxFieldValue <= valueForComparing)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool BattleAI_TurnEndAttack()
|
|
{
|
|
AIVirtualField aIVirtualField = new AIVirtualField(_ai.CurrentVirtualField)
|
|
{
|
|
BestPlayPtn = _ai.BestPlayPtn
|
|
};
|
|
AIVirtualField aIVirtualField2 = new AIVirtualField(aIVirtualField);
|
|
List<AIVirtualActionInfo> moves = new List<AIVirtualActionInfo>();
|
|
AIVirtualTurnEndInfo aIVirtualTurnEndInfo = new AIVirtualTurnEndInfo(aIVirtualField2.AllyClass);
|
|
moves.Add(aIVirtualTurnEndInfo);
|
|
BattleSequencer.OnAfterExecuteAttackCommon(aIVirtualField2, aIVirtualTurnEndInfo, ref moves);
|
|
float num = AISimulationUtility.EvaluateField(aIVirtualField2, EvaluationType.SIMPLE);
|
|
float num2 = float.MinValue;
|
|
AIVirtualCard aIVirtualCard = null;
|
|
AIVirtualCard aIVirtualCard2 = null;
|
|
for (int i = 0; i < aIVirtualField.AllyInplayCards.Count; i++)
|
|
{
|
|
if (!aIVirtualField.AllyInplayCards[i].IsUnit)
|
|
{
|
|
continue;
|
|
}
|
|
for (int j = -1; j < aIVirtualField.EnemyInplayCards.Count; j++)
|
|
{
|
|
if (j >= 0 && !aIVirtualField.EnemyInplayCards[j].IsUnit)
|
|
{
|
|
continue;
|
|
}
|
|
aIVirtualField2 = new AIVirtualField(aIVirtualField);
|
|
moves.Clear();
|
|
AIVirtualCard aIVirtualCard3 = aIVirtualField2.AllyInplayCards[i];
|
|
AIVirtualCard aIVirtualCard4 = ((j < 0) ? aIVirtualField2.EnemyClass : aIVirtualField2.EnemyInplayCards[j]);
|
|
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(aIVirtualCard3, aIVirtualCard4);
|
|
if (AIAttackSimulationUtility.IsAttackPossible(aIVirtualField2, aIVirtualAttackInfo))
|
|
{
|
|
moves.Add(aIVirtualAttackInfo);
|
|
AIVirtualAttackSimulator.Attack(aIVirtualAttackInfo, aIVirtualField2);
|
|
AIVirtualTurnEndInfo aIVirtualTurnEndInfo2 = new AIVirtualTurnEndInfo(aIVirtualField2.AllyClass);
|
|
moves.Add(aIVirtualTurnEndInfo2);
|
|
BattleSequencer.OnAfterExecuteAttackCommon(aIVirtualField2, aIVirtualTurnEndInfo2, ref moves);
|
|
num2 = AISimulationUtility.EvaluateField(aIVirtualField2, EvaluationType.SIMPLE);
|
|
if (num2 > num)
|
|
{
|
|
num = num2;
|
|
aIVirtualCard = aIVirtualCard3;
|
|
aIVirtualCard2 = aIVirtualCard4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (aIVirtualCard != null && aIVirtualCard2 != null)
|
|
{
|
|
_ai.OprAttack(new AIVirtualAttackInfo(aIVirtualCard, aIVirtualCard2));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public IEnumerator Cr_BattleAI_ImmediateAttack()
|
|
{
|
|
AIVirtualField aIVirtualField = new AIVirtualField(_ai.CurrentVirtualField);
|
|
AIVirtualTurnEndInfo turnEndSituation = new AIVirtualTurnEndInfo(aIVirtualField.AllyClass);
|
|
BattleSequencer.ProcessAllyTurnEndToOpponentTurnStart(aIVirtualField, turnEndSituation);
|
|
if (aIVirtualField.IsSuccess())
|
|
{
|
|
_ai.cr_isTerminate = true;
|
|
_ai.IsTurnEndLethal = true;
|
|
yield break;
|
|
}
|
|
if (!_ai.CurrentVirtualField.isForceImmediateAttack())
|
|
{
|
|
int num = _ai.CurrentVirtualField.EnemyInplayCards.Count((AIVirtualCard card) => card.IsGuard);
|
|
int num2 = _ai.CurrentVirtualField.AllyInplayCards.Count((AIVirtualCard card) => card.IsAttackable(EnemyAI.EmptyPlayPtn));
|
|
bool flag = _ai.CurrentVirtualField.AllyInplayCards.Any((AIVirtualCard card) => card.IsIgnoreGuard);
|
|
if (num >= num2 && !flag)
|
|
{
|
|
_ai.cr_isTerminate = false;
|
|
yield break;
|
|
}
|
|
}
|
|
_simulationResultWithEmptyPlayPtn = new BestInPlayMoveAI(_ai);
|
|
yield return EnemyAICoroutine.GetInstance().StartCoroutine(_simulationResultWithEmptyPlayPtn._CrSimulate(_ai.CurrentVirtualField, doesUseEvo: true, checkTimeOverLogic: true));
|
|
if (_ai.IsRunWeakLogic)
|
|
{
|
|
_simulationResultWithEmptyPlayPtn = new AITimeOverAttackSimulator();
|
|
yield return _simulationResultWithEmptyPlayPtn._CrSimulate(_ai.CurrentVirtualField, doesUseEvo: true, checkTimeOverLogic: false);
|
|
}
|
|
AIVirtualField cr_MaxField = _simulationResultWithEmptyPlayPtn.Cr_MaxField;
|
|
if (cr_MaxField == null || !cr_MaxField.EnemyClass.IsDead || cr_MaxField.AllyClass.IsDead)
|
|
{
|
|
_ai.cr_isTerminate = false;
|
|
yield break;
|
|
}
|
|
AIVirtualActionInfo cr_FirstActionInfo = _simulationResultWithEmptyPlayPtn.Cr_FirstActionInfo;
|
|
if (cr_FirstActionInfo == null)
|
|
{
|
|
_ai.cr_isTerminate = false;
|
|
yield break;
|
|
}
|
|
_ai.cr_isTerminate = true;
|
|
if (cr_FirstActionInfo.ActionType == AIOperationType.EVOLVE && !cr_FirstActionInfo.Actor.BaseCard.IsEvolution)
|
|
{
|
|
_ai.OprEvolution(cr_FirstActionInfo.Actor);
|
|
}
|
|
else if (cr_FirstActionInfo.ActionType == AIOperationType.ATTACK)
|
|
{
|
|
if ((cr_FirstActionInfo as AIVirtualAttackInfo).AttackTarget != null)
|
|
{
|
|
_ai.OprAttack(cr_FirstActionInfo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ai.cr_isTerminate = false;
|
|
}
|
|
}
|
|
}
|