PkmnLib.NET/PkmnLib.Dynamic/AI/PokemonAI.cs

94 lines
4.0 KiB
C#
Raw Normal View History

2024-10-01 09:00:01 +00:00
using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.Models.Choices;
using PkmnLib.Static.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.AI;
/// <summary>
/// The base class for implementing an AI for Pokémon.
/// </summary>
public abstract class PokemonAI
{
/// <summary>
/// The name of the AI.
/// </summary>
public StringKey Name { get; set; }
/// <inheritdoc cref="PokemonAI" />
protected PokemonAI(StringKey name)
{
Name = name;
}
/// <summary>
/// Gets the choice for the Pokémon.
/// </summary>
public abstract ITurnChoice GetChoice(IBattle battle, IPokemon pokemon);
public IEnumerable<(byte side, byte position)> GetValidTargetsForMove(IPokemon user, ILearnedMove move)
{
byte GetOppositeSide(byte side) => side == 0 ? (byte)1 : (byte)0;
var userBattleData = user.BattleData!;
switch (move.MoveData.Target)
{
case MoveTarget.Adjacent:
yield return (GetOppositeSide(userBattleData.SideIndex), userBattleData.Position);
break;
case MoveTarget.AdjacentAlly:
if (userBattleData.Position > 0)
yield return (userBattleData.SideIndex, (byte)(userBattleData.Position - 1));
if (userBattleData.Battle.PositionsPerSide > userBattleData.Position + 1)
yield return (userBattleData.SideIndex, (byte)(userBattleData.Position + 1));
break;
case MoveTarget.AdjacentAllySelf:
if (userBattleData.Position > 0)
yield return (userBattleData.SideIndex, (byte)(userBattleData.Position - 1));
if (userBattleData.Battle.PositionsPerSide > userBattleData.Position + 1)
yield return (userBattleData.SideIndex, (byte)(userBattleData.Position + 1));
yield return (userBattleData.SideIndex, userBattleData.Position);
break;
case MoveTarget.AdjacentOpponent:
yield return (GetOppositeSide(userBattleData.SideIndex), userBattleData.Position);
if (userBattleData.Position > 0)
yield return (GetOppositeSide(userBattleData.SideIndex), (byte)(userBattleData.Position - 1));
if (userBattleData.Battle.PositionsPerSide > userBattleData.Position + 1)
yield return (GetOppositeSide(userBattleData.SideIndex), (byte)(userBattleData.Position + 1));
break;
case MoveTarget.All:
yield return (userBattleData.SideIndex, userBattleData.Position);
break;
case MoveTarget.AllAdjacent:
yield return (userBattleData.SideIndex, userBattleData.Position);
break;
case MoveTarget.AllAdjacentOpponent:
yield return (GetOppositeSide(userBattleData.SideIndex), userBattleData.Position);
break;
case MoveTarget.AllAlly:
yield return (userBattleData.SideIndex, userBattleData.Position);
break;
case MoveTarget.AllOpponent:
yield return (GetOppositeSide(userBattleData.SideIndex), userBattleData.Position);
break;
case MoveTarget.Any:
foreach (var side in userBattleData.Battle.Sides)
{
foreach (var pokemon in side.Pokemon)
{
if (pokemon?.BattleData == null)
continue;
yield return (side.Index, pokemon.BattleData!.Position);
}
}
break;
case MoveTarget.RandomOpponent:
yield return (GetOppositeSide(userBattleData.SideIndex), userBattleData.Position);
break;
case MoveTarget.SelfUse:
yield return (userBattleData.SideIndex, userBattleData.Position);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}