PkmnLib.NET/PkmnLib.Dynamic/AI/Explicit/ExplicitAIHandlers.cs
Deukhoofd bf83b25238
All checks were successful
Build / Build (push) Successful in 58s
Implements AI Switching
2025-07-12 13:03:00 +02:00

229 lines
8.9 KiB
C#

using PkmnLib.Dynamic.Models;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.AI.Explicit;
public record struct MoveOption(AIMoveState Move, IBattle Battle, IPokemon? Target, uint EstimatedDamage = 0);
public delegate bool AIBoolHandler(IExplicitAI ai, MoveOption option);
public delegate bool AISwitchBoolHandler(IExplicitAI ai, IPokemon pokemon, IBattle battle,
IReadOnlyList<IPokemon> reserves);
public delegate void AIMoveBasePowerHandler(IExplicitAI ai, MoveOption option, ref int score);
public delegate void AIScoreMoveHandler(IExplicitAI ai, MoveOption option, ref int score);
public interface IReadOnlyExplicitAIHandlers
{
/// <summary>
/// A list of checks to determine if a move will fail.
/// </summary>
IReadOnlyDictionary<StringKey, AIBoolHandler> MoveFailureCheck { get; }
/// <summary>
/// Checks if a move will fail based on the provided function code and options.
/// </summary>
bool MoveWillFail(IExplicitAI ai, StringKey functionCode, MoveOption option);
/// <summary>
/// A list of checks to determine if a move will fail against a target.
/// </summary>
IReadOnlyDictionary<StringKey, AIBoolHandler> MoveFailureAgainstTargetCheck { get; }
/// <summary>
/// Checks if a move will fail against a target based on the provided function code and options.
/// </summary>
bool MoveWillFailAgainstTarget(IExplicitAI ai, StringKey functionCode, MoveOption option);
/// <summary>
/// A list of handlers to apply scores for move effects.
/// </summary>
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> MoveEffectScore { get; }
/// <summary>
/// Applies the score for a move effect based on the provided name and options.
/// </summary>
void ApplyMoveEffectScore(IExplicitAI ai, StringKey name, MoveOption option, ref int score);
/// <summary>
/// A list of handlers to apply scores for move effects against a target.
/// </summary>
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> MoveEffectAgainstTargetScore { get; }
/// <summary>
/// Applies the score for a move effect against a target based on the provided name and options.
/// </summary>
void ApplyMoveEffectAgainstTargetScore(IExplicitAI ai, StringKey name, MoveOption option, ref int score);
/// <summary>
/// A list of handlers to determine the base power of a move.
/// </summary>
IReadOnlyDictionary<StringKey, AIMoveBasePowerHandler> MoveBasePower { get; }
/// <summary>
/// Applies the base power for a move based on the provided name and options.
/// </summary>
void GetBasePower(IExplicitAI ai, StringKey name, MoveOption option, ref int power);
/// <summary>
/// A list of handlers to apply scores for general move effectiveness.
/// </summary>
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> GeneralMoveScore { get; }
/// <summary>
/// Applies the score for a general move based on the provided option.
/// </summary>
void ApplyGenerateMoveScoreModifiers(IExplicitAI ai, MoveOption option, ref int score);
/// <summary>
/// A list of handlers to apply scores for general move effectiveness against a target.
/// </summary>
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> GeneralMoveAgainstTargetScore { get; }
/// <summary>
/// Applies the score for a general move against a target based on the provided option.
/// </summary>
void ApplyGenerateMoveAgainstTargetScoreModifiers(IExplicitAI ai, MoveOption option, ref int score);
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> ShouldSwitchFunctions { get; }
bool ShouldSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves);
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> ShouldNotSwitchFunctions { get; }
bool ShouldNotSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves);
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> AbilityRanking { get; }
}
public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
{
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIBoolHandler> IReadOnlyExplicitAIHandlers.MoveFailureCheck => MoveFailureCheck;
public FunctionHandlerDictionary<AIBoolHandler> MoveFailureCheck { get; } = new();
/// <inheritdoc />
public bool MoveWillFail(IExplicitAI ai, StringKey functionCode, MoveOption option) =>
MoveFailureCheck.TryGetValue(functionCode, out var handler) && handler(ai, option);
public FunctionHandlerDictionary<AIBoolHandler> MoveFailureAgainstTargetCheck { get; } = new();
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIBoolHandler> IReadOnlyExplicitAIHandlers.MoveFailureAgainstTargetCheck =>
MoveFailureAgainstTargetCheck;
/// <inheritdoc />
public bool MoveWillFailAgainstTarget(IExplicitAI ai, StringKey functionCode, MoveOption option) =>
MoveFailureAgainstTargetCheck.TryGetValue(functionCode, out var handler) && handler(ai, option);
public FunctionHandlerDictionary<AIScoreMoveHandler> MoveEffectScore { get; } = [];
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.MoveEffectScore =>
MoveEffectScore;
public FunctionHandlerDictionary<AIScoreMoveHandler> MoveEffectAgainstTargetScore = [];
/// <inheritdoc />
public void ApplyMoveEffectScore(IExplicitAI ai, StringKey name, MoveOption option, ref int score)
{
if (MoveEffectScore.TryGetValue(name, out var handler))
handler(ai, option, ref score);
}
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.MoveEffectAgainstTargetScore =>
MoveEffectAgainstTargetScore;
public FunctionHandlerDictionary<AIMoveBasePowerHandler> MoveBasePower = [];
/// <inheritdoc />
public void ApplyMoveEffectAgainstTargetScore(IExplicitAI ai, StringKey name, MoveOption option, ref int score)
{
if (MoveEffectAgainstTargetScore.TryGetValue(name, out var handler))
handler(ai, option, ref score);
}
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIMoveBasePowerHandler> IReadOnlyExplicitAIHandlers.MoveBasePower =>
MoveBasePower;
public FunctionHandlerDictionary<AIScoreMoveHandler> GeneralMoveScore = [];
/// <inheritdoc />
public void GetBasePower(IExplicitAI ai, StringKey name, MoveOption option, ref int power)
{
if (MoveBasePower.TryGetValue(name, out var handler))
handler(ai, option, ref power);
}
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.GeneralMoveScore =>
GeneralMoveScore;
public FunctionHandlerDictionary<AIScoreMoveHandler> GeneralMoveAgainstTargetScore = [];
/// <inheritdoc />
public void ApplyGenerateMoveScoreModifiers(IExplicitAI ai, MoveOption option, ref int score)
{
foreach (var (_, handler) in GeneralMoveScore)
{
handler(ai, option, ref score);
}
}
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.GeneralMoveAgainstTargetScore =>
GeneralMoveAgainstTargetScore;
/// <inheritdoc />
public void ApplyGenerateMoveAgainstTargetScoreModifiers(IExplicitAI ai, MoveOption option, ref int score)
{
foreach (var (_, handler) in GeneralMoveAgainstTargetScore)
{
handler(ai, option, ref score);
}
}
public FunctionHandlerDictionary<AISwitchBoolHandler> ShouldSwitchFunctions = [];
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> IReadOnlyExplicitAIHandlers.ShouldSwitchFunctions =>
ShouldSwitchFunctions;
public bool ShouldSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves)
{
var shouldSwitch = false;
foreach (var (_, handler) in ShouldSwitchFunctions)
{
shouldSwitch |= handler(ai, pokemon, battle, reserves);
}
return shouldSwitch;
}
public FunctionHandlerDictionary<AISwitchBoolHandler> ShouldNotSwitchFunctions = [];
/// <inheritdoc />
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> IReadOnlyExplicitAIHandlers.ShouldNotSwitchFunctions =>
ShouldNotSwitchFunctions;
public FunctionHandlerDictionary<AIScoreMoveHandler> AbilityRanking = [];
/// <inheritdoc />
public bool ShouldNotSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves)
{
var shouldNotSwitch = false;
foreach (var (_, handler) in ShouldNotSwitchFunctions)
{
shouldNotSwitch |= handler(ai, pokemon, battle, reserves);
}
return shouldNotSwitch;
}
/// <inheritdoc />
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.AbilityRanking =>
AbilityRanking;
}