using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.Models.Choices;
using PkmnLib.Static;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.AI;
///
/// HighestDamageAI is an AI that selects the move that it expects to deal the highest damage.
///
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();
return move != null
? new MoveChoice(pokemon, move, opponentSide, 0)
: 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).FirstOrDefault();
if (movesWithDamage is null)
{
return battle.Library.MiscLibrary.ReplacementChoice(pokemon, opponentSide, 0);
}
var bestMove = movesWithDamage.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;
}
}