/// <summary>
        /// Determines whether chosen actions are valid.
        /// </summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>False if the team already chose actions or the actions are illegal, True otherwise.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool AreActionsValid(PBETeam team, IEnumerable <PBEAction> actions)
        {
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to validate actions.");
            }
            if (team.ActionsRequired.Count == 0 || actions.Count() != team.ActionsRequired.Count)
            {
                return(false);
            }
            var standBy = new List <PBEPokemon>();

            foreach (PBEAction action in actions)
            {
                PBEPokemon pkmn = team.TryGetPokemon(action.PokemonId);
                if (!team.ActionsRequired.Contains(pkmn))
                {
                    return(false);
                }
                switch (action.Decision)
                {
                case PBEDecision.Fight:
                {
                    if (Array.IndexOf(pkmn.GetUsableMoves(), action.FightMove) == -1 ||
                        (action.FightMove == pkmn.TempLockedMove && action.FightTargets != pkmn.TempLockedTargets) ||
                        !AreTargetsValid(pkmn, action.FightMove, action.FightTargets)
                        )
                    {
                        return(false);
                    }
                    break;
                }

                case PBEDecision.SwitchOut:
                {
                    if (!pkmn.CanSwitchOut())
                    {
                        return(false);
                    }
                    PBEPokemon switchPkmn = team.TryGetPokemon(action.SwitchPokemonId);
                    if (switchPkmn == null ||
                        switchPkmn.HP == 0 ||
                        switchPkmn.FieldPosition != PBEFieldPosition.None ||     // Also takes care of trying to switch into yourself
                        standBy.Contains(switchPkmn)
                        )
                    {
                        return(false);
                    }
                    else
                    {
                        standBy.Add(switchPkmn);
                    }
                    break;
                }
                }
            }
            return(true);
        }
예제 #2
0
 /// <summary>Selects switches if they are valid. Changes the battle state if both teams have selected valid switches.</summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>True if the switches are valid and were selected.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool SelectSwitchesIfValid(PBETeam team, IList <PBESwitchIn> switches)
 {
     if (AreSwitchesValid(team, switches))
     {
         lock (team.Battle._disposeLockObj)
         {
             if (!team.Battle.IsDisposed)
             {
                 team.SwitchInsRequired = 0;
                 foreach (PBESwitchIn s in switches)
                 {
                     PBEPokemon pkmn = team.TryGetPokemon(s.PokemonId);
                     pkmn.FieldPosition = s.Position;
                     team.SwitchInQueue.Add(pkmn);
                 }
                 if (team.Battle.Teams.All(t => t.SwitchInsRequired == 0))
                 {
                     team.Battle.SwitchesOrActions();
                 }
                 return(true);
             }
         }
     }
     return(false);
 }
예제 #3
0
        /// <summary>Determines whether chosen switches are valid.</summary>
        /// <param name="team">The team the inputted switches belong to.</param>
        /// <param name="switches">The switches the team wishes to execute.</param>
        /// <returns>False if the team already chose switches or the switches are illegal, True otherwise.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
        public static bool AreSwitchesValid(PBETeam team, IList <PBESwitchIn> switches)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (switches == null || switches.Any(s => s == null))
            {
                throw new ArgumentNullException(nameof(switches));
            }
            if (team.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(team));
            }
            if (team.Battle.BattleState != PBEBattleState.WaitingForSwitchIns)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to validate switches.");
            }
            if (team.SwitchInsRequired == 0 || switches.Count != team.SwitchInsRequired)
            {
                return(false);
            }
            var verified = new List <PBEPokemon>(team.SwitchInsRequired);

            foreach (PBESwitchIn s in switches)
            {
                PBEPokemon pkmn = team.TryGetPokemon(s.PokemonId);
                if (pkmn == null || pkmn.HP == 0 || pkmn.FieldPosition != PBEFieldPosition.None || verified.Contains(pkmn))
                {
                    return(false);
                }
                verified.Add(pkmn);
            }
            return(true);
        }
예제 #4
0
 /// <summary>Selects switches if they are valid. Changes the battle state if both teams have selected valid switches.</summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>True if the switches are valid and were selected.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool SelectSwitchesIfValid(PBETeam team, IList <PBESwitchIn> switches)
 {
     if (team == null)
     {
         throw new ArgumentNullException(nameof(team));
     }
     if (switches == null)
     {
         throw new ArgumentNullException(nameof(switches));
     }
     if (team.IsDisposed)
     {
         throw new ObjectDisposedException(nameof(team));
     }
     if (team.Battle.BattleState != PBEBattleState.WaitingForSwitchIns)
     {
         throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to select switches.");
     }
     if (AreSwitchesValid(team, switches))
     {
         lock (team.Battle._disposeLockObj)
         {
             if (!team.Battle.IsDisposed)
             {
                 team.SwitchInsRequired = 0;
                 foreach (PBESwitchIn s in switches)
                 {
                     PBEPokemon pkmn = team.TryGetPokemon(s.PokemonId);
                     pkmn.FieldPosition = s.Position;
                     team.SwitchInQueue.Add(pkmn);
                 }
                 if (team.Battle.Teams.All(t => t.SwitchInsRequired == 0))
                 {
                     team.Battle.SwitchesOrActions();
                 }
                 return(true);
             }
         }
     }
     return(false);
 }
        /// <summary>Selects actions if they are valid. Changes the battle state if both teams have selected valid actions.</summary>
        /// <param name="trainer">The trainer the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>True if the actions are valid and were selected.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool SelectActionsIfValid(PBETrainer trainer, IReadOnlyList <PBETurnAction> actions)
        {
            if (AreActionsValid(trainer, actions))
            {
                trainer.ActionsRequired.Clear();
                foreach (PBETurnAction action in actions)
                {
                    PBEBattlePokemon pkmn = trainer.TryGetPokemon(action.PokemonId);
                    if (action.Decision == PBETurnDecision.Fight && pkmn.GetMoveTargets(action.FightMove) == PBEMoveTarget.RandomFoeSurrounding)
                    {
                        switch (trainer.Battle.BattleFormat)
                        {
                        case PBEBattleFormat.Single:
                        case PBEBattleFormat.Rotation:
                        {
                            action.FightTargets = PBETurnTarget.FoeCenter;
                            break;
                        }

                        case PBEBattleFormat.Double:
                        {
                            action.FightTargets = PBERandom.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeRight;
                            break;
                        }

                        case PBEBattleFormat.Triple:
                        {
                            if (pkmn.FieldPosition == PBEFieldPosition.Left)
                            {
                                action.FightTargets = PBERandom.RandomBool() ? PBETurnTarget.FoeCenter : PBETurnTarget.FoeRight;
                            }
                            else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                            {
                                PBETeam oppTeam = trainer.Team.OpposingTeam;
                                int     r; // Keep randomly picking until a non-fainted foe is selected
roll:
                                r = PBERandom.RandomInt(0, 2);
                                if (r == 0)
                                {
                                    if (oppTeam.TryGetPokemon(PBEFieldPosition.Left) != null)
                                    {
                                        action.FightTargets = PBETurnTarget.FoeLeft;
                                    }
                                    else
                                    {
                                        goto roll;
                                    }
                                }
                                else if (r == 1)
                                {
                                    if (oppTeam.TryGetPokemon(PBEFieldPosition.Center) != null)
                                    {
                                        action.FightTargets = PBETurnTarget.FoeCenter;
                                    }
                                    else
                                    {
                                        goto roll;
                                    }
                                }
                                else
                                {
                                    if (oppTeam.TryGetPokemon(PBEFieldPosition.Right) != null)
                                    {
                                        action.FightTargets = PBETurnTarget.FoeRight;
                                    }
                                    else
                                    {
                                        goto roll;
                                    }
                                }
                            }
                            else
                            {
                                action.FightTargets = PBERandom.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeCenter;
                            }
                            break;
                        }

                        default: throw new ArgumentOutOfRangeException(nameof(trainer.Battle.BattleFormat));
                        }
                    }
                    pkmn.TurnAction = action;
                }
                if (trainer.Battle.Trainers.All(t => t.ActionsRequired.Count == 0))
                {
                    trainer.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
                    trainer.Battle.OnStateChanged?.Invoke(trainer.Battle);
                }
                return(true);
            }
            return(false);
        }
예제 #6
0
        /// <summary>Selects actions if they are valid. Changes the battle state if both teams have selected valid actions.</summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>True if the actions are valid and were selected.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool SelectActionsIfValid(PBETeam team, IList <PBETurnAction> actions)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (actions == null)
            {
                throw new ArgumentNullException(nameof(actions));
            }
            if (team.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(team));
            }
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to select actions.");
            }
            if (AreActionsValid(team, actions))
            {
                lock (team.Battle._disposeLockObj)
                {
                    if (!team.Battle.IsDisposed)
                    {
                        team.ActionsRequired.Clear();
                        foreach (PBETurnAction action in actions)
                        {
                            PBEPokemon pkmn = team.TryGetPokemon(action.PokemonId);
                            if (action.Decision == PBETurnDecision.Fight && pkmn.GetMoveTargets(action.FightMove) == PBEMoveTarget.RandomFoeSurrounding)
                            {
                                switch (team.Battle.BattleFormat)
                                {
                                case PBEBattleFormat.Single:
                                case PBEBattleFormat.Rotation:
                                {
                                    action.FightTargets = PBETurnTarget.FoeCenter;
                                    break;
                                }

                                case PBEBattleFormat.Double:
                                {
                                    action.FightTargets = PBEUtils.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeRight;
                                    break;
                                }

                                case PBEBattleFormat.Triple:
                                {
                                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                                    {
                                        action.FightTargets = PBEUtils.RandomBool() ? PBETurnTarget.FoeCenter : PBETurnTarget.FoeRight;
                                    }
                                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                                    {
                                        int r;     // Keep randomly picking until a non-fainted foe is selected
roll:
                                        r = PBEUtils.RandomInt(0, 2);
                                        if (r == 0)
                                        {
                                            if (team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Left) != null)
                                            {
                                                action.FightTargets = PBETurnTarget.FoeLeft;
                                            }
                                            else
                                            {
                                                goto roll;
                                            }
                                        }
                                        else if (r == 1)
                                        {
                                            if (team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Center) != null)
                                            {
                                                action.FightTargets = PBETurnTarget.FoeCenter;
                                            }
                                            else
                                            {
                                                goto roll;
                                            }
                                        }
                                        else
                                        {
                                            if (team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Right) != null)
                                            {
                                                action.FightTargets = PBETurnTarget.FoeRight;
                                            }
                                            else
                                            {
                                                goto roll;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        action.FightTargets = PBEUtils.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeCenter;
                                    }
                                    break;
                                }

                                default: throw new ArgumentOutOfRangeException(nameof(team.Battle.BattleFormat));
                                }
                            }
                            pkmn.TurnAction = action;
                        }
                        if (team.Battle.Teams.All(t => t.ActionsRequired.Count == 0))
                        {
                            team.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
                            team.Battle.OnStateChanged?.Invoke(team.Battle);
                        }
                        return(true);
                    }
                }
            }
            return(false);
        }
예제 #7
0
        /// <summary>
        /// Selects actions if they are valid. Changes the battle state if both teams have selected valid actions.
        /// </summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>True if the actions are valid and were selected.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool SelectActionsIfValid(PBETeam team, IEnumerable <PBEAction> actions)
        {
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to select actions.");
            }
            if (AreActionsValid(team, actions))
            {
                team.ActionsRequired.Clear();
                foreach (PBEAction action in actions)
                {
                    PBEPokemon pkmn = team.Battle.TryGetPokemon(action.PokemonId);
                    pkmn.SelectedAction = action;
                    switch (pkmn.SelectedAction.Decision)
                    {
                    case PBEDecision.Fight:
                    {
                        switch (pkmn.GetMoveTargets(pkmn.SelectedAction.FightMove))
                        {
                        case PBEMoveTarget.RandomFoeSurrounding:
                        {
                            switch (team.Battle.BattleFormat)
                            {
                            case PBEBattleFormat.Single:
                            case PBEBattleFormat.Rotation:
                            {
                                pkmn.SelectedAction.FightTargets = PBETarget.FoeCenter;
                                break;
                            }

                            case PBEBattleFormat.Double:
                            {
                                pkmn.SelectedAction.FightTargets = PBEUtils.RNG.NextBoolean() ? PBETarget.FoeLeft : PBETarget.FoeRight;
                                break;
                            }

                            case PBEBattleFormat.Triple:
                            {
                                if (pkmn.FieldPosition == PBEFieldPosition.Left)
                                {
                                    pkmn.SelectedAction.FightTargets = PBEUtils.RNG.NextBoolean() ? PBETarget.FoeCenter : PBETarget.FoeRight;
                                }
                                else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                                {
                                    PBETeam opposingTeam = team == team.Battle.Teams[0] ? team.Battle.Teams[1] : team.Battle.Teams[0];
                                    int     r;                     // Keep randomly picking until a non-fainted foe is selected
roll:
                                    r = PBEUtils.RNG.Next(3);
                                    if (r == 0)
                                    {
                                        if (opposingTeam.TryGetPokemon(PBEFieldPosition.Left) != null)
                                        {
                                            pkmn.SelectedAction.FightTargets = PBETarget.FoeLeft;
                                        }
                                        else
                                        {
                                            goto roll;
                                        }
                                    }
                                    else if (r == 1)
                                    {
                                        if (opposingTeam.TryGetPokemon(PBEFieldPosition.Center) != null)
                                        {
                                            pkmn.SelectedAction.FightTargets = PBETarget.FoeCenter;
                                        }
                                        else
                                        {
                                            goto roll;
                                        }
                                    }
                                    else
                                    {
                                        if (opposingTeam.TryGetPokemon(PBEFieldPosition.Right) != null)
                                        {
                                            pkmn.SelectedAction.FightTargets = PBETarget.FoeRight;
                                        }
                                        else
                                        {
                                            goto roll;
                                        }
                                    }
                                }
                                else
                                {
                                    pkmn.SelectedAction.FightTargets = PBEUtils.RNG.NextBoolean() ? PBETarget.FoeLeft : PBETarget.FoeCenter;
                                }
                                break;
                            }
                            }
                            break;
                        }

                        case PBEMoveTarget.SingleAllySurrounding:
                        {
                            if (team.Battle.BattleFormat == PBEBattleFormat.Single || team.Battle.BattleFormat == PBEBattleFormat.Rotation)
                            {
                                pkmn.SelectedAction.FightTargets = PBETarget.AllyCenter;
                            }
                            break;
                        }
                        }
                        break;
                    }
                    }
                }
                if (team.Battle.Teams.All(t => t.ActionsRequired.Count == 0))
                {
                    team.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
                    team.Battle.OnStateChanged?.Invoke(team.Battle);
                }
                return(true);
            }
            return(false);
        }
예제 #8
0
        /// <summary>
        /// Gets all Pokémon that will be hit.
        /// </summary>
        /// <param name="user">The Pokémon that will act.</param>
        /// <param name="requestedTargets">The targets the Pokémon wishes to hit.</param>
        /// <param name="canHitFarCorners">Whether the move can hit far Pokémon in a triple battle.</param>
        static PBEPokemon[] GetRuntimeTargets(PBEPokemon user, PBETarget requestedTargets, bool canHitFarCorners)
        {
            PBETeam opposingTeam = user.Team == user.Team.Battle.Teams[0] ? user.Team.Battle.Teams[1] : user.Team.Battle.Teams[0];

            var targets = new List <PBEPokemon>();

            if (requestedTargets.HasFlag(PBETarget.AllyLeft))
            {
                targets.Add(user.Team.TryGetPokemon(PBEFieldPosition.Left));
            }
            if (requestedTargets.HasFlag(PBETarget.AllyCenter))
            {
                targets.Add(user.Team.TryGetPokemon(PBEFieldPosition.Center));
            }
            if (requestedTargets.HasFlag(PBETarget.AllyRight))
            {
                targets.Add(user.Team.TryGetPokemon(PBEFieldPosition.Right));
            }
            if (requestedTargets.HasFlag(PBETarget.FoeLeft))
            {
                PBEPokemon pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                if (pkmn == null)
                {
                    if (user.Team.Battle.BattleFormat == PBEBattleFormat.Double)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                    }
                    else if (user.Team.Battle.BattleFormat == PBEBattleFormat.Triple)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Center);
                        // Center fainted as well and user can reach far right
                        if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Right || canHitFarCorners))
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                        }
                    }
                }
                targets.Add(pkmn);
            }
            if (requestedTargets.HasFlag(PBETarget.FoeCenter))
            {
                PBEPokemon pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Center);
                // Target fainted, fallback to its teammate
                if (pkmn == null)
                {
                    if (user.Team.Battle.BattleFormat == PBEBattleFormat.Triple)
                    {
                        if (user.FieldPosition == PBEFieldPosition.Left)
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                            // Right fainted as well and user can reach far left
                            if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Left || canHitFarCorners))
                            {
                                pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                            }
                        }
                        else if (user.FieldPosition == PBEFieldPosition.Right)
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                            // Left fainted as well and user can reach far right
                            if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Right || canHitFarCorners))
                            {
                                pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                            }
                        }
                        else // Center
                        {
                            PBEPokemon oppLeft  = opposingTeam.TryGetPokemon(PBEFieldPosition.Left),
                                       oppRight = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                            // Left is dead but not right
                            if (oppLeft == null && oppRight != null)
                            {
                                pkmn = oppRight;
                            }
                            // Right is dead but not left
                            else if (oppLeft != null && oppRight == null)
                            {
                                pkmn = oppLeft;
                            }
                            // Randomly select left or right
                            else
                            {
                                pkmn = PBEUtils.RNG.NextBoolean() ? oppLeft : oppRight;
                            }
                        }
                    }
                }
                targets.Add(pkmn);
            }
            if (requestedTargets.HasFlag(PBETarget.FoeRight))
            {
                PBEPokemon pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                // Target fainted, fallback to its teammate
                if (pkmn == null)
                {
                    if (user.Team.Battle.BattleFormat == PBEBattleFormat.Double)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                    }
                    else if (user.Team.Battle.BattleFormat == PBEBattleFormat.Triple)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Center);
                        // Center fainted as well and user can reach far left
                        if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Left || canHitFarCorners))
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                        }
                    }
                }
                targets.Add(pkmn);
            }
            return(targets.Where(p => p != null).Distinct().ToArray()); // Remove duplicate targets
        }