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.
This commit is contained in:
417
SVSim.BattleEngine/Engine/Wizard/AIEmoteMng.cs
Normal file
417
SVSim.BattleEngine/Engine/Wizard/AIEmoteMng.cs
Normal file
@@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteMng
|
||||
{
|
||||
private EnemyAI AI;
|
||||
|
||||
private float _allyAdvOnTurnStart;
|
||||
|
||||
private float _opponentAdvOnTurnStart;
|
||||
|
||||
private int _allyLegionNumOnTurnStart;
|
||||
|
||||
private float _allyAdvOnFirstAttack;
|
||||
|
||||
private float _advOnBeforeSetCard;
|
||||
|
||||
private int _opponentLifeOnBeforeSetCard;
|
||||
|
||||
private int _opponentLifeOnBeforeAttack;
|
||||
|
||||
private bool _isLastOpr_CardPlay;
|
||||
|
||||
private float _playedCardValue;
|
||||
|
||||
private float _allyAdvOnCardPlay;
|
||||
|
||||
private bool _isFirstAttacked;
|
||||
|
||||
private bool _isOpponentTurnEmoteOccured;
|
||||
|
||||
private bool _isAIGreeted;
|
||||
|
||||
private bool _isAIThanked;
|
||||
|
||||
private readonly Stopwatch _stopwatch;
|
||||
|
||||
private bool _isThinkingEmoteOccured;
|
||||
|
||||
public Dictionary<int, int> EmoteCategoryPlayedCounter { get; private set; }
|
||||
|
||||
public bool IsOpponentTurnEmoteOccured => _isOpponentTurnEmoteOccured;
|
||||
|
||||
public Stopwatch Stopwatch => _stopwatch;
|
||||
|
||||
public int EmoteRandomSeed { get; private set; }
|
||||
|
||||
public AIEmoteMng(EnemyAI ai)
|
||||
{
|
||||
AI = ai;
|
||||
EmoteRandomSeed = new Random().Next();
|
||||
_stopwatch = new Stopwatch();
|
||||
_isAIGreeted = false;
|
||||
_isAIThanked = false;
|
||||
EmoteCategoryPlayedCounter = new Dictionary<int, int>();
|
||||
}
|
||||
|
||||
public float EvalDisplacement_PlayedValue()
|
||||
{
|
||||
if (!_isLastOpr_CardPlay)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() - (_allyAdvOnCardPlay + _playedCardValue);
|
||||
}
|
||||
|
||||
public void ResetLastOpr()
|
||||
{
|
||||
_isLastOpr_CardPlay = false;
|
||||
}
|
||||
|
||||
public void SetUpOnAllyTurnStart()
|
||||
{
|
||||
_isFirstAttacked = false;
|
||||
ResetLastOpr();
|
||||
AI.EmoteQuery.UpdateCategoryInterval();
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
_isThinkingEmoteOccured = false;
|
||||
}
|
||||
|
||||
public void EvalFieldOnTurnStart()
|
||||
{
|
||||
_allyAdvOnTurnStart = AI.CalcFieldAdvantage();
|
||||
_allyLegionNumOnTurnStart = AI.ALLY.InPlayCards.Count((BattleCardBase c) => c.IsTribe(CardBasePrm.TribeType.LEGION));
|
||||
}
|
||||
|
||||
public void EvalFieldOnOpponentTurnStart()
|
||||
{
|
||||
_opponentAdvOnTurnStart = AI.CalcFieldAdvantage();
|
||||
}
|
||||
|
||||
public void EvalFieldOnAttack()
|
||||
{
|
||||
if (!_isFirstAttacked)
|
||||
{
|
||||
_allyAdvOnFirstAttack = AI.CalcFieldAdvantage();
|
||||
_isFirstAttacked = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void EvalFieldOnBeforeSetCard()
|
||||
{
|
||||
_advOnBeforeSetCard = AI.CalcFieldAdvantage();
|
||||
_opponentLifeOnBeforeSetCard = AI.OPPONENT.Class.Life;
|
||||
}
|
||||
|
||||
public void EvalFieldOnBeforeAttack()
|
||||
{
|
||||
_opponentLifeOnBeforeAttack = AI.OPPONENT.Class.Life;
|
||||
}
|
||||
|
||||
public void EvalAllyOnCardPlay(AIVirtualCard playCard, AISinglePlayptnRecord playptnRecord)
|
||||
{
|
||||
if (playptnRecord != null && playptnRecord.PlayPtn != null && playptnRecord.PlayPtn.Count > 0)
|
||||
{
|
||||
_isLastOpr_CardPlay = true;
|
||||
_allyAdvOnCardPlay = AI.CalcFieldAdvantage();
|
||||
AIVirtualTargetSelectAction play = new AIVirtualTargetSelectAction(playCard, playCard, AIOperationType.PLAY);
|
||||
_playedCardValue = AI.EnemyAIPlay.EvaluateHandValue(playCard, playptnRecord.PlayPtn, play, isOnBattleSimulate: false, playptnRecord);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOpponentTurnEmote()
|
||||
{
|
||||
_isOpponentTurnEmoteOccured = true;
|
||||
}
|
||||
|
||||
public void ResetOpponentTurnEmoteFlag()
|
||||
{
|
||||
_isOpponentTurnEmoteOccured = false;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyCardDestroy()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsReverseDisAdv()
|
||||
{
|
||||
if (_allyAdvOnTurnStart >= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() >= 0f;
|
||||
}
|
||||
|
||||
public bool IsOpponentEarnGreatMerit()
|
||||
{
|
||||
float num = AI.CalcFieldAdvantage();
|
||||
int ppTotal = AI.OPPONENT.PpTotal;
|
||||
return _opponentAdvOnTurnStart - num > (float)ppTotal * 2f;
|
||||
}
|
||||
|
||||
public bool IsFailedReverseDisAdv()
|
||||
{
|
||||
if (_allyAdvOnTurnStart >= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() < 0f;
|
||||
}
|
||||
|
||||
public bool IsOpponentFailedReverseDisAdv()
|
||||
{
|
||||
if (_opponentAdvOnTurnStart <= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() > 0f;
|
||||
}
|
||||
|
||||
public bool IsRemainTooPP()
|
||||
{
|
||||
return AI.ALLY.Pp >= 2;
|
||||
}
|
||||
|
||||
public bool IsOpponentRemainTooPP()
|
||||
{
|
||||
return AI.OPPONENT.Pp > AI.OPPONENT.PpTotal / 2;
|
||||
}
|
||||
|
||||
public bool IsGiantPlayed()
|
||||
{
|
||||
float num = 10f;
|
||||
return AI.FieldInplayValueDifference >= num;
|
||||
}
|
||||
|
||||
public bool IsEnoughUnit()
|
||||
{
|
||||
return AI.ALLY.InPlayCards.Count() >= 3;
|
||||
}
|
||||
|
||||
public bool IsEnoughGrave()
|
||||
{
|
||||
return AI.ALLY.CemeteryList.Count >= 6;
|
||||
}
|
||||
|
||||
public bool IsCheckmated()
|
||||
{
|
||||
int num = 0;
|
||||
foreach (BattleCardBase inPlayCard in AI.OPPONENT.InPlayCards)
|
||||
{
|
||||
if (inPlayCard.IsUnit)
|
||||
{
|
||||
num += inPlayCard.Atk;
|
||||
}
|
||||
}
|
||||
if (AI.OPPONENT.IsEvolve && AI.OPPONENT.InPlayCards.Any((BattleCardBase card) => card.IsUnit && !card.IsEvolution))
|
||||
{
|
||||
num += AI.OPPONENT.InPlayCards.Max((BattleCardBase card) => (!card.IsEvolution) ? (card.BaseParameter.EvoAtk - card.BaseParameter.Atk) : 0);
|
||||
}
|
||||
int num2 = 0;
|
||||
List<AIVirtualCard> bothClassAndInplayCards = AI.CurrentVirtualField.CardListSet.BothClassAndInplayCards;
|
||||
for (int num3 = 0; num3 < bothClassAndInplayCards.Count; num3++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = bothClassAndInplayCards[num3];
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTag(AIPlayTagType.TurnEndDamage))
|
||||
{
|
||||
num2 += aIVirtualCard.TagCollectionContainer.TurnEndTags.GetTurnEndDamageToAllyLeader(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
return num + num2 >= AI.ALLY.Class.Life;
|
||||
}
|
||||
|
||||
public bool IsHuntDown()
|
||||
{
|
||||
if (AI.OPPONENT.InPlayCards.Any((BattleCardBase c) => c.SkillApplyInformation.IsGuard))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int num = 0;
|
||||
foreach (BattleCardBase inPlayCard in AI.ALLY.InPlayCards)
|
||||
{
|
||||
if (inPlayCard.IsUnit)
|
||||
{
|
||||
num += inPlayCard.Atk;
|
||||
}
|
||||
}
|
||||
if (AI.ALLY.CurrentEpCount > 0)
|
||||
{
|
||||
num += 2;
|
||||
}
|
||||
return num >= AI.OPPONENT.Class.Life;
|
||||
}
|
||||
|
||||
public bool IsEliminatedAllyLegion(AIVirtualCard destroyingCard)
|
||||
{
|
||||
if (_allyLegionNumOnTurnStart < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (AI.CurrentVirtualField.AllyInplayCards.Count((AIVirtualCard c) => c.IsTribe(CardBasePrm.TribeType.LEGION) && c.IsSameCard(destroyingCard)) > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsAwaking(int turnOffset)
|
||||
{
|
||||
if (AI.ALLY.Pp + turnOffset == 7)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsUnexpectedBattle()
|
||||
{
|
||||
if (!_isFirstAttacked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() < _allyAdvOnFirstAttack;
|
||||
}
|
||||
|
||||
public bool IsBanishOverExpected(BattleCardBase actCard, AIVirtualField fieldAfterPlayed)
|
||||
{
|
||||
if (!actCard.IsSpell)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float num = (float)actCard.Cost * 2f + 4f;
|
||||
float num2 = AI.ParamQuery.EvaluateBattlePlayerPair(AI.CurrentVirtualField);
|
||||
if (AI.ParamQuery.EvaluateBattlePlayerPair(fieldAfterPlayed) - num2 >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentBanishSplendid(AIVirtualCard actCard)
|
||||
{
|
||||
if (actCard.IsAlly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float num = (float)actCard.Cost * 2f + 4f;
|
||||
float num2 = AI.CalcFieldAdvantage();
|
||||
if (_advOnBeforeSetCard - num2 >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentBanishBad(AIVirtualCard actCard)
|
||||
{
|
||||
if (actCard.IsAlly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float num = actCard.Cost;
|
||||
float num2 = AI.CalcFieldAdvantage();
|
||||
if (_advOnBeforeSetCard - num2 < num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentHealClassLifeLargeOnCardPlay()
|
||||
{
|
||||
int num = 4;
|
||||
if (AI.OPPONENT.Class.Life - _opponentLifeOnBeforeSetCard >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentHealClassLifeLargeOnAttack()
|
||||
{
|
||||
int num = 4;
|
||||
if (AI.OPPONENT.Class.Life - _opponentLifeOnBeforeAttack >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsThinkingLong()
|
||||
{
|
||||
float num = 20000f;
|
||||
if (!_isThinkingEmoteOccured)
|
||||
{
|
||||
return (float)_stopwatch.ElapsedMilliseconds > num;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnThinkingEmote()
|
||||
{
|
||||
_isThinkingEmoteOccured = true;
|
||||
_stopwatch.Reset();
|
||||
}
|
||||
|
||||
public void OnOperationRequest()
|
||||
{
|
||||
if (!_isThinkingEmoteOccured)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReplyAllowed(ClassCharaPrm.EmotionType emoteType, ref ClassCharaPrm.EmotionType replyEmote)
|
||||
{
|
||||
switch (emoteType)
|
||||
{
|
||||
case ClassCharaPrm.EmotionType.GREET:
|
||||
if (_isAIGreeted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
replyEmote = ClassCharaPrm.EmotionType.GREET;
|
||||
_isAIGreeted = true;
|
||||
return true;
|
||||
case ClassCharaPrm.EmotionType.THANK:
|
||||
if (_isAIThanked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
replyEmote = ClassCharaPrm.EmotionType.THANK;
|
||||
_isAIThanked = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPlayedCountOnEmotePlaying(int category)
|
||||
{
|
||||
if (EmoteCategoryPlayedCounter.ContainsKey(category))
|
||||
{
|
||||
EmoteCategoryPlayedCounter[category]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmoteCategoryPlayedCounter.Add(category, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetEmotePlayCount(int category)
|
||||
{
|
||||
if (EmoteCategoryPlayedCounter.ContainsKey(category))
|
||||
{
|
||||
return EmoteCategoryPlayedCounter[category];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user