Esempio n. 1
0
        private void SelectMoveForTurn(PBEMove move)
        {
            PBEBattlePokemon pkmn            = _pkmn.Pkmn;
            PBEMoveTarget    possibleTargets = pkmn.GetMoveTargets(move);
            // Single battle only
            PBETurnTarget targets;

            switch (possibleTargets)
            {
            case PBEMoveTarget.All: targets = PBETurnTarget.AllyCenter | PBETurnTarget.FoeCenter; break;

            case PBEMoveTarget.AllFoes:
            case PBEMoveTarget.AllFoesSurrounding:
            case PBEMoveTarget.AllSurrounding:
            case PBEMoveTarget.RandomFoeSurrounding:
            case PBEMoveTarget.SingleFoeSurrounding:
            case PBEMoveTarget.SingleNotSelf:
            case PBEMoveTarget.SingleSurrounding: targets = PBETurnTarget.FoeCenter; break;

            case PBEMoveTarget.AllTeam:
            case PBEMoveTarget.Self:
            case PBEMoveTarget.SelfOrAllySurrounding:
            case PBEMoveTarget.SingleAllySurrounding: targets = PBETurnTarget.AllyCenter; break;

            default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
            }
            pkmn.TurnAction = new PBETurnAction(pkmn, move, targets);
            _parent.ActionsLoop(false);
        }
Esempio n. 2
0
 private PBEMoveData(PBEType type, PBEMoveCategory category, sbyte priority, byte ppTier, byte power, byte accuracy,
                     PBEMoveEffect effect, int effectParam, PBEMoveTarget targets,
                     PBEMoveFlag flags)
 {
     Type   = type; Category = category; Priority = priority; PPTier = ppTier; Power = power; Accuracy = accuracy;
     Effect = effect; EffectParam = effectParam; Targets = targets;
     Flags  = flags;
 }
Esempio n. 3
0
        public static bool IsSpreadMove(PBEMoveTarget targets)
        {
            switch (targets)
            {
            case PBEMoveTarget.All:
            case PBEMoveTarget.AllFoes:
            case PBEMoveTarget.AllFoesSurrounding:
            case PBEMoveTarget.AllSurrounding:
            case PBEMoveTarget.AllTeam: return(true);

            default: return(false);
            }
        }
Esempio n. 4
0
        private unsafe void SelectMoveForTurn(PBEMove move)
        {
            PBEMoveTarget possibleTargets = _pkmn.GetMoveTargets(move);

            if (_pkmn.Battle.BattleFormat == PBEBattleFormat.Single || _pkmn.Battle.BattleFormat == PBEBattleFormat.Rotation)
            {
                PBETurnTarget targets;
                switch (possibleTargets)
                {
                case PBEMoveTarget.All: targets = PBETurnTarget.AllyCenter | PBETurnTarget.FoeCenter; break;

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding: targets = PBETurnTarget.FoeCenter; break;

                case PBEMoveTarget.AllTeam:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                case PBEMoveTarget.SingleAllySurrounding: targets = PBETurnTarget.AllyCenter; break;

                default: throw new Exception();
                }
                _pkmn.TurnAction = new PBETurnAction(_pkmn, move, targets);
                BattleGUI.Instance.ActionsLoop(false);
            }
            else // Double / Triple
            {
                void TargetSelected()
                {
                    BattleGUI.Instance.ActionsLoop(false);
                    _targetsGUI = null;
                    // no need to change callbacks since this'll get disposed in actionsloop
                }

                void TargetCancelled()
                {
                    _targetsGUI = null;
                    SetCallbacksForMoves();
                }

                _targetsGUI = new TargetsGUI(_pkmn, possibleTargets, move, BattleGUI.Instance.SpritedParties, TargetSelected, TargetCancelled);
                Game.Instance.SetCallback(CB_Targets);
                Game.Instance.SetRCallback(RCB_Targets);
            }
        }
Esempio n. 5
0
        /// <summary>Creates valid actions for a battle turn for a specific team.</summary>
        /// <param name="team">The team to create actions for.</param>
        /// <exception cref="InvalidOperationException">Thrown when <paramref name="team"/> has no active battlers or <paramref name="team"/>'s <see cref="PBETeam.Battle"/>'s <see cref="PBEBattle.BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when a Pokémon has no moves, the AI tries to use a move with invalid targets, or <paramref name="team"/>'s <see cref="PBETeam.Battle"/>'s <see cref="PBEBattle.BattleFormat"/> is invalid.</exception>
        public static PBETurnAction[] CreateActions(PBETeam team)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (team.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(team));
            }
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(team.Battle.BattleState)} must be {PBEBattleState.WaitingForActions} to create actions.");
            }
            var actions = new PBETurnAction[team.ActionsRequired.Count];
            var standBy = new List <PBEPokemon>();

            for (int i = 0; i < actions.Length; i++)
            {
                PBEPokemon user = team.ActionsRequired[i];
                // If a Pokémon is forced to struggle, it is best that it just stays in until it faints
                if (user.IsForcedToStruggle())
                {
                    actions[i] = new PBETurnAction(user.Id, PBEMove.Struggle, GetPossibleTargets(user, user.GetMoveTargets(PBEMove.Struggle))[0]);
                }
                // If a Pokémon has a temp locked move (Dig, Dive, Shadow Force) it must be used
                else if (user.TempLockedMove != PBEMove.None)
                {
                    actions[i] = new PBETurnAction(user.Id, user.TempLockedMove, user.TempLockedTargets);
                }
                // The Pokémon is free to switch or fight (unless it cannot switch due to Magnet Pull etc)
                else
                {
                    // Gather all options of switching and moves
                    PBEPokemon[] availableForSwitch = team.Party.Except(standBy).Where(p => p.FieldPosition == PBEFieldPosition.None && p.HP > 0).ToArray();
                    PBEMove[]    usableMoves        = user.GetUsableMoves();
                    var          possibleActions    = new List <(PBETurnAction Action, double Score)>();
                    for (int m = 0; m < usableMoves.Length; m++) // Score moves
                    {
                        PBEMove         move            = usableMoves[m];
                        PBEType         moveType        = user.GetMoveType(move);
                        PBEMoveTarget   moveTargets     = user.GetMoveTargets(move);
                        PBETurnTarget[] possibleTargets = PBEMoveData.IsSpreadMove(moveTargets)
                            ? new PBETurnTarget[] { GetSpreadMoveTargets(user, moveTargets) }
                            : GetPossibleTargets(user, moveTargets);
                        foreach (PBETurnTarget possibleTarget in possibleTargets)
                        {
                            // TODO: RandomFoeSurrounding (probably just account for the specific effects that use this target type)
                            // TODO: Don't queue up to do the same thing (two trying to afflict the same target when there are multiple targets)
                            var targets = new List <PBEPokemon>();
                            if (possibleTarget.HasFlag(PBETurnTarget.AllyLeft))
                            {
                                targets.Add(team.TryGetPokemon(PBEFieldPosition.Left));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.AllyCenter))
                            {
                                targets.Add(team.TryGetPokemon(PBEFieldPosition.Center));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.AllyRight))
                            {
                                targets.Add(team.TryGetPokemon(PBEFieldPosition.Right));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.FoeLeft))
                            {
                                targets.Add(team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Left));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.FoeCenter))
                            {
                                targets.Add(team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Center));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.FoeRight))
                            {
                                targets.Add(team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Right));
                            }
                            double score;
                            if (targets.All(p => p == null))
                            {
                                score = -100;
                            }
                            else
                            {
                                score = 0d;
                                targets.RemoveAll(p => p == null);
                                PBEMoveData mData = PBEMoveData.Data[move];
                                switch (mData.Effect)
                                {
                                case PBEMoveEffect.Attract:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Destiny knot
                                        if (target.IsAttractionPossible(user, useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.BrickBreak:
                                case PBEMoveEffect.Dig:
                                case PBEMoveEffect.Dive:
                                case PBEMoveEffect.Fly:
                                case PBEMoveEffect.Hit:
                                case PBEMoveEffect.Hit__MaybeBurn:
                                case PBEMoveEffect.Hit__MaybeBurn__10PercentFlinch:
                                case PBEMoveEffect.Hit__MaybeConfuse:
                                case PBEMoveEffect.Hit__MaybeFlinch:
                                case PBEMoveEffect.Hit__MaybeFreeze:
                                case PBEMoveEffect.Hit__MaybeFreeze__10PercentFlinch:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2:
                                case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1:
                                case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1:
                                case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1:
                                case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2:
                                case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1:
                                case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1:
                                case PBEMoveEffect.Hit__MaybeParalyze:
                                case PBEMoveEffect.Hit__MaybeParalyze__10PercentFlinch:
                                case PBEMoveEffect.Hit__MaybePoison:
                                case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1:
                                case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1:
                                case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1:
                                case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1:
                                case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1:
                                case PBEMoveEffect.Hit__MaybeToxic:
                                case PBEMoveEffect.HPDrain:
                                case PBEMoveEffect.Recoil:
                                case PBEMoveEffect.Recoil__10PercentBurn:
                                case PBEMoveEffect.Recoil__10PercentParalyze:
                                case PBEMoveEffect.SuckerPunch:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Favor hitting ally with move if waterabsorb/voltabsorb etc
                                        // TODO: Liquid ooze
                                        // TODO: Check items
                                        // TODO: Stat changes and accuracy (even thunder/guillotine accuracy)
                                        // TODO: Check base power specifically against hp remaining (include spread move damage reduction)
                                        target.IsAffectedByMove(user, moveType, out double damageMultiplier, useKnownInfo: true);
                                        if (damageMultiplier <= 0)     // (-infinity, 0.0] Ineffective
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                        else if (damageMultiplier <= 0.25)     // (0.0, 0.25] NotVeryEffective
                                        {
                                            score += target.Team == team ? -5 : -30;
                                        }
                                        else if (damageMultiplier < 1)     // (0.25, 1.0) NotVeryEffective
                                        {
                                            score += target.Team == team ? -10 : -10;
                                        }
                                        else if (damageMultiplier == 1)     // [1.0, 1.0] Normal
                                        {
                                            score += target.Team == team ? -15 : +10;
                                        }
                                        else if (damageMultiplier < 4)     // (1.0, 4.0) SuperEffective
                                        {
                                            score += target.Team == team ? -20 : +25;
                                        }
                                        else     // [4.0, infinity) SuperEffective
                                        {
                                            score += target.Team == team ? -30 : +40;
                                        }
                                        if (user.HasType(moveType) && damageMultiplier > 0)     // STAB
                                        {
                                            score += (user.Ability == PBEAbility.Adaptability ? 7 : 5) * (target.Team == team ? -1 : +1);
                                        }
                                    }

                                    break;
                                }

                                case PBEMoveEffect.Burn:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Heatproof, physical attacker
                                        if (target.IsBurnPossible(user, useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_ACC:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Accuracy, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_ATK:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_DEF:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Defense, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_EVA:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Evasion, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_SPATK:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.SpAttack, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_SPDEF:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.SpDefense, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_SPE:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Speed, mData.EffectParam, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.Confuse:
                                case PBEMoveEffect.Flatter:
                                case PBEMoveEffect.Swagger:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Only swagger/flatter if the opponent most likely won't use it against you
                                        if (target.IsConfusionPossible(user, useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.Growth:
                                {
                                    int change = team.Battle.WillLeafGuardActivate() ? +2 : +1;
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, change, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpAttack, change, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.LeechSeed:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        if (target.IsLeechSeedPossible(useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.LightScreen:
                                {
                                    score += team.TeamStatus.HasFlag(PBETeamStatus.LightScreen) || IsTeammateUsingEffect(actions, PBEMoveEffect.LightScreen) ? -100 : +40;
                                    break;
                                }

                                case PBEMoveEffect.LowerTarget_ATK_DEF_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, -1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Defense, -1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.LowerTarget_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Defense, -1, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpDefense, -1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Attack, +2, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpAttack, +2, ref score);
                                        ScoreStatChange(user, target, PBEStat.Speed, +2, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.LuckyChant:
                                {
                                    score += team.TeamStatus.HasFlag(PBETeamStatus.LuckyChant) || IsTeammateUsingEffect(actions, PBEMoveEffect.LuckyChant) ? -100 : +40;
                                    break;
                                }

                                case PBEMoveEffect.Moonlight:
                                case PBEMoveEffect.Rest:
                                case PBEMoveEffect.RestoreTargetHP:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        if (target.Team == team)
                                        {
                                            score += HPAware(target.HPPercentage, +45, -15);
                                        }
                                        else
                                        {
                                            score -= 100;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.Nothing:
                                case PBEMoveEffect.Teleport:
                                {
                                    score -= 100;
                                    break;
                                }

                                case PBEMoveEffect.Paralyze:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Effectiveness with thunder wave/glare
                                        if (target.IsParalysisPossible(user, useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.Poison:
                                case PBEMoveEffect.Toxic:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Poison Heal
                                        if (target.IsPoisonPossible(user, useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_ATK_ACC_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Accuracy, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_ATK_DEF_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Defense, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_ATK_DEF_ACC_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Defense, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Accuracy, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_ATK_SPATK_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpAttack, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_ATK_SPE_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Speed, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_DEF_SPDEF_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Defense, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpDefense, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.SpAttack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpDefense, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_SPE_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.SpAttack, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.SpDefense, +1, ref score);
                                        ScoreStatChange(user, target, PBEStat.Speed, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.RaiseTarget_SPE_By2_ATK_By1:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        ScoreStatChange(user, target, PBEStat.Speed, +2, ref score);
                                        ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                    }
                                    break;
                                }

                                case PBEMoveEffect.Reflect:
                                {
                                    score += team.TeamStatus.HasFlag(PBETeamStatus.Reflect) || IsTeammateUsingEffect(actions, PBEMoveEffect.Reflect) ? -100 : +40;
                                    break;
                                }

                                case PBEMoveEffect.Safeguard:
                                {
                                    score += team.TeamStatus.HasFlag(PBETeamStatus.Safeguard) || IsTeammateUsingEffect(actions, PBEMoveEffect.Safeguard) ? -100 : +40;
                                    break;
                                }

                                case PBEMoveEffect.Sleep:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        // TODO: Bad Dreams
                                        if (target.IsSleepPossible(user, useKnownInfo: true) == PBEResult.Success)
                                        {
                                            score += target.Team == team ? -20 : +40;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -60;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.Substitute:
                                {
                                    foreach (PBEPokemon target in targets)
                                    {
                                        if (target.IsSubstitutePossible() == PBEResult.Success)
                                        {
                                            score += target.Team == team?HPAware(target.HPPercentage, -30, +50) : -60;
                                        }
                                        else
                                        {
                                            score += target.Team == team ? 0 : -20;
                                        }
                                    }
                                    break;
                                }

                                case PBEMoveEffect.ChangeTarget_SPATK__IfAttractionPossible:
                                case PBEMoveEffect.Conversion:
                                case PBEMoveEffect.Curse:
                                case PBEMoveEffect.Endeavor:
                                case PBEMoveEffect.FinalGambit:
                                case PBEMoveEffect.FocusEnergy:
                                case PBEMoveEffect.GastroAcid:
                                case PBEMoveEffect.Hail:
                                case PBEMoveEffect.Haze:
                                case PBEMoveEffect.HelpingHand:
                                case PBEMoveEffect.HPDrain__RequireSleep:
                                case PBEMoveEffect.MagnetRise:
                                case PBEMoveEffect.Metronome:
                                case PBEMoveEffect.OneHitKnockout:
                                case PBEMoveEffect.PainSplit:
                                case PBEMoveEffect.PowerTrick:
                                case PBEMoveEffect.Protect:
                                case PBEMoveEffect.PsychUp:
                                case PBEMoveEffect.Psywave:
                                case PBEMoveEffect.RainDance:
                                case PBEMoveEffect.Sandstorm:
                                case PBEMoveEffect.SeismicToss:
                                case PBEMoveEffect.Selfdestruct:
                                case PBEMoveEffect.SetDamage:
                                case PBEMoveEffect.SimpleBeam:
                                case PBEMoveEffect.Snore:
                                case PBEMoveEffect.Soak:
                                case PBEMoveEffect.Spikes:
                                case PBEMoveEffect.StealthRock:
                                case PBEMoveEffect.SunnyDay:
                                case PBEMoveEffect.SuperFang:
                                case PBEMoveEffect.Tailwind:
                                case PBEMoveEffect.ToxicSpikes:
                                case PBEMoveEffect.Transform:
                                case PBEMoveEffect.TrickRoom:
                                case PBEMoveEffect.Whirlwind:
                                case PBEMoveEffect.WideGuard:
                                {
                                    // TODO Moves
                                    break;
                                }

                                default: throw new ArgumentOutOfRangeException(nameof(PBEMoveData.Effect));
                                }
                            }
                            possibleActions.Add((new PBETurnAction(user.Id, move, possibleTarget), score));
                        }
                    }
                    if (user.CanSwitchOut())
                    {
                        for (int s = 0; s < availableForSwitch.Length; s++) // Score switches
                        {
                            PBEPokemon switchPkmn = availableForSwitch[s];
                            // TODO: Entry hazards
                            // TODO: Known moves of active battlers
                            // TODO: Type effectiveness
                            double score = -10d;
                            possibleActions.Add((new PBETurnAction(user.Id, switchPkmn.Id), score));
                        }
                    }

                    string ToDebugString((PBETurnAction Action, double Score) t)
                    {
                        string str = "{";

                        if (t.Action.Decision == PBETurnDecision.Fight)
                        {
                            str += string.Format("Fight {0} {1}", t.Action.FightMove, t.Action.FightTargets);
                        }
                        else
                        {
                            str += string.Format("Switch {0}", team.TryGetPokemon(t.Action.SwitchPokemonId).Nickname);
                        }
                        str += " [" + t.Score + "]}";
                        return(str);
                    }

                    IOrderedEnumerable <(PBETurnAction Action, double Score)> byScore = possibleActions.OrderByDescending(t => t.Score);
                    Debug.WriteLine("{0}'s possible actions: {1}", user.Nickname, byScore.Select(t => ToDebugString(t)).Print());
                    double bestScore = byScore.First().Score;
                    actions[i] = byScore.Where(t => t.Score == bestScore).ToArray().RandomElement().Action; // Pick random action of the ones that tied for best score
                }
                // Action was chosen, finish up for this Pokémon
                if (actions[i].Decision == PBETurnDecision.SwitchOut)
                {
                    standBy.Add(team.TryGetPokemon(actions[i].SwitchPokemonId));
                }
            }
            return(actions);
        }
Esempio n. 6
0
        /// <summary>Creates valid actions for a battle turn for a specific team.</summary>
        /// <param name="team">The team to create actions for.</param>
        /// <exception cref="InvalidOperationException">Thrown when <paramref name="team"/> has no active battlers or <paramref name="team"/>'s <see cref="PBETeam.Battle"/>'s <see cref="PBEBattle.BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when a Pokémon has no moves, the AI tries to use a move with invalid targets, or <paramref name="team"/>'s <see cref="PBETeam.Battle"/>'s <see cref="PBEBattle.BattleFormat"/> is invalid.</exception>
        public static PBETurnAction[] CreateActions(PBETeam team)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(team.Battle.BattleState)} must be {PBEBattleState.WaitingForActions} to create actions.");
            }

            var actions = new PBETurnAction[team.ActionsRequired.Count];
            var standBy = new List <PBEPokemon>();

            for (int i = 0; i < actions.Length; i++)
            {
                PBEPokemon pkmn = team.ActionsRequired[i];

                // If a Pokémon is forced to struggle, it is best that it just stays in until it faints
                if (pkmn.IsForcedToStruggle())
                {
                    actions[i] = new PBETurnAction(pkmn.Id, PBEMove.Struggle, GetPossibleTargets(pkmn, pkmn.GetMoveTargets(PBEMove.Struggle))[0]);
                }
                // If a Pokémon has a temp locked move (Dig, Dive, Shadow Force) it must be used
                else if (pkmn.TempLockedMove != PBEMove.None)
                {
                    actions[i] = new PBETurnAction(pkmn.Id, pkmn.TempLockedMove, pkmn.TempLockedTargets);
                }
                // The Pokémon is free to switch or fight (unless it cannot switch due to Magnet Pull etc)
                else
                {
                    // Gather all options of switching and moves
                    PBEPokemon[] availableForSwitch = team.Party.Except(standBy).Where(p => p.FieldPosition == PBEFieldPosition.None && p.HP > 0).ToArray();
                    PBEMove[]    usableMoves        = pkmn.GetUsableMoves();

                    var possibleActions = new List <(PBETurnAction Action, double Score)>();
                    for (int m = 0; m < usableMoves.Length; m++) // Score moves
                    {
                        PBEMove         move            = usableMoves[m];
                        PBEType         moveType        = pkmn.GetMoveType(move);
                        PBEMoveTarget   moveTargets     = pkmn.GetMoveTargets(move);
                        PBETurnTarget[] possibleTargets = PBEMoveData.IsSpreadMove(moveTargets)
                            ? new PBETurnTarget[] { GetSpreadMoveTargets(pkmn, moveTargets) }
                            : GetPossibleTargets(pkmn, moveTargets);
                        foreach (PBETurnTarget possibleTarget in possibleTargets)
                        {
                            // TODO: RandomFoeSurrounding (probably just account for the specific effects that use this target type)
                            var targets = new List <PBEPokemon>();
                            if (possibleTarget.HasFlag(PBETurnTarget.AllyLeft))
                            {
                                targets.Add(team.TryGetPokemon(PBEFieldPosition.Left));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.AllyCenter))
                            {
                                targets.Add(team.TryGetPokemon(PBEFieldPosition.Center));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.AllyRight))
                            {
                                targets.Add(team.TryGetPokemon(PBEFieldPosition.Right));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.FoeLeft))
                            {
                                targets.Add(team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Left));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.FoeCenter))
                            {
                                targets.Add(team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Center));
                            }
                            if (possibleTarget.HasFlag(PBETurnTarget.FoeRight))
                            {
                                targets.Add(team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Right));
                            }

                            double score = 0.0;
                            switch (PBEMoveData.Data[move].Effect)
                            {
                            case PBEMoveEffect.Burn:
                            case PBEMoveEffect.Paralyze:
                            case PBEMoveEffect.Poison:
                            case PBEMoveEffect.Sleep:
                            case PBEMoveEffect.Toxic:
                            {
                                foreach (PBEPokemon target in targets)
                                {
                                    if (target == null)
                                    {
                                        // TODO: If all targets are null, this should give a bad score
                                    }
                                    else
                                    {
                                        // TODO: Effectiveness check
                                        // TODO: Favor sleep with Bad Dreams (unless ally)
                                        if (target.Status1 != PBEStatus1.None)
                                        {
                                            score += target.Team == team.OpposingTeam ? -60 : 0;
                                        }
                                        else
                                        {
                                            score += target.Team == team.OpposingTeam ? +40 : -20;
                                        }
                                    }
                                }
                                break;
                            }

                            case PBEMoveEffect.Hail:
                            {
                                if (team.Battle.Weather == PBEWeather.Hailstorm)
                                {
                                    score -= 100;
                                }
                                break;
                            }

                            case PBEMoveEffect.BrickBreak:
                            case PBEMoveEffect.Dig:
                            case PBEMoveEffect.Dive:
                            case PBEMoveEffect.Fly:
                            case PBEMoveEffect.Hit:
                            case PBEMoveEffect.Hit__MaybeBurn:
                            case PBEMoveEffect.Hit__MaybeConfuse:
                            case PBEMoveEffect.Hit__MaybeFlinch:
                            case PBEMoveEffect.Hit__MaybeFreeze:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2:
                            case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1:
                            case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1:
                            case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1:
                            case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2:
                            case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1:
                            case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1:
                            case PBEMoveEffect.Hit__MaybeParalyze:
                            case PBEMoveEffect.Hit__MaybePoison:
                            case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1:
                            case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1:
                            case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1:
                            case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1:
                            case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1:
                            case PBEMoveEffect.Hit__MaybeToxic:
                            case PBEMoveEffect.HPDrain:
                            case PBEMoveEffect.Recoil:
                            case PBEMoveEffect.FlareBlitz:
                            case PBEMoveEffect.SuckerPunch:
                            case PBEMoveEffect.VoltTackle:
                            {
                                foreach (PBEPokemon target in targets)
                                {
                                    if (target == null)
                                    {
                                        // TODO: If all targets are null, this should give a bad score
                                    }
                                    else
                                    {
                                        // TODO: Put type checking somewhere in PBEPokemon (levitate, wonder guard, etc)
                                        // TODO: Favor hitting ally with move if it absorbs it
                                        // TODO: Check items
                                        // TODO: Stat changes and accuracy
                                        // TODO: Check base power specifically against hp remaining (include spread move damage reduction)
                                        double typeEffectiveness = PBEPokemonData.TypeEffectiveness[moveType][target.KnownType1];
                                        typeEffectiveness *= PBEPokemonData.TypeEffectiveness[moveType][target.KnownType2];
                                        if (typeEffectiveness <= 0.0)     // (-infinity, 0.0] Ineffective
                                        {
                                            score += target.Team == team.OpposingTeam ? -60 : -1;
                                        }
                                        else if (typeEffectiveness <= 0.25)     // (0.0, 0.25] NotVeryEffective
                                        {
                                            score += target.Team == team.OpposingTeam ? -30 : -5;
                                        }
                                        else if (typeEffectiveness < 1.0)     // (0.25, 1.0) NotVeryEffective
                                        {
                                            score += target.Team == team.OpposingTeam ? -10 : -10;
                                        }
                                        else if (typeEffectiveness == 1.0)     // [1.0, 1.0] Normal
                                        {
                                            score += target.Team == team.OpposingTeam ? +10 : -15;
                                        }
                                        else if (typeEffectiveness < 4.0)     // (1.0, 4.0) SuperEffective
                                        {
                                            score += target.Team == team.OpposingTeam ? +25 : -20;
                                        }
                                        else     // [4.0, infinity) SuperEffective
                                        {
                                            score += target.Team == team.OpposingTeam ? +40 : -30;
                                        }
                                        if (pkmn.HasType(moveType) && typeEffectiveness > 0.0)     // STAB
                                        {
                                            score += (pkmn.Ability == PBEAbility.Adaptability ? 15 : 10) * (target.Team == team.OpposingTeam ? +1 : -1);
                                        }
                                    }
                                }

                                break;
                            }

                            case PBEMoveEffect.Moonlight:
                            case PBEMoveEffect.Rest:
                            case PBEMoveEffect.RestoreTargetHP:
                            case PBEMoveEffect.RestoreUserHP:
                            {
                                PBEPokemon target = targets[0];
                                if (target == null || target.Team == team.OpposingTeam)
                                {
                                    score -= 100;
                                }
                                else     // Ally
                                {
                                    // 0% = +45, 25% = +30, 50% = +15, 75% = 0, 100% = -15
                                    score -= (60 * target.HPPercentage) - 45;
                                }
                                break;
                            }

                            case PBEMoveEffect.RainDance:
                            {
                                if (team.Battle.Weather == PBEWeather.Rain)
                                {
                                    score -= 100;
                                }
                                break;
                            }

                            case PBEMoveEffect.Sandstorm:
                            {
                                if (team.Battle.Weather == PBEWeather.Sandstorm)
                                {
                                    score -= 100;
                                }
                                break;
                            }

                            case PBEMoveEffect.SunnyDay:
                            {
                                if (team.Battle.Weather == PBEWeather.HarshSunlight)
                                {
                                    score -= 100;
                                }
                                break;
                            }

                            case PBEMoveEffect.Attract:
                            case PBEMoveEffect.ChangeTarget_ACC:
                            case PBEMoveEffect.ChangeTarget_ATK:
                            case PBEMoveEffect.ChangeTarget_DEF:
                            case PBEMoveEffect.ChangeTarget_EVA:
                            case PBEMoveEffect.ChangeTarget_SPDEF:
                            case PBEMoveEffect.ChangeTarget_SPE:
                            case PBEMoveEffect.ChangeUser_ATK:
                            case PBEMoveEffect.ChangeUser_DEF:
                            case PBEMoveEffect.ChangeUser_EVA:
                            case PBEMoveEffect.ChangeUser_SPATK:
                            case PBEMoveEffect.ChangeUser_SPDEF:
                            case PBEMoveEffect.ChangeUser_SPE:
                            case PBEMoveEffect.Confuse:
                            case PBEMoveEffect.Curse:
                            case PBEMoveEffect.Endeavor:
                            case PBEMoveEffect.Fail:
                            case PBEMoveEffect.FinalGambit:
                            case PBEMoveEffect.Flatter:
                            case PBEMoveEffect.FocusEnergy:
                            case PBEMoveEffect.GastroAcid:
                            case PBEMoveEffect.Growth:
                            case PBEMoveEffect.HelpingHand:
                            case PBEMoveEffect.LeechSeed:
                            case PBEMoveEffect.LightScreen:
                            case PBEMoveEffect.LowerTarget_ATK_DEF_By1:
                            case PBEMoveEffect.LowerUser_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2:
                            case PBEMoveEffect.LuckyChant:
                            case PBEMoveEffect.Metronome:
                            case PBEMoveEffect.OneHitKnockout:
                            case PBEMoveEffect.PainSplit:
                            case PBEMoveEffect.Protect:
                            case PBEMoveEffect.PsychUp:
                            case PBEMoveEffect.Psywave:
                            case PBEMoveEffect.RaiseUser_ATK_ACC_By1:
                            case PBEMoveEffect.RaiseUser_ATK_DEF_By1:
                            case PBEMoveEffect.RaiseUser_ATK_DEF_ACC_By1:
                            case PBEMoveEffect.RaiseUser_ATK_SPATK_By1:
                            case PBEMoveEffect.RaiseUser_ATK_SPE_By1:
                            case PBEMoveEffect.RaiseUser_DEF_SPDEF_By1:
                            case PBEMoveEffect.RaiseUser_SPATK_SPDEF_By1:
                            case PBEMoveEffect.RaiseUser_SPATK_SPDEF_SPE_By1:
                            case PBEMoveEffect.RaiseUser_SPE_By2_ATK_By1:
                            case PBEMoveEffect.Reflect:
                            case PBEMoveEffect.SeismicToss:
                            case PBEMoveEffect.Selfdestruct:
                            case PBEMoveEffect.SetDamage:
                            case PBEMoveEffect.Snore:
                            case PBEMoveEffect.Spikes:
                            case PBEMoveEffect.StealthRock:
                            case PBEMoveEffect.Substitute:
                            case PBEMoveEffect.SuperFang:
                            case PBEMoveEffect.Swagger:
                            case PBEMoveEffect.ToxicSpikes:
                            case PBEMoveEffect.Transform:
                            case PBEMoveEffect.TrickRoom:
                            case PBEMoveEffect.Whirlwind:
                            case PBEMoveEffect.WideGuard:
                            {
                                // TODO Moves
                                break;
                            }

                            default: throw new ArgumentOutOfRangeException(nameof(PBEMoveData.Effect));
                            }
                            possibleActions.Add((new PBETurnAction(pkmn.Id, move, possibleTarget), score));
                        }
                    }
                    if (pkmn.CanSwitchOut())
                    {
                        for (int s = 0; s < availableForSwitch.Length; s++) // Score switches
                        {
                            PBEPokemon switchPkmn = availableForSwitch[s];
                            // TODO: Entry hazards
                            // TODO: Known moves of active battlers
                            // TODO: Type effectiveness
                            double score = 0.0;
                            possibleActions.Add((new PBETurnAction(pkmn.Id, switchPkmn.Id), score));
                        }
                    }

                    string ToDebugString((PBETurnAction Action, double Score) t)
                    {
                        string str = "{";

                        if (t.Action.Decision == PBETurnDecision.Fight)
                        {
                            str += string.Format("Fight {0} {1}", t.Action.FightMove, t.Action.FightTargets);
                        }
                        else
                        {
                            str += string.Format("Switch {0}", team.TryGetPokemon(t.Action.SwitchPokemonId).Nickname);
                        }
                        str += " [" + t.Score + "]}";
                        return(str);
                    }

                    IOrderedEnumerable <(PBETurnAction Action, double Score)> byScore = possibleActions.OrderByDescending(t => t.Score);
                    Debug.WriteLine("{0}'s possible actions: {1}", pkmn.Nickname, byScore.Select(t => ToDebugString(t)).Print());
                    double bestScore = byScore.First().Score;
                    actions[i] = byScore.Where(t => t.Score == bestScore).ToArray().RandomElement().Action; // Pick random action of the ones that tied for best score
                }

                // Action was chosen, finish up for this Pokémon
                if (actions[i].Decision == PBETurnDecision.SwitchOut)
                {
                    standBy.Add(team.TryGetPokemon(actions[i].SwitchPokemonId));
                }
            }
            return(actions);
        }
Esempio n. 7
0
        private PBETurnAction DecideAction(PBEBattlePokemon user, List <PBETurnAction> actions, List <PBEBattlePokemon> standBy)
        {
            // Gather all options of switching and moves
            PBEMove[] usableMoves     = user.GetUsableMoves();
            var       possibleActions = new List <(PBETurnAction Action, float Score)>();

            for (int m = 0; m < usableMoves.Length; m++) // Score moves
            {
                PBEMove         move            = usableMoves[m];
                PBEType         moveType        = user.GetMoveType(move);
                PBEMoveTarget   moveTargets     = user.GetMoveTargets(move);
                PBETurnTarget[] possibleTargets = PBEDataUtils.IsSpreadMove(moveTargets)
                            ? new PBETurnTarget[] { PBEBattleUtils.GetSpreadMoveTargets(user, moveTargets) }
                            : PBEBattleUtils.GetPossibleTargets(user, moveTargets);
                foreach (PBETurnTarget possibleTarget in possibleTargets)
                {
                    // TODO: RandomFoeSurrounding (probably just account for the specific effects that use this target type)
                    // TODO: Don't queue up to do the same thing (two trying to afflict the same target when there are multiple targets)
                    var targets = new List <PBEBattlePokemon>();
                    if (possibleTarget.HasFlag(PBETurnTarget.AllyLeft))
                    {
                        Trainer.Team.TryAddPokemonToCollection(PBEFieldPosition.Left, targets);
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.AllyCenter))
                    {
                        Trainer.Team.TryAddPokemonToCollection(PBEFieldPosition.Center, targets);
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.AllyRight))
                    {
                        Trainer.Team.TryAddPokemonToCollection(PBEFieldPosition.Right, targets);
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.FoeLeft))
                    {
                        Trainer.Team.OpposingTeam.TryAddPokemonToCollection(PBEFieldPosition.Left, targets);
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.FoeCenter))
                    {
                        Trainer.Team.OpposingTeam.TryAddPokemonToCollection(PBEFieldPosition.Center, targets);
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.FoeRight))
                    {
                        Trainer.Team.OpposingTeam.TryAddPokemonToCollection(PBEFieldPosition.Right, targets);
                    }
                    float score = ScoreMove(targets, user, move, moveType, actions);
                    possibleActions.Add((new PBETurnAction(user, move, possibleTarget), score));
                }
            }
            if (user.CanSwitchOut())
            {
                PBEBattlePokemon[] availableForSwitch = Trainer.Party.Except(standBy).Where(p => p.FieldPosition == PBEFieldPosition.None && p.CanBattle).ToArray();
                for (int s = 0; s < availableForSwitch.Length; s++) // Score switches
                {
                    PBEBattlePokemon switchPkmn = availableForSwitch[s];
                    // TODO: Entry hazards
                    // TODO: Known moves of active battlers
                    // TODO: Type effectiveness
                    float score = -10;
                    possibleActions.Add((new PBETurnAction(user, switchPkmn), score));
                }
            }

            IOrderedEnumerable <(PBETurnAction Action, float Score)> byScore = possibleActions.OrderByDescending(t => t.Score);

            Debug_LogGeneratedActions(user, byScore);
            float bestScore = byScore.First().Score;

            return(PBEDataProvider.GlobalRandom.RandomElement(byScore.Where(t => t.Score == bestScore).ToArray()).Action); // Pick random action of the ones that tied for best score
        }
Esempio n. 8
0
        private static PBETurnAction DecideAction(PBETrainer trainer, PBEBattlePokemon user, IEnumerable <PBETurnAction> actions, IEnumerable <PBEBattlePokemon> standBy)
        {
            // Gather all options of switching and moves
            PBEMove[] usableMoves     = user.GetUsableMoves();
            var       possibleActions = new List <(PBETurnAction Action, double Score)>();

            for (int m = 0; m < usableMoves.Length; m++) // Score moves
            {
                PBEMove         move            = usableMoves[m];
                PBEType         moveType        = user.GetMoveType(move);
                PBEMoveTarget   moveTargets     = user.GetMoveTargets(move);
                PBETurnTarget[] possibleTargets = PBEDataUtils.IsSpreadMove(moveTargets)
                            ? new PBETurnTarget[] { PBEBattleUtils.GetSpreadMoveTargets(user, moveTargets) }
                            : PBEBattleUtils.GetPossibleTargets(user, moveTargets);
                foreach (PBETurnTarget possibleTarget in possibleTargets)
                {
                    // TODO: RandomFoeSurrounding (probably just account for the specific effects that use this target type)
                    // TODO: Don't queue up to do the same thing (two trying to afflict the same target when there are multiple targets)
                    var targets = new List <PBEBattlePokemon>();
                    if (possibleTarget.HasFlag(PBETurnTarget.AllyLeft))
                    {
                        targets.Add(trainer.TryGetPokemon(PBEFieldPosition.Left));
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.AllyCenter))
                    {
                        targets.Add(trainer.TryGetPokemon(PBEFieldPosition.Center));
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.AllyRight))
                    {
                        targets.Add(trainer.TryGetPokemon(PBEFieldPosition.Right));
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.FoeLeft))
                    {
                        targets.Add(trainer.Team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Left));
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.FoeCenter))
                    {
                        targets.Add(trainer.Team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Center));
                    }
                    if (possibleTarget.HasFlag(PBETurnTarget.FoeRight))
                    {
                        targets.Add(trainer.Team.OpposingTeam.TryGetPokemon(PBEFieldPosition.Right));
                    }
                    double score;
                    if (targets.All(p => p == null))
                    {
                        score = -100;
                    }
                    else
                    {
                        score = 0;
                        targets.RemoveAll(p => p == null);
                        IPBEMoveData mData = PBEDataProvider.Instance.GetMoveData(move);
                        if (!mData.IsMoveUsable())
                        {
                            throw new ArgumentOutOfRangeException(nameof(trainer), $"{move} is not yet implemented in Pokémon Battle Engine.");
                        }
                        switch (mData.Effect)
                        {
                        case PBEMoveEffect.Acrobatics:
                        case PBEMoveEffect.Bounce:
                        case PBEMoveEffect.BrickBreak:
                        case PBEMoveEffect.Brine:
                        case PBEMoveEffect.ChipAway:
                        case PBEMoveEffect.CrushGrip:
                        case PBEMoveEffect.Dig:
                        case PBEMoveEffect.Dive:
                        case PBEMoveEffect.Eruption:
                        case PBEMoveEffect.Facade:
                        case PBEMoveEffect.Feint:
                        case PBEMoveEffect.Flail:
                        case PBEMoveEffect.Fly:
                        case PBEMoveEffect.FoulPlay:
                        case PBEMoveEffect.Frustration:
                        case PBEMoveEffect.GrassKnot:
                        case PBEMoveEffect.HeatCrash:
                        case PBEMoveEffect.Hex:
                        case PBEMoveEffect.HiddenPower:
                        case PBEMoveEffect.Hit:
                        case PBEMoveEffect.Hit__2Times:
                        case PBEMoveEffect.Hit__2Times__MaybePoison:
                        case PBEMoveEffect.Hit__2To5Times:
                        case PBEMoveEffect.Hit__MaybeBurn:
                        case PBEMoveEffect.Hit__MaybeBurn__10PercentFlinch:
                        case PBEMoveEffect.Hit__MaybeBurnFreezeParalyze:
                        case PBEMoveEffect.Hit__MaybeConfuse:
                        case PBEMoveEffect.Hit__MaybeFlinch:
                        case PBEMoveEffect.Hit__MaybeFreeze:
                        case PBEMoveEffect.Hit__MaybeFreeze__10PercentFlinch:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2:
                        case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1:
                        case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1:
                        case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1:
                        case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2:
                        case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1:
                        case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1:
                        case PBEMoveEffect.Hit__MaybeParalyze:
                        case PBEMoveEffect.Hit__MaybeParalyze__10PercentFlinch:
                        case PBEMoveEffect.Hit__MaybePoison:
                        case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1:
                        case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1:
                        case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1:
                        case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1:
                        case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1:
                        case PBEMoveEffect.Hit__MaybeToxic:
                        case PBEMoveEffect.HPDrain:
                        case PBEMoveEffect.Judgment:
                        case PBEMoveEffect.Magnitude:
                        case PBEMoveEffect.Payback:
                        case PBEMoveEffect.PayDay:
                        case PBEMoveEffect.Psyshock:
                        case PBEMoveEffect.Punishment:
                        case PBEMoveEffect.Recoil:
                        case PBEMoveEffect.Recoil__10PercentBurn:
                        case PBEMoveEffect.Recoil__10PercentParalyze:
                        case PBEMoveEffect.Retaliate:
                        case PBEMoveEffect.Return:
                        case PBEMoveEffect.SecretPower:
                        case PBEMoveEffect.ShadowForce:
                        case PBEMoveEffect.SmellingSalt:
                        case PBEMoveEffect.StoredPower:
                        case PBEMoveEffect.TechnoBlast:
                        case PBEMoveEffect.Venoshock:
                        case PBEMoveEffect.WakeUpSlap:
                        case PBEMoveEffect.WeatherBall:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                // TODO: Favor hitting ally with move if waterabsorb/voltabsorb etc
                                // TODO: Liquid ooze
                                // TODO: Check items
                                // TODO: Stat changes and accuracy (even thunder/guillotine accuracy)
                                // TODO: Check base power specifically against hp remaining (include spread move damage reduction)
                                PBETypeEffectiveness.IsAffectedByAttack(user, target, moveType, out double damageMultiplier, useKnownInfo: true);
                                if (damageMultiplier <= 0)     // (-infinity, 0.0] Ineffective
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                                else if (damageMultiplier <= 0.25)     // (0.0, 0.25] NotVeryEffective
                                {
                                    score += target.Team == trainer.Team ? -5 : -30;
                                }
                                else if (damageMultiplier < 1)     // (0.25, 1.0) NotVeryEffective
                                {
                                    score += target.Team == trainer.Team ? -10 : -10;
                                }
                                else if (damageMultiplier == 1)     // [1.0, 1.0] Normal
                                {
                                    score += target.Team == trainer.Team ? -15 : +10;
                                }
                                else if (damageMultiplier < 4)     // (1.0, 4.0) SuperEffective
                                {
                                    score += target.Team == trainer.Team ? -20 : +25;
                                }
                                else     // [4.0, infinity) SuperEffective
                                {
                                    score += target.Team == trainer.Team ? -30 : +40;
                                }
                                if (user.ReceivesSTAB(moveType) && damageMultiplier > 0)
                                {
                                    score += (user.Ability == PBEAbility.Adaptability ? 7 : 5) * (target.Team == trainer.Team ? -1 : +1);
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.Attract:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                // TODO: Destiny knot
                                if (target.IsAttractionPossible(user, useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.Burn:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                // TODO: Heatproof, physical attacker
                                if (target.IsBurnPossible(user, useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_ACC:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Accuracy, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_ATK:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_DEF:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Defense, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_EVA:
                        case PBEMoveEffect.Minimize:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Evasion, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_SPATK:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.SpAttack, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_SPDEF:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.SpDefense, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.ChangeTarget_SPE:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Speed, mData.EffectParam, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.Confuse:
                        case PBEMoveEffect.Flatter:
                        case PBEMoveEffect.Swagger:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                // TODO: Only swagger/flatter if the opponent most likely won't use it against you
                                if (target.IsConfusionPossible(user, useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.Growth:
                        {
                            int change = trainer.Battle.WillLeafGuardActivate() ? +2 : +1;
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, change, ref score);
                                ScoreStatChange(user, target, PBEStat.SpAttack, change, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.LeechSeed:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                if (target.IsLeechSeedPossible(useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.LightScreen:
                        {
                            score += trainer.Team.TeamStatus.HasFlag(PBETeamStatus.LightScreen) || IsTeammateUsingEffect(actions, PBEMoveEffect.LightScreen) ? -100 : +40;
                            break;
                        }

                        case PBEMoveEffect.LowerTarget_ATK_DEF_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, -1, ref score);
                                ScoreStatChange(user, target, PBEStat.Defense, -1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.LowerTarget_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Defense, -1, ref score);
                                ScoreStatChange(user, target, PBEStat.SpDefense, -1, ref score);
                                ScoreStatChange(user, target, PBEStat.Attack, +2, ref score);
                                ScoreStatChange(user, target, PBEStat.SpAttack, +2, ref score);
                                ScoreStatChange(user, target, PBEStat.Speed, +2, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.LuckyChant:
                        {
                            score += trainer.Team.TeamStatus.HasFlag(PBETeamStatus.LuckyChant) || IsTeammateUsingEffect(actions, PBEMoveEffect.LuckyChant) ? -100 : +40;
                            break;
                        }

                        case PBEMoveEffect.Moonlight:
                        case PBEMoveEffect.Rest:
                        case PBEMoveEffect.RestoreTargetHP:
                        case PBEMoveEffect.Roost:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                if (target.Team == trainer.Team)
                                {
                                    score += HPAware(target.HPPercentage, +45, -15);
                                }
                                else
                                {
                                    score -= 100;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.Nothing:
                        case PBEMoveEffect.Teleport:
                        {
                            score -= 100;
                            break;
                        }

                        case PBEMoveEffect.Paralyze:
                        case PBEMoveEffect.ThunderWave:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                bool tw = mData.Effect != PBEMoveEffect.ThunderWave || PBETypeEffectiveness.ThunderWaveTypeCheck(user, target, move, useKnownInfo: true) == PBEResult.Success;
                                if (tw && target.IsParalysisPossible(user, useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.Poison:
                        case PBEMoveEffect.Toxic:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                // TODO: Poison Heal
                                if (target.IsPoisonPossible(user, useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_ATK_ACC_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.Accuracy, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_ATK_DEF_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.Defense, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_ATK_DEF_ACC_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.Defense, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.Accuracy, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_ATK_SPATK_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.SpAttack, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_ATK_SPE_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.Speed, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_DEF_SPDEF_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Defense, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.SpDefense, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.SpAttack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.SpDefense, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_SPE_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.SpAttack, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.SpDefense, +1, ref score);
                                ScoreStatChange(user, target, PBEStat.Speed, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.RaiseTarget_SPE_By2_ATK_By1:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                ScoreStatChange(user, target, PBEStat.Speed, +2, ref score);
                                ScoreStatChange(user, target, PBEStat.Attack, +1, ref score);
                            }
                            break;
                        }

                        case PBEMoveEffect.Reflect:
                        {
                            score += trainer.Team.TeamStatus.HasFlag(PBETeamStatus.Reflect) || IsTeammateUsingEffect(actions, PBEMoveEffect.Reflect) ? -100 : +40;
                            break;
                        }

                        case PBEMoveEffect.Safeguard:
                        {
                            score += trainer.Team.TeamStatus.HasFlag(PBETeamStatus.Safeguard) || IsTeammateUsingEffect(actions, PBEMoveEffect.Safeguard) ? -100 : +40;
                            break;
                        }

                        case PBEMoveEffect.Sleep:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                // TODO: Bad Dreams
                                if (target.IsSleepPossible(user, useKnownInfo: true) == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? -20 : +40;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -60;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.Substitute:
                        {
                            foreach (PBEBattlePokemon target in targets)
                            {
                                if (target.IsSubstitutePossible() == PBEResult.Success)
                                {
                                    score += target.Team == trainer.Team ? HPAware(target.HPPercentage, -30, +50) : -60;
                                }
                                else
                                {
                                    score += target.Team == trainer.Team ? 0 : -20;
                                }
                            }
                            break;
                        }

                        case PBEMoveEffect.BellyDrum:
                        case PBEMoveEffect.Camouflage:
                        case PBEMoveEffect.ChangeTarget_SPATK__IfAttractionPossible:
                        case PBEMoveEffect.Conversion:
                        case PBEMoveEffect.Curse:
                        case PBEMoveEffect.Endeavor:
                        case PBEMoveEffect.Entrainment:
                        case PBEMoveEffect.FinalGambit:
                        case PBEMoveEffect.FocusEnergy:
                        case PBEMoveEffect.Foresight:
                        case PBEMoveEffect.GastroAcid:
                        case PBEMoveEffect.Hail:
                        case PBEMoveEffect.Haze:
                        case PBEMoveEffect.HelpingHand:
                        case PBEMoveEffect.HPDrain__RequireSleep:
                        case PBEMoveEffect.LockOn:
                        case PBEMoveEffect.MagnetRise:
                        case PBEMoveEffect.Metronome:
                        case PBEMoveEffect.MiracleEye:
                        case PBEMoveEffect.Nightmare:
                        case PBEMoveEffect.OneHitKnockout:
                        case PBEMoveEffect.PainSplit:
                        case PBEMoveEffect.PowerTrick:
                        case PBEMoveEffect.Protect:
                        case PBEMoveEffect.PsychUp:
                        case PBEMoveEffect.Psywave:
                        case PBEMoveEffect.QuickGuard:
                        case PBEMoveEffect.RainDance:
                        case PBEMoveEffect.ReflectType:
                        case PBEMoveEffect.Refresh:
                        case PBEMoveEffect.RolePlay:
                        case PBEMoveEffect.Sandstorm:
                        case PBEMoveEffect.SeismicToss:
                        case PBEMoveEffect.Selfdestruct:
                        case PBEMoveEffect.SetDamage:
                        case PBEMoveEffect.SimpleBeam:
                        case PBEMoveEffect.Sketch:
                        case PBEMoveEffect.Snore:
                        case PBEMoveEffect.Soak:
                        case PBEMoveEffect.Spikes:
                        case PBEMoveEffect.StealthRock:
                        case PBEMoveEffect.SuckerPunch:
                        case PBEMoveEffect.SunnyDay:
                        case PBEMoveEffect.SuperFang:
                        case PBEMoveEffect.Tailwind:
                        case PBEMoveEffect.ToxicSpikes:
                        case PBEMoveEffect.Transform:
                        case PBEMoveEffect.TrickRoom:
                        case PBEMoveEffect.Whirlwind:
                        case PBEMoveEffect.WideGuard:
                        case PBEMoveEffect.WorrySeed:
                        {
                            // TODO
                            break;
                        }

                        default: throw new ArgumentOutOfRangeException(nameof(IPBEMoveData.Effect));
                        }
                    }
                    possibleActions.Add((new PBETurnAction(user, move, possibleTarget), score));
                }
            }
            if (user.CanSwitchOut())
            {
                PBEBattlePokemon[] availableForSwitch = trainer.Party.Except(standBy).Where(p => p.FieldPosition == PBEFieldPosition.None && p.HP > 0).ToArray();
                for (int s = 0; s < availableForSwitch.Length; s++) // Score switches
                {
                    PBEBattlePokemon switchPkmn = availableForSwitch[s];
                    // TODO: Entry hazards
                    // TODO: Known moves of active battlers
                    // TODO: Type effectiveness
                    double score = -10d;
                    possibleActions.Add((new PBETurnAction(user, switchPkmn), score));
                }
            }

            string ToDebugString((PBETurnAction Action, double Score) t)
            {
                string str = "{";

                if (t.Action.Decision == PBETurnDecision.Fight)
                {
                    str += string.Format("Fight {0} {1}", t.Action.FightMove, t.Action.FightTargets);
                }
                else
                {
                    str += string.Format("Switch {0}", trainer.TryGetPokemon(t.Action.SwitchPokemonId).Nickname);
                }
                str += " [" + t.Score + "]}";
                return(str);
            }

            IOrderedEnumerable <(PBETurnAction Action, double Score)> byScore = possibleActions.OrderByDescending(t => t.Score);

            Debug.WriteLine("{0}'s possible actions: {1}", user.Nickname, byScore.Select(t => ToDebugString(t)).Print());
            double bestScore = byScore.First().Score;

            return(PBEDataProvider.GlobalRandom.RandomElement(byScore.Where(t => t.Score == bestScore).ToArray()).Action); // Pick random action of the ones that tied for best score
        }
        public static PBETurnTarget GetSpreadMoveTargets(PBEBattlePokemon pkmn, PBEMoveTarget targets)
        {
            switch (pkmn.Battle.BattleFormat)
            {
            case PBEBattleFormat.Single:
            {
                switch (targets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETurnTarget.AllyCenter | PBETurnTarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETurnTarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETurnTarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            case PBEBattleFormat.Double:
            {
                switch (targets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyLeft | PBETurnTarget.AllyRight | PBETurnTarget.FoeLeft | PBETurnTarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.FoeLeft | PBETurnTarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyLeft | PBETurnTarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETurnTarget.AllyRight | PBETurnTarget.FoeLeft | PBETurnTarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyLeft | PBETurnTarget.FoeLeft | PBETurnTarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            case PBEBattleFormat.Triple:
            {
                switch (targets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyLeft | PBETurnTarget.AllyCenter | PBETurnTarget.AllyRight | PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoesSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETurnTarget.AllyCenter | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETurnTarget.AllyLeft | PBETurnTarget.AllyRight | PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyCenter | PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyLeft | PBETurnTarget.AllyCenter | PBETurnTarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            case PBEBattleFormat.Rotation:
            {
                switch (targets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyCenter | PBETurnTarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETurnTarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            default: throw new ArgumentOutOfRangeException(nameof(pkmn.Battle.BattleFormat));
            }
        }
Esempio n. 10
0
        public static PBETurnTarget[] GetPossibleTargets(PBEBattlePokemon pkmn, PBEMoveTarget targets)
        {
            switch (pkmn.Battle.BattleFormat)
            {
            case PBEBattleFormat.Single:
            {
                switch (targets)
                {
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.FoeCenter });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            case PBEBattleFormat.Double:
            {
                switch (targets)
                {
                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.Self:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.FoeLeft, PBETurnTarget.FoeRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyRight, PBETurnTarget.FoeLeft, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.FoeLeft, PBETurnTarget.FoeRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            case PBEBattleFormat.Triple:
            {
                switch (targets)
                {
                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.Self:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyCenter });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyCenter, PBETurnTarget.AllyRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter, PBETurnTarget.AllyRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleNotSelf:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter, PBETurnTarget.AllyRight, PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyRight, PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyCenter, PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter, PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyLeft, PBETurnTarget.AllyRight, PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter, PBETurnTarget.FoeRight });
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter, PBETurnTarget.FoeLeft, PBETurnTarget.FoeCenter });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            case PBEBattleFormat.Rotation:
            {
                switch (targets)
                {
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.FoeCenter });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(new PBETurnTarget[] { PBETurnTarget.AllyCenter });
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(targets));
                }
            }

            default: throw new ArgumentOutOfRangeException(nameof(pkmn.Battle.BattleFormat));
            }
        }
Esempio n. 11
0
        static PBETarget DecideTargets(PBEPokemon pkmn, PBEMove move)
        {
            PBEMoveTarget possibleTargets = pkmn.GetMoveTargets(move);

            switch (pkmn.Team.Battle.BattleFormat)
            {
            case PBEBattleFormat.Single:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.AllyCenter | PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.None);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            case PBEBattleFormat.Double:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyLeft | PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.FoeLeft | PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyLeft | PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyLeft | PBETarget.FoeLeft | PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.Self:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.AllyLeft);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SelfOrAllySurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else
                        {
                            return(PBETarget.AllyRight);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.AllyRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyLeft);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleFoeSurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        int val = PBEUtils.RNG.Next(0, 3);
                        if (val == 0)
                        {
                            return(PBETarget.AllyRight);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        int val = PBEUtils.RNG.Next(0, 3);
                        if (val == 0)
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.None);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            case PBEBattleFormat.Triple:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyLeft | PBETarget.AllyCenter | PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoesSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.FoeCenter | PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.FoeLeft | PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.AllyCenter | PBETarget.FoeCenter | PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.AllyLeft | PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyCenter | PBETarget.FoeLeft | PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyLeft | PBETarget.AllyCenter | PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.Self:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.AllyLeft);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(PBETarget.AllyCenter);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SelfOrAllySurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else
                        {
                            return(PBETarget.AllyCenter);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        int val = PBEUtils.RNG.Next(0, 3);
                        if (val == 0)
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.AllyCenter);
                        }
                        else
                        {
                            return(PBETarget.AllyRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.AllyCenter);
                        }
                        else
                        {
                            return(PBETarget.AllyRight);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleAllySurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(PBETarget.AllyCenter);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else
                        {
                            return(PBETarget.AllyRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleFoeSurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        int val = PBEUtils.RNG.Next(0, 3);
                        if (val == 0)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        if (PBEUtils.RNG.NextBoolean())
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else
                        {
                            return(PBETarget.FoeCenter);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleNotSelf:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        int val = PBEUtils.RNG.Next(0, 5);
                        if (val == 0)
                        {
                            return(PBETarget.AllyCenter);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.AllyRight);
                        }
                        else if (val == 2)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else if (val == 3)
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        int val = PBEUtils.RNG.Next(0, 5);
                        if (val == 0)
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.AllyRight);
                        }
                        else if (val == 2)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else if (val == 3)
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        int val = PBEUtils.RNG.Next(0, 5);
                        if (val == 0)
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.AllyCenter);
                        }
                        else if (val == 2)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else if (val == 3)
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleSurrounding:             // TODO
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        int val = PBEUtils.RNG.Next(0, 3);
                        if (val == 0)
                        {
                            return(PBETarget.AllyCenter);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        int val = PBEUtils.RNG.Next(0, 5);
                        if (val == 0)
                        {
                            return(PBETarget.AllyLeft);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.AllyRight);
                        }
                        else if (val == 2)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else if (val == 3)
                        {
                            return(PBETarget.FoeCenter);
                        }
                        else
                        {
                            return(PBETarget.FoeRight);
                        }
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        int val = PBEUtils.RNG.Next(0, 3);
                        if (val == 0)
                        {
                            return(PBETarget.AllyCenter);
                        }
                        else if (val == 1)
                        {
                            return(PBETarget.FoeLeft);
                        }
                        else
                        {
                            return(PBETarget.FoeCenter);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.None);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            case PBEBattleFormat.Rotation:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyCenter | PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(PBETarget.None);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            default: throw new ArgumentOutOfRangeException(nameof(pkmn.Team.Battle.BattleFormat));
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Determines whether chosen targets are valid for a given move.
        /// </summary>
        /// <param name="pkmn">The Pokémon that will act.</param>
        /// <param name="move">The move the Pokémon wishes to use.</param>
        /// <param name="targets">The targets bitfield to validate.</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="targets"/>, <paramref name="move"/>, <paramref name="pkmn"/>'s <see cref="PBEPokemon.FieldPosition"/>, or <paramref name="pkmn"/>'s <see cref="PBEBattle"/>'s <see cref="BattleFormat"/> is invalid.</exception>
        public static bool AreTargetsValid(PBEPokemon pkmn, PBEMove move, PBETarget targets)
        {
            if (move == PBEMove.None || move >= PBEMove.MAX)
            {
                throw new ArgumentOutOfRangeException(nameof(move));
            }
            PBEMoveTarget possibleTargets = pkmn.GetMoveTargets(move);

            switch (pkmn.Team.Battle.BattleFormat)
            {
            case PBEBattleFormat.Single:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == (PBETarget.AllyCenter | PBETarget.FoeCenter));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(true);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            case PBEBattleFormat.Double:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyLeft | PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.FoeLeft | PBETarget.FoeRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyLeft | PBETarget.AllyRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == (PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeRight));
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyLeft | PBETarget.FoeLeft | PBETarget.FoeRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.Self:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyLeft);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyLeft);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.FoeLeft || targets == PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyRight || targets == PBETarget.FoeLeft || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.FoeLeft || targets == PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(true);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            case PBEBattleFormat.Triple:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyLeft | PBETarget.AllyCenter | PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoesSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == (PBETarget.FoeCenter | PBETarget.FoeRight));
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == (PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight));
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.FoeLeft | PBETarget.FoeCenter));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == (PBETarget.AllyCenter | PBETarget.FoeCenter | PBETarget.FoeRight));
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == (PBETarget.AllyLeft | PBETarget.AllyRight | PBETarget.FoeLeft | PBETarget.FoeCenter | PBETarget.FoeRight));
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyCenter | PBETarget.FoeLeft | PBETarget.FoeCenter));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyLeft | PBETarget.AllyCenter | PBETarget.AllyRight));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.Self:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyLeft);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.AllyCenter);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyCenter);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyCenter || targets == PBETarget.AllyRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyCenter || targets == PBETarget.AllyRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyCenter);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleNotSelf:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyCenter || targets == PBETarget.AllyRight || targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyRight || targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyCenter || targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left)
                    {
                        return(targets == PBETarget.AllyCenter || targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                    {
                        return(targets == PBETarget.AllyLeft || targets == PBETarget.AllyRight || targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter || targets == PBETarget.FoeRight);
                    }
                    else if (pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyCenter || targets == PBETarget.FoeLeft || targets == PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(true);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            case PBEBattleFormat.Rotation:
            {
                switch (possibleTargets)
                {
                case PBEMoveTarget.All:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == (PBETarget.AllyCenter | PBETarget.FoeCenter));
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllFoes:
                case PBEMoveTarget.AllFoesSurrounding:
                case PBEMoveTarget.AllSurrounding:
                case PBEMoveTarget.SingleFoeSurrounding:
                case PBEMoveTarget.SingleNotSelf:
                case PBEMoveTarget.SingleSurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.FoeCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.AllTeam:
                case PBEMoveTarget.Self:
                case PBEMoveTarget.SelfOrAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(targets == PBETarget.AllyCenter);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                case PBEMoveTarget.RandomFoeSurrounding:
                case PBEMoveTarget.SingleAllySurrounding:
                {
                    if (pkmn.FieldPosition == PBEFieldPosition.Left || pkmn.FieldPosition == PBEFieldPosition.Center || pkmn.FieldPosition == PBEFieldPosition.Right)
                    {
                        return(true);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(pkmn.FieldPosition));
                    }
                }

                default: throw new ArgumentOutOfRangeException(nameof(possibleTargets));
                }
            }

            default: throw new ArgumentOutOfRangeException(nameof(pkmn.Team.Battle.BattleFormat));
            }
        }