Adds some doc comments

This commit is contained in:
2026-07-05 14:04:01 +02:00
parent a649e58826
commit 1ab15110f5
5 changed files with 89 additions and 4 deletions

View File

@@ -6,8 +6,14 @@ using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.AI; namespace PkmnLib.Dynamic.AI;
/// <summary>
/// Helper functions for AI
/// </summary>
public static class AIHelpers public static class AIHelpers
{ {
/// <summary>
/// Estimates the amount of damage that will be done by a move against a target.
/// </summary>
public static uint CalculateDamageEstimation(IMoveData move, IPokemon user, IPokemon target, public static uint CalculateDamageEstimation(IMoveData move, IPokemon user, IPokemon target,
IDynamicLibrary library) IDynamicLibrary library)
{ {

View File

@@ -1,8 +1,18 @@
namespace PkmnLib.Dynamic.AI; namespace PkmnLib.Dynamic.AI;
/// <summary>
/// Logging implementation for AI
/// </summary>
public static class AILogging public static class AILogging
{ {
/// <summary>
/// The actual function called by the logging.
/// </summary>
public static Action<string> LogHandler { get; set; } = _ => { }; public static Action<string> LogHandler { get; set; } = _ => { };
/// <summary>
/// Forwarding function.
/// </summary>
/// <param name="message"></param>
public static void LogInformation(string message) => LogHandler(message); public static void LogInformation(string message) => LogHandler(message);
} }

View File

@@ -3,14 +3,25 @@ using PkmnLib.Static.Moves;
namespace PkmnLib.Dynamic.AI.Explicit; namespace PkmnLib.Dynamic.AI.Explicit;
/// <summary>
/// Container wrapper for a move and its user.
/// </summary>
public class AIMoveState public class AIMoveState
{ {
/// <inheritdoc cref="AIMoveState" />
public AIMoveState(IPokemon user, IMoveData move) public AIMoveState(IPokemon user, IMoveData move)
{ {
User = user; User = user;
Move = move; Move = move;
} }
/// <summary>
/// The user that's being wrapper
/// </summary>
public IPokemon User { get; } public IPokemon User { get; }
/// <summary>
/// The move that's being wrapper
/// </summary>
public IMoveData Move { get; } public IMoveData Move { get; }
} }

View File

@@ -45,8 +45,7 @@ public partial class ExplicitAI
return false; return false;
} }
var battleSide = pokemon.BattleData!.BattleSide; var battleSide = pokemon.BattleData!.BattleSide;
var bestReplacement = var bestReplacement = ChooseBestReplacementPokemon(terribleMoves, usablePokemon, battleSide);
ChooseBestReplacementPokemon(pokemon.BattleData!.Position, terribleMoves, usablePokemon, battleSide);
if (bestReplacement is null) if (bestReplacement is null)
{ {
AILogging.LogInformation( AILogging.LogInformation(
@@ -57,8 +56,8 @@ public partial class ExplicitAI
return true; return true;
} }
private IPokemon? ChooseBestReplacementPokemon(byte position, bool terribleMoves, private IPokemon? ChooseBestReplacementPokemon(bool terribleMoves, IReadOnlyList<IPokemon> usablePokemon,
IReadOnlyList<IPokemon> usablePokemon, IBattleSide battleSide) IBattleSide battleSide)
{ {
var options = usablePokemon.Where((_, index) => var options = usablePokemon.Where((_, index) =>
{ {

View File

@@ -3,17 +3,35 @@ using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.AI.Explicit; namespace PkmnLib.Dynamic.AI.Explicit;
/// <summary>
/// An option where a move is used against a target
/// </summary>
public record struct MoveOption(AIMoveState Move, IBattle Battle, IPokemon? Target, uint EstimatedDamage = 0); public record struct MoveOption(AIMoveState Move, IBattle Battle, IPokemon? Target, uint EstimatedDamage = 0);
/// <summary>
/// A function that takes an explicit AI and a move option and returns a boolean value.
/// </summary>
public delegate bool AIBoolHandler(IExplicitAI ai, MoveOption option); public delegate bool AIBoolHandler(IExplicitAI ai, MoveOption option);
/// <summary>
/// A function for returning whether a Pokemon should switch.
/// </summary>
public delegate bool AISwitchBoolHandler(IExplicitAI ai, IPokemon pokemon, IBattle battle, public delegate bool AISwitchBoolHandler(IExplicitAI ai, IPokemon pokemon, IBattle battle,
IReadOnlyList<IPokemon> reserves); IReadOnlyList<IPokemon> reserves);
/// <summary>
/// A function for returning the base power of a move.
/// </summary>
public delegate void AIMoveBasePowerHandler(IExplicitAI ai, MoveOption option, ref int score); public delegate void AIMoveBasePowerHandler(IExplicitAI ai, MoveOption option, ref int score);
/// <summary>
/// A function for returning a score
/// </summary>
public delegate void AIScoreMoveHandler(IExplicitAI ai, MoveOption option, ref int score); public delegate void AIScoreMoveHandler(IExplicitAI ai, MoveOption option, ref int score);
/// <summary>
/// Explicit AI Handlers are a library that allow plugins to explicitly indicate AI preferences.
/// </summary>
public interface IReadOnlyExplicitAIHandlers public interface IReadOnlyExplicitAIHandlers
{ {
/// <summary> /// <summary>
@@ -86,28 +104,50 @@ public interface IReadOnlyExplicitAIHandlers
/// </summary> /// </summary>
void ApplyGenerateMoveAgainstTargetScoreModifiers(IExplicitAI ai, MoveOption option, ref int score); void ApplyGenerateMoveAgainstTargetScoreModifiers(IExplicitAI ai, MoveOption option, ref int score);
/// <summary>
/// Functions that indicate whether a Pokemon should switch
/// </summary>
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> ShouldSwitchFunctions { get; } IReadOnlyDictionary<StringKey, AISwitchBoolHandler> ShouldSwitchFunctions { get; }
/// <summary>
/// Indicates whether a Pokemon should switch into another Pokemon
/// </summary>
bool ShouldSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves); bool ShouldSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves);
/// <summary>
/// Functions that indicate whether a Pokemon should NOT switch
/// </summary>
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> ShouldNotSwitchFunctions { get; } IReadOnlyDictionary<StringKey, AISwitchBoolHandler> ShouldNotSwitchFunctions { get; }
/// <summary>
/// Indicates whether a Pokemon should NOT switch into another Pokemon
/// </summary>
bool ShouldNotSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves); bool ShouldNotSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves);
/// <summary>
/// Scores abilities
/// </summary>
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> AbilityRanking { get; } IReadOnlyDictionary<StringKey, AIScoreMoveHandler> AbilityRanking { get; }
} }
/// <inheritdoc />
public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
{ {
/// <inheritdoc /> /// <inheritdoc />
IReadOnlyDictionary<StringKey, AIBoolHandler> IReadOnlyExplicitAIHandlers.MoveFailureCheck => MoveFailureCheck; IReadOnlyDictionary<StringKey, AIBoolHandler> IReadOnlyExplicitAIHandlers.MoveFailureCheck => MoveFailureCheck;
/// <summary>
/// Checks whether a move will fail
/// </summary>
public FunctionHandlerDictionary<AIBoolHandler> MoveFailureCheck { get; } = new(); public FunctionHandlerDictionary<AIBoolHandler> MoveFailureCheck { get; } = new();
/// <inheritdoc /> /// <inheritdoc />
public bool MoveWillFail(IExplicitAI ai, StringKey functionCode, MoveOption option) => public bool MoveWillFail(IExplicitAI ai, StringKey functionCode, MoveOption option) =>
MoveFailureCheck.TryGetValue(functionCode, out var handler) && handler(ai, option); MoveFailureCheck.TryGetValue(functionCode, out var handler) && handler(ai, option);
/// <summary>
/// Checks whether a move will fail against a target
/// </summary>
public FunctionHandlerDictionary<AIBoolHandler> MoveFailureAgainstTargetCheck { get; } = new(); public FunctionHandlerDictionary<AIBoolHandler> MoveFailureAgainstTargetCheck { get; } = new();
/// <inheritdoc /> /// <inheritdoc />
@@ -118,12 +158,18 @@ public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
public bool MoveWillFailAgainstTarget(IExplicitAI ai, StringKey functionCode, MoveOption option) => public bool MoveWillFailAgainstTarget(IExplicitAI ai, StringKey functionCode, MoveOption option) =>
MoveFailureAgainstTargetCheck.TryGetValue(functionCode, out var handler) && handler(ai, option); MoveFailureAgainstTargetCheck.TryGetValue(functionCode, out var handler) && handler(ai, option);
/// <summary>
/// Functions to score a move
/// </summary>
public FunctionHandlerDictionary<AIScoreMoveHandler> MoveEffectScore { get; } = []; public FunctionHandlerDictionary<AIScoreMoveHandler> MoveEffectScore { get; } = [];
/// <inheritdoc /> /// <inheritdoc />
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.MoveEffectScore => IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.MoveEffectScore =>
MoveEffectScore; MoveEffectScore;
/// <summary>
/// Functions to score a move against a target
/// </summary>
public FunctionHandlerDictionary<AIScoreMoveHandler> MoveEffectAgainstTargetScore = []; public FunctionHandlerDictionary<AIScoreMoveHandler> MoveEffectAgainstTargetScore = [];
/// <inheritdoc /> /// <inheritdoc />
@@ -137,6 +183,9 @@ public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.MoveEffectAgainstTargetScore => IReadOnlyDictionary<StringKey, AIScoreMoveHandler> IReadOnlyExplicitAIHandlers.MoveEffectAgainstTargetScore =>
MoveEffectAgainstTargetScore; MoveEffectAgainstTargetScore;
/// <summary>
/// Functions that indicate a moves base power
/// </summary>
public FunctionHandlerDictionary<AIMoveBasePowerHandler> MoveBasePower = []; public FunctionHandlerDictionary<AIMoveBasePowerHandler> MoveBasePower = [];
/// <inheritdoc /> /// <inheritdoc />
@@ -150,6 +199,9 @@ public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
IReadOnlyDictionary<StringKey, AIMoveBasePowerHandler> IReadOnlyExplicitAIHandlers.MoveBasePower => IReadOnlyDictionary<StringKey, AIMoveBasePowerHandler> IReadOnlyExplicitAIHandlers.MoveBasePower =>
MoveBasePower; MoveBasePower;
/// <summary>
/// Functions that indicate a moves score
/// </summary>
public FunctionHandlerDictionary<AIScoreMoveHandler> GeneralMoveScore = []; public FunctionHandlerDictionary<AIScoreMoveHandler> GeneralMoveScore = [];
/// <inheritdoc /> /// <inheritdoc />
@@ -193,6 +245,7 @@ public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> IReadOnlyExplicitAIHandlers.ShouldSwitchFunctions => IReadOnlyDictionary<StringKey, AISwitchBoolHandler> IReadOnlyExplicitAIHandlers.ShouldSwitchFunctions =>
ShouldSwitchFunctions; ShouldSwitchFunctions;
/// <inheritdoc />
public bool ShouldSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves) public bool ShouldSwitch(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves)
{ {
var shouldSwitch = false; var shouldSwitch = false;
@@ -203,6 +256,9 @@ public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
return shouldSwitch; return shouldSwitch;
} }
/// <summary>
/// Functions that indicate whether we should not switch
/// </summary>
public FunctionHandlerDictionary<AISwitchBoolHandler> ShouldNotSwitchFunctions = []; public FunctionHandlerDictionary<AISwitchBoolHandler> ShouldNotSwitchFunctions = [];
/// <inheritdoc /> /// <inheritdoc />
@@ -210,6 +266,9 @@ public class ExplicitAIHandlers : IReadOnlyExplicitAIHandlers
IReadOnlyDictionary<StringKey, AISwitchBoolHandler> IReadOnlyExplicitAIHandlers.ShouldNotSwitchFunctions => IReadOnlyDictionary<StringKey, AISwitchBoolHandler> IReadOnlyExplicitAIHandlers.ShouldNotSwitchFunctions =>
ShouldNotSwitchFunctions; ShouldNotSwitchFunctions;
/// <summary>
/// Functions to rank an ability
/// </summary>
public FunctionHandlerDictionary<AIScoreMoveHandler> AbilityRanking = []; public FunctionHandlerDictionary<AIScoreMoveHandler> AbilityRanking = [];
/// <inheritdoc /> /// <inheritdoc />