using PkmnLib.Static.Moves; namespace PkmnLib.Dynamic.Models.BattleFlow; /// /// Helper class for resolving the targets of a move. /// public static class TargetResolver { /// /// Get the targets of a move based on the target type, and the selected side and position to target. /// public static IReadOnlyList ResolveTargets(IBattle battle, byte side, byte position, MoveTarget target) { return target switch { MoveTarget.Adjacent or MoveTarget.AdjacentAlly or MoveTarget.AdjacentAllySelf or MoveTarget.AdjacentOpponent or MoveTarget.Any or MoveTarget.RandomOpponent or MoveTarget.SelfUse => [battle.GetPokemon(side, position)], MoveTarget.All => GetAllTargets(battle), MoveTarget.AllAdjacentOpponent => GetAllAdjacentAndOpponent(battle, side, position), MoveTarget.AllAdjacent => GetAllAdjacent(battle, side, position), MoveTarget.AllAlly => battle.Sides[side].Pokemon.ToList(), MoveTarget.AllOpponent => battle.Sides[GetOppositeSide(side)].Pokemon.ToList(), _ => throw new ArgumentOutOfRangeException(nameof(target), target, null), }; } /// /// Validates whether a given target is valid for a move choice. Returns true if the target is valid. /// public static bool IsValidTarget(byte side, byte position, MoveTarget target, IPokemon user) { var userBattleData = user.BattleData; if (userBattleData == null) throw new ArgumentNullException(nameof(user.BattleData)); var userSide = userBattleData.SideIndex; var userPosition = userBattleData.Position; switch (target) { case MoveTarget.Adjacent: case MoveTarget.AllAdjacent: { var diff = Math.Abs(position - userPosition); if (diff == 0) return userSide == side; return diff <= 1; } case MoveTarget.AdjacentAlly: { if (userSide != side) return false; return Math.Abs(position - userPosition) == 1; } case MoveTarget.AdjacentAllySelf: { if (userSide != side) return false; return Math.Abs(position - userPosition) <= 1; } case MoveTarget.AdjacentOpponent: case MoveTarget.AllAdjacentOpponent: { if (userSide == side) return false; return Math.Abs(position - userPosition) <= 1; } case MoveTarget.All: case MoveTarget.Any: case MoveTarget.RandomOpponent: return true; case MoveTarget.AllAlly: return userSide == side; case MoveTarget.AllOpponent: return userSide != side; case MoveTarget.SelfUse: return userSide == side && userPosition == position; } throw new ArgumentOutOfRangeException(nameof(target), target, null); } private static IReadOnlyList GetAllTargets(IBattle battle) => battle.Sides.SelectMany(x => x.Pokemon).ToList(); private static byte GetOppositeSide(byte side) => side == 0 ? (byte)1 : (byte)0; /// /// Gets all Pokémon that are adjacent to of directly opposite of a Pokémon. This means the target, /// the Pokémon left of it, the Pokémon right of it, and the Pokémon opposite of it. /// private static IReadOnlyList GetAllAdjacentAndOpponent(IBattle battle, byte side, byte position) { var left = position - 1; var right = position + 1; if (left < 0 && right >= battle.PositionsPerSide) { return [battle.GetPokemon(side, position), battle.GetPokemon(GetOppositeSide(side), position)]; } if (left < 0) { return [ battle.GetPokemon(side, position), battle.GetPokemon(GetOppositeSide(side), position), battle.GetPokemon(side, (byte)right), ]; } if (right >= battle.PositionsPerSide) { return [ battle.GetPokemon(side, position), battle.GetPokemon(GetOppositeSide(side), position), battle.GetPokemon(side, (byte)left), ]; } return [ battle.GetPokemon(side, position), battle.GetPokemon(GetOppositeSide(side), position), battle.GetPokemon(side, (byte)left), battle.GetPokemon(side, (byte)right), ]; } private static IReadOnlyList GetAllAdjacent(IBattle battle, byte side, byte position) { var left = position - 1; var right = position + 1; if (left < 0 && right >= battle.PositionsPerSide) { return [battle.GetPokemon(side, position)]; } if (left < 0) { return [battle.GetPokemon(side, position), battle.GetPokemon(side, (byte)right)]; } if (right >= battle.PositionsPerSide) { return [battle.GetPokemon(side, position), battle.GetPokemon(side, (byte)left)]; } return [ battle.GetPokemon(side, position), battle.GetPokemon(side, (byte)left), battle.GetPokemon(side, (byte)right), ]; } }