Files
SVSimServer/SVSim.BattleEngine/Engine/Wizard/AIRuleBaseBattleSimulator.cs
gamer147 957af3d1ec feat(battle-engine): full Unity/VFX/god-object shims + expanded copy closure (2570 files)
Authored Unity primitive/object-model shim, VFX layer (control-flow-preserving, InstantVfx never invokes its action -- headless suppression), god-object stubs (GameMgr/EffectMgr/UIManager with faithfully-extracted nested enums), View/UI/Touch tree, LitJson+BetterList+Tuple copied, third-party stubs. Discovered Roslyn header-error masking: fixing class-header type errors unmasks body references, so the true copy closure is ~2570 files (was 782 under masking). Errors: masked-25720 -> 268; our shim files compile clean. Remaining: ~50 residual shim/external types, 24 NGUI UI-base overrides, static-type fixes, plus likely 1-2 more unmask waves.
2026-06-05 17:22:20 -04:00

104 lines
4.0 KiB
C#

using System.Collections.Generic;
using System.Linq;
namespace Wizard;
public class AIRuleBaseBattleSimulator
{
private EnemyAI _ai;
private PlayPtnWithToken[] _bestPlayPtnWithToken;
private bool _canChangeToTimeOverLogic;
public AIRuleBaseBattleSimulator(EnemyAI ai, PlayPtnWithToken[] bestPlayPtnWithToken, bool canChangeToTimeOverLogic)
{
_ai = ai;
_bestPlayPtnWithToken = bestPlayPtnWithToken;
_canChangeToTimeOverLogic = canChangeToTimeOverLogic;
}
public void RunSequence(AIVirtualField originalField, int[] actionPermList, int evoIndex, List<int> enemyTargets, SimulationResult bestRecord, SimulationAdditionalActionInfoSet additionalOptions, InplayMovePatternFilter patternFilter, bool checkActFailure = true)
{
AIVirtualField aIVirtualField = new AIVirtualField(originalField);
bool[] array = new bool[actionPermList.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = true;
}
AIVirtualActionInfo aIVirtualActionInfo = AISimulationUtility.CreateActionInfoOnFieldFromSituation(aIVirtualField, additionalOptions?.ForceEvoAction);
List<AIVirtualActionInfo> actionInfoSequence = AISimulationUtility.GetActionInfoSequence(aIVirtualField, actionPermList, array, (aIVirtualActionInfo != null) ? (-1) : evoIndex);
if (aIVirtualActionInfo != null && !actionInfoSequence.Any((AIVirtualActionInfo info) => info.ActionType == AIOperationType.EVOLVE))
{
bool flag = false;
for (int num = 0; num < actionInfoSequence.Count; num++)
{
if (actionInfoSequence[num].Actor.IsSameCard(aIVirtualActionInfo.Actor))
{
actionInfoSequence.Insert(num, aIVirtualActionInfo);
flag = true;
break;
}
}
if (!flag)
{
actionInfoSequence.Add(aIVirtualActionInfo);
}
}
List<AIVirtualCard> enemyTargetSequence = AISimulationUtility.GetEnemyTargetSequence(aIVirtualField, enemyTargets);
SimulationSetting simSetting = new SimulationSetting(isHandRemovalValid: true, useLeaderAttackPreCheck: true, aIVirtualField.IsNoSkipAttackInPlayPtn(), checkActFailure);
ExecuteSimulationWithActionSequence(aIVirtualField, actionInfoSequence, enemyTargetSequence, simSetting, bestRecord, patternFilter);
}
public void RunPlaySkipWithActionSequence(AIVirtualField originalField, List<AIVirtualActionInfo> actionSequence, List<AIVirtualCard> enemyTargets, SimulationResult bestRecord, SimulationAdditionalActionInfoSet additionalOptions)
{
}
private void ExecuteSimulationWithActionSequence(AIVirtualField fieldTemp, List<AIVirtualActionInfo> actionInfoSequence, List<AIVirtualCard> enemyTargetSequence, SimulationSetting simSetting, SimulationResult bestRecord, InplayMovePatternFilter patternFilter)
{
BattleSequencer.ExecSimulation(fieldTemp, actionInfoSequence, enemyTargetSequence, simSetting);
if (NeedsChangeToTimeOverLogic())
{
return;
}
AIVirtualTurnEndInfo aIVirtualTurnEndInfo = new AIVirtualTurnEndInfo(fieldTemp.AllyClass);
actionInfoSequence.Add(aIVirtualTurnEndInfo);
BattleSequencer.OnAfterExecuteAttackCommon(fieldTemp, aIVirtualTurnEndInfo, ref actionInfoSequence, isAttackToLeaderAgain: true);
if (NeedsChangeToTimeOverLogic())
{
return;
}
float num = AISimulationUtility.EvaluateField(fieldTemp, EvaluationType.SELF_TURN);
if (NeedsChangeToTimeOverLogic())
{
return;
}
float num2 = num;
if (_bestPlayPtnWithToken == null)
{
num2 = num - (fieldTemp.EnemyClass.IsDead ? 0f : fieldTemp.EvaluateThreaten());
}
if (AISimulationUtility.IsBestRecord(fieldTemp, num2, num, bestRecord))
{
bestRecord.BestResultField = fieldTemp;
bestRecord.MaxFieldValue = num2;
bestRecord.ActionSequence = actionInfoSequence;
bestRecord.MaxFieldValueAtSelfTurnEnd = num;
if (fieldTemp.EnemyClass.IsDead)
{
bestRecord.MinActionLengthOfLethal = fieldTemp.ActionLength;
}
patternFilter?.ConfirmBestPattern(enemyTargetSequence);
}
}
private bool NeedsChangeToTimeOverLogic()
{
if (_ai.IsRunWeakLogic)
{
return !_canChangeToTimeOverLogic;
}
return false;
}
}