using PkmnLib.Dynamic.Models; using PkmnLib.Dynamic.Models.Choices; using PkmnLib.Static; using PkmnLib.Static.Utils; namespace PkmnLib.Dynamic.AI; public class HighestDamageAI : PokemonAI { /// public HighestDamageAI() : base("highest_damage") { } /// public override ITurnChoice GetChoice(IBattle battle, IPokemon pokemon) { var opponentSide = pokemon.BattleData!.SideIndex == 0 ? (byte)1 : (byte)0; var opponent = battle.Sides[opponentSide].Pokemon.WhereNotNull().FirstOrDefault(x => x.IsUsable); var moves = pokemon.Moves.WhereNotNull().Where(x => battle.CanUse(new MoveChoice(pokemon, x, opponentSide, 0))) .ToList(); if (opponent == null) { var move = moves.FirstOrDefault(); if (move != null) { return new MoveChoice(pokemon, move, opponentSide, 0); } return battle.Library.MiscLibrary.ReplacementChoice(pokemon, opponentSide, 0); } var movesWithDamage = moves.Select(move => { var hitData = new CustomHitData { BasePower = move.MoveData.BasePower, Effectiveness = battle.Library.StaticLibrary.Types.GetEffectiveness(move.MoveData.MoveType, opponent.Types), Type = move.MoveData.MoveType, }; return new { Move = move, Damage = battle.Library.DamageCalculator.GetDamage(null, move.MoveData.Category, pokemon, opponent, 1, 0, hitData), }; }).OrderByDescending(x => x.Damage).ToList(); if (movesWithDamage.Count == 0) { return battle.Library.MiscLibrary.ReplacementChoice(pokemon, opponentSide, 0); } var bestMove = movesWithDamage.First().Move; return new MoveChoice(pokemon, bestMove, opponentSide, 0); } private class CustomHitData : IHitData { /// public bool IsCritical => false; /// public ushort BasePower { get; init; } /// public float Effectiveness { get; init; } /// public uint Damage => 0; /// public TypeIdentifier? Type { get; init; } /// public bool IsContact => false; /// public bool HasFailed => false; /// public void Fail() { } /// public void SetFlag(StringKey flag) { } /// public bool HasFlag(StringKey flag) => false; } }