Package org.pokenet.server.battle

Examples of org.pokenet.server.battle.BattleField$PokemonWrapper


   
    /**
     * Return whether the move hit.
     */
    public boolean attemptHit(PokemonMove move, Pokemon user, Pokemon target) {
        BattleField field = user.getField();
        double accuracy = move.getAccuracy();
        boolean hit;
        if ((accuracy != 0.0)
                && (user.hasAbility("No Guard") || target.hasAbility("No Guard") ||
                       user.hasEffect(MoveList.LockOnEffect.class))
                ) {
            hit = true;
        } else {
            double effective = (accuracy
                    * user.getAccuracy().getMultiplier())
                    / target.getEvasion().getMultiplier();
            if (effective > 1.0) effective = 1.0;

            hit = (field.getRandom().nextDouble() <= effective);
        }
        if (!hit) {
            field.showMessage(user.getName() + "'s attack missed!");
        }
        return hit;
    }
View Full Code Here


   
    public strictfp int calculateDamage(
            PokemonMove move,
            Pokemon attacker, Pokemon defender, boolean silent) {
       
        final BattleField field = attacker.getField();
        PokemonType moveType = move.getType();
        final boolean special = isMoveSpecial(move);
       
        boolean isCritical = move.canCriticalHit() &&
                isCriticalHit(move, attacker, defender);
       
        double attack = attacker.getStat(special
            ? Pokemon.S_SPATTACK
            : Pokemon.S_ATTACK);
       
        int defStat = special
            ? Pokemon.S_SPDEFENCE
            : Pokemon.S_DEFENCE;
       
        StatMultiplier mul = defender.getMultiplier(defStat);
        double defMultiplier = mul.getMultiplier();
        if (isCritical && (defMultiplier > 1.0)) {
            defMultiplier = mul.getSecondaryMultiplier();
        }
        double defence = defender.getStat(defStat, defMultiplier);
       
        final int random = field.getRandom().nextInt(16) + 85;
       
        double multiplier = move.getEffectiveness(attacker, defender);
       
        if (multiplier > 1.0) {
            if (!silent) {
                field.showMessage("It's super effective!");
            }
        } else if (multiplier == 0.0) {
            if (!silent) {
                field.showMessage("It doesn't affect " + defender.getName() + "...");
            }
            // Just return now to prevent a critical hit from occurring.
            return 0;
        } else if (multiplier < 1.0) {
            if (!silent) {
                field.showMessage("It's not very effective...");
            }
        }
       
        final boolean stab = attacker.isType(moveType);
        double stabFactor = attacker.hasAbility("Adaptability") ? 2.0 : 1.5;
       
        int damage = (int)(((int)((int)(((int)((2 * attacker.getLevel()) / 5.0 + 2.0)
        * attack
        * move.getPower())
        / defence)
        / 50.0)
        + 2)
        * (random / 100.0)
        * (stab ? stabFactor : 1.0)
        * multiplier);
       
        if (isCritical) {
            damage *= attacker.hasAbility("Sniper") ? 3 : 2;
            if (defender.hasAbility("Anger Point")) {
                if (!silent) {
                    field.showMessage(defender.getName()
                            + "'s Anger Point raised its attack!");
                }
                StatChangeEffect eff = new StatChangeEffect(
                        Pokemon.S_ATTACK,true, 12);
                eff.setDescription(null);
                defender.addStatus(defender, eff);
            }
            if (!silent) {
                field.showMessage("A critical hit!");
            }
        }
       
        return ((damage < 1) ? 1 : damage);
    }
View Full Code Here

        new PokemonMove(PokemonType.T_GROUND, 0, 1.0, 20) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        BattleField field = user.getField();
        SpikesEffect spikes = SpikesEffect.getSpikes(field, SpikesEffect.class);
        if (spikes == null) {
          spikes = new SpikesEffect();
          field.applyEffect(spikes);
        }
        spikes.addSpikes(target);
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Rapid Spin",
        new PokemonMove(PokemonType.T_NORMAL, 20, 1.0, 40) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (getEffectiveness(user, target) == 0.0) {
          user.getField().showMessage("It doesn't affect "
              + target.getName() + "...");
          return 0;
        }
        if (user.hasEffect(RestrainingEffect.class) || user.hasEffect(LeechSeedEffect.class)) {
          user.removeStatus(RestrainingEffect.class);
          user.removeStatus(LeechSeedEffect.class);
          user.getField().showMessage(user.getName() + " was released!");
        }
        ArrayList<FieldEffect> spikes = user.getField().getEffectsByType(SpikesEffect.class);
        Iterator<FieldEffect> i = spikes.iterator();
        boolean blewAway = false;
        while (i.hasNext()) {
          SpikesEffect eff = (SpikesEffect)i.next();
          if (eff != null && eff.getLayers(user) >= 1) {
            eff.removeSpikes(user);
            blewAway = true;
          }
        }
        if (blewAway) {
          user.getField().showMessage(user.getName() + " blew away the spikes!");
        }
        return super.use(mech, user, target);                 
      }
    }
    ));

    m_moves.add(new MoveListEntry("Charge", new StatusMove(
        PokemonType.T_ELECTRIC, 0, 1.0, 20, new StatusEffect[] {
            new StatusEffect() {
              private int m_turns = 2;
              public String getName() {
                return "Charge";
              }
              public boolean apply(Pokemon p) {
                if (p.getField().getMechanics() instanceof JewelMechanics) {
                  p.addStatus(p, new StatChangeEffect(Pokemon.S_SPDEFENCE, true, 1));
                }
                return true;
              }
              //tier is not very important
              public int getTier() {
                return 1;
              }
              public String getDescription() {
                return " is charging power!";
              }
              public boolean tick(Pokemon p) {
                if (--m_turns <= 0) {
                  p.removeStatus(this);
                  return true;
                }
                return false;
              }
              public boolean isMoveTransformer(boolean enemy) {
                return !enemy;
              }
              public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
                PokemonMove move = entry.getMove();
                if (move.getType().equals(PokemonType.T_ELECTRIC)) {
                  int power = move.getPower();
                  move.setPower(power * 2);
                }
                return entry;
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Rest",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 10) {
      public boolean attemptHit(BattleMechanics mech, Pokemon source, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (user.hasAbility("Insomnia")
            || user.hasAbility("Vital Spirit")
            || user.hasEffect(SleepEffect.class)
            || (user.getHealth() == user.getStat(Pokemon.S_HP))) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        user.removeStatus(StatusEffect.SPECIAL_EFFECT_LOCK);
        // The turn it is applied still counts as a turn
        user.addStatus(user, new SleepEffect(3));                   
        int change = user.getStat(Pokemon.S_HP) - user.getHealth();
        user.changeHealth(change);
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Reflect",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!user.getField().applyEffect(new StatCutEffect(Pokemon.S_DEFENCE,
            user.getParty(), "reflect"))) {
          user.getField().showMessage("But it failed!");
        }
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Light Screen",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!user.getField().applyEffect(new StatCutEffect(Pokemon.S_SPDEFENCE,
            user.getParty(), "light screen"))) {
          user.getField().showMessage("But it failed!");
        }
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Brick Break",
        new PokemonMove(PokemonType.T_FIGHTING, 75, 1.0, 15) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        ArrayList<FieldEffect> effects = user.getField().getEffectsByType(StatCutEffect.class);
        Iterator<FieldEffect> i = effects.iterator();
        while (i.hasNext()) {
          StatCutEffect eff = (StatCutEffect)i.next();
          if (eff.getParty() == target.getParty()) {
            user.getField().removeEffect(eff);
            user.getField().showMessage("The wall shattered!");
          }
        }
        return super.use(mech, user, target);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Camouflage", new StatusMove(
        PokemonType.T_NORMAL, 0, 1.0, 20, new StatusEffect[] {
            new StatusEffect() {
              private PokemonType[] types;

              public String getName() {
                return "Camouflage";
              }
              public String getDescription() {
                return null;
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean apply(Pokemon p) {
                types = p.getTypes();

                //todo: this should be based on the terrain but it isn't implemented yet
                PokemonType type = PokemonType.T_NORMAL;

                p.setType(new PokemonType[] { type });
                p.getField().showMessage(p.getName() + " became the "
                    + type + " type!");
                return true;
              }
              public boolean switchOut(Pokemon p) {
                p.setType(types);
                return true;
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    ) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }));

    m_moves.add(new MoveListEntry("Nature Power",
        new PokemonMove(PokemonType.T_NORMAL, 0, 0.95, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        //todo: this should also be based on terrain
        if (mech instanceof JewelMechanics) {
          return user.useMove(getMove("Swift"), target);
        } else {
          return user.useMove(getMove("Tri Attack"), target);
        }
      }
      public boolean isAttack() {
        return false;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Secret Power",
        new PokemonMove(PokemonType.T_NORMAL, 70, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int damage = mech.calculateDamage(this, user, target);
        target.changeHealth(-damage);

        double random = mech.getRandom().nextDouble();
        //todo: this should also be based on terrain
        if (random <= 0.3) {
          target.addStatus(user, new ParalysisEffect());
        }
        return damage;
      }
    }
    ));

    //Doesn't do anything in 1 vs 1
    m_moves.add(new MoveListEntry("Follow Me",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().showMessage(user.getName() + " became the centre of attention!");
        return 0;
      }
      public int getPriority() {
        return 4;
      }
    }
    ));

    //Doesn't do anything in 1 vs 1
    m_moves.add(new MoveListEntry("Helping Hand",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().showMessage("But it failed!");
        return 0;
      }
      public int getPriority() {
        return 6;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Doom Desire",
        new PokemonMove(PokemonType.T_STEEL, 120, 0.85, 5) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int damage;
        if (!super.attemptHit(mech, user, target)) {
          damage = 0;
        } else {
          PokemonMove move = new PokemonMove(PokemonType.T_TYPELESS, this.getPower(), 1.0, 1);
          move.setMoveListEntry(getMoveListEntry());
          damage = mech.calculateDamage(move, user, target);
        }

        user.getField().applyEffect(
            new DelayedDamageEffect(damage, target.getParty(), 3));
        return 0;                   
      }
    }
    ));

    m_moves.add(new MoveListEntry("Future Sight",
        new PokemonMove(PokemonType.T_PSYCHIC, 80, 0.9, 15) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int damage;
        if (!super.attemptHit(mech, user, target)) {
          damage = 0;
        } else {
          damage = mech.calculateDamage(
              new PokemonMove(PokemonType.T_TYPELESS, this.getPower(), 1.0, 1), user, target);
        }

        user.getField().applyEffect(
            new DelayedDamageEffect(damage, target.getParty(), 3));
        return 0;                   
      }
    }
    ));

    m_moves.add(new MoveListEntry("Focus Punch",
        new DamageListenerMove(PokemonType.T_FIGHTING, 150, 1.0, 20) {          
      public void beginTurn(BattleTurn[] turn, int index, Pokemon source) {
        if (!source.hasEffect(SleepEffect.class) && !source.hasEffect(FreezeEffect.class)) {
          source.getField().showMessage(source.getName() + " is tightening its focus!");
        }
        super.beginTurn(turn, index, source);
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        DamageListenerEffect listener = getListener(user);
        if (listener == null) return 0;
        if (listener.getDamage() > 0) {
          user.getField().showMessage(user.getName() + " lost its focus and couldn't move!");
          return 0;
        }
        return super.use(mech, user, target);
      }
      public int getPriority() {
        return -2;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Low Kick",
        new MassBasedMove(PokemonType.T_FIGHTING, 1.0, 20)));

    m_moves.add(new MoveListEntry("Baton Pass",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 40) {
      @SuppressWarnings("unchecked")
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        BattleField field = user.getField();
        int party = user.getParty();
        if (field.getAliveCount(party) == 1) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        List<StatusEffect> list = user.getNormalStatuses(0);
        List applied = new ArrayList();
        Iterator<StatusEffect>  i = list.iterator();
        while (i.hasNext()) {
          StatusEffect effect = (StatusEffect)i.next();
          if (effect.getLock() != StatusEffect.SPECIAL_EFFECT_LOCK) {
            if (effect.isPassable()) {
              if (effect instanceof LeechSeedEffect) {
                applied.add(new LeechSeedEffect(false));
              } else if (effect instanceof PerishSongEffect) {
                applied.add(new PerishSongEffect(false));
              } else {
                applied.add(effect.clone());
              }
              if (effect instanceof CoEffect) {
                CoEffect coeffect = (CoEffect)effect;
                if (!coeffect.getType().equals(AttractEffect.class)) {
                  effect.disable();
                }
              }
            }
          }
        }
        int substitute = user.getSubstitute();
        field.requestAndWaitForSwitch(party);
        target = field.getActivePokemon()[party];
        target.setSubstitute(substitute);
        i = applied.iterator();
        field.setNarrationEnabled(false);
        while (i.hasNext()) {
          StatusEffect effect = (StatusEffect)i.next();
          target.addStatus(target, effect);
        }
        field.setNarrationEnabled(true);
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon source, Pokemon target) {
        return true;
      }
    }));

    PokemonMove roar = new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.hasAbility("Suction Cups") || target.hasEffect(IngrainEffect.class)) {
          user.getField().showMessage("But it failed!");
          return 0;
        }

        if (target.isFainted())
          return 0;

        ArrayList<Pokemon> party = new ArrayList<Pokemon>(Arrays.asList(target.getTeammates()));
        Iterator<Pokemon> i = party.iterator();
        while (i.hasNext()) {
          Pokemon p = (Pokemon)i.next();
          if (p == null || p.isFainted() || (p == target)) {
            i.remove();
          }
        }
        if (party.size() == 0) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        Pokemon p = (Pokemon)party.get(mech.getRandom().nextInt(party.size()));
        p.getField().switchInPokemon(p.getParty(), p.getId());
        p.addStatus(user, new StatusEffect() {
          public int getTier() {
            return 1;
          }
          public boolean tick(Pokemon p) {
            p.removeStatus(this);
            return true;
          }
          public boolean isMoveTransformer(boolean enemy) {
            return !enemy;
          }
          public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
            return null;
          }
          public String getDescription() {
            return null;
          }
          public String getName() {
            return null;
          }
        });
        return 0;
      }
      public int getPriority() {
        return -5;
      }

    };

    PokemonMove whirlwind = (PokemonMove)roar.clone();
    m_moves.add(new MoveListEntry("Roar", roar));
    m_moves.add(new MoveListEntry("Whirlwind", whirlwind));

    m_moves.add(new MoveListEntry("Wish",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().applyEffect(new DelayedStatusEffect(
            new PercentEffect(0.5, false, -1, "The wish came true!"),
            user.getParty(), 2, " made a wish!"));
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Counter",
        new CounterMove(PokemonType.T_FIGHTING, 1.0, 20, 2)));
    m_moves.add(new MoveListEntry("Mirror Coat",
        new CounterMove(PokemonType.T_PSYCHIC, 1.0, 20, 1)));

    m_moves.add(new MoveListEntry("Pursuit",
        new PokemonMove(PokemonType.T_DARK, 40, 1.0, 20) {
      public void beginTurn(BattleTurn[] turn, int index, Pokemon source) {
        // Note: assumes two pokemon.
        BattleTurn opp = turn[1 - index];
        Pokemon target = source.getOpponent();
        boolean damageNow = false;
        if (!opp.isMoveTurn()) {
          damageNow = true;
        } else {
          MoveListEntry entry = target.getMove(opp.getId());
          if (entry.getName().equals("U-turn")) {
            if (target.getStat(Pokemon.S_SPEED) > source.getStat(Pokemon.S_SPEED)) {
              damageNow = true;
            }
          }
        }

        if (!damageNow)
          return;

        // Prevent this attack from occurring later in the turn.
        turn[index] = null;

        if (source.isImmobilised(null))
          return;

        int power = getPower();
        setPower(power * 2);
        source.useMove(new MoveListEntry("Pursuit", (PokemonMove)clone()), target);
        setPower(power);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Revenge",
        new DamageListenerMove(PokemonType.T_FIGHTING, 60, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        DamageListenerEffect listener = getListener(user);
        if (listener == null) return 0;
        if (listener.getDamage() <= 0) {
          return super.use(mech, user, target);
        }
        int power = 60;
        setPower(power * 2);
        int damage = super.use(mech, user, target);
        setPower(power);
        return damage;
      }
      public int getPriority() {
        return -3;
      }
    }
    ));

    /********************************************************************
     * DP moves start
     ********************************************************************/

    m_moves.add(new MoveListEntry("U-turn",
        new PokemonMove(PokemonType.T_BUG, 70, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int damage = mech.calculateDamage(this, user, target);
        target.changeHealth(-damage);

        int party = user.getParty();
        BattleField field = user.getField();
        if (field.getAliveCount(party) > 1) {
          field.requestAndWaitForSwitch(party);
          target = field.getActivePokemon()[party];
          HoldItem item = target.getItem();
          if (item instanceof ChoiceBandItem) {
            for (int i = 0; i < 4; ++i) {
              MoveListEntry entry = target.getMove(i);
              if ((entry != null) && entry.getName().equals("U-turn")) {
                ((ChoiceBandItem)item).setChoice(target, mech, entry);
                break;
              }
            }
          }
        }
        return damage;
      }
    }));

    m_moves.add(new MoveListEntry("Lunar Dance",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int party = user.getParty();
        BattleField field = user.getField();
        if (field.getAliveCount(party) == 1) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        user.faint();
        field.requestAndWaitForSwitch(party);
        target = field.getActivePokemon()[party];
        target.changeHealth(target.getStat(Pokemon.S_HP));
        for (int i = 0; i < 4; ++i) {
          MoveListEntry entry = target.getMove(i);
          if (entry != null) {
            PokemonMove move = entry.getMove();
            if (move != null) {
              target.setPp(i, target.getMaxPp(i));
            }
          }
        }
        target.removeStatus(StatusEffect.SPECIAL_EFFECT_LOCK);
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon source, Pokemon target) {
        return true;
      }
    }));

    m_moves.add(new MoveListEntry("Worry Seed",
        new PokemonMove(PokemonType.T_GRASS, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.hasAbility("Multitype") || target.hasSubstitute()) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        target.setAbility(IntrinsicAbility.getInstance("Insomnia"), false);
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Psycho Shift",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.hasSubstitute()) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        StatusEffect eff = user.getEffect(StatusEffect.SPECIAL_EFFECT_LOCK);
        if (eff == null)
          return 0;
        StatusEffect clone = (StatusEffect)eff.clone();
        if (!target.hasEffect(StatusEffect.SPECIAL_EFFECT_LOCK)) {
          user.removeStatus(eff);
          target.addStatus(user, clone);
        }
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Trick Room",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 5) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        BattleField field = user.getField();
        FieldEffect effect = field.getEffectByType(SpeedSwapEffect.class);
        if (effect != null) {
          field.removeEffect(effect);
        } else {
          field.showMessage(user.getName() + " twisted the dimensions!");
          field.applyEffect(new SpeedSwapEffect());
        }
        return 0;
      }
      public int getPriority() {
        return -5;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Gyro Ball",
        new PokemonMove(PokemonType.T_STEEL, 100, 1.0, 5) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int power = 51 * target.getStat(Pokemon.S_SPEED) /
        user.getStat(Pokemon.S_SPEED) / 2;
        if (power > 150) power = 150;
        setPower(getPower() * power / 100);
        int damage = mech.calculateDamage(this, user, target);
        target.changeHealth(-damage);
        setPower(100);
        return damage;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Wake-up Slap",
        new PokemonMove(PokemonType.T_FIGHTING, 60, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int power = getPower();
        if (!target.hasSubstitute() && target.hasEffect(SleepEffect.class)) {
          setPower(2 * power);
          target.removeStatus(StatusEffect.SPECIAL_EFFECT_LOCK);
          user.getField().showMessage(target.getName() + " woke up!");
        }
        int damage = mech.calculateDamage(this, user, target);
        setPower(power);
        target.changeHealth(-damage);
        return damage;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Hammer Arm", new StatusMove(
        PokemonType.T_FIGHTING, 100, 0.9, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPEED, false)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Brine",
        new PokemonMove(PokemonType.T_WATER, 65, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int power = getPower();
        if (target.getHealth() < (target.getStat(Pokemon.S_HP) / 2)) {
          setPower(power * 2);
        }
        int damage = super.use(mech, user, target);
        setPower(power);
        return damage;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Acupressure",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 30) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int random = mech.getRandom().nextInt(7) + 1;
        user.addStatus(user, new StatChangeEffect(random, true, 2));
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Close Combat", new StatusMove(
        PokemonType.T_FIGHTING, 120, 1.0, 5, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_DEFENCE, false),
            new StatChangeEffect(Pokemon.S_SPDEFENCE, false)
        },
        new boolean[] { true, true },
        new double[] { 1.0, 1.0 }
    )));

    //todo: get right tier   
    m_moves.add(new MoveListEntry("Aqua Ring", new StatusMove(
        PokemonType.T_WATER, 0, 1.0, 20, new StatusEffect[] {
            new PercentEffect(0.0625, false, 3, "'s Aqua Ring restored health!") {
              public boolean isSingleton() {
                return true;
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    //todo: find correct rate for all of these
    m_moves.add(new MoveListEntry("Flare Blitz",
        new RecoilMove(PokemonType.T_FIRE, 120, 1.0, 15, 1.0/3.0)));

    m_moves.add(new MoveListEntry("Brave Bird",
        new RecoilMove(PokemonType.T_FLYING, 120, 1.0, 15, 1.0/3.0)));

    m_moves.add(new MoveListEntry("Wood Hammer",
        new RecoilMove(PokemonType.T_GRASS, 120, 1.0, 15, 1.0/3.0)));

    m_moves.add(new MoveListEntry("Head Smash",
        new RecoilMove(PokemonType.T_ROCK, 150, 0.8, 5, 0.5)));

    m_moves.add(new MoveListEntry("Force Palm", new StatusMove(
        PokemonType.T_FIGHTING, 60, 1.0, 10, new StatusEffect[] {
            new ParalysisEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Aura Sphere",
        new PerfectAccuracyMove(PokemonType.T_FIGHTING, 90, 20)));

    m_moves.add(new MoveListEntry("Magnet Bomb",
        new PerfectAccuracyMove(PokemonType.T_STEEL, 60, 20)));

    m_moves.add(new MoveListEntry("Rock Polish", new StatusMove(
        PokemonType.T_ROCK, 0, 1.0, 30, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPEED, true, 2)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Poison Jab", new StatusMove(
        PokemonType.T_POISON, 80, 1.0, 20, new StatusEffect[] {
            new PoisonEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Dark Pulse", new StatusMove(
        PokemonType.T_DARK, 80, 1.0, 15, new StatusEffect[] {
            new FlinchEffect()
        },
        new boolean[] { false },
        new double[] { 0.2 }
    )));

    m_moves.add(new MoveListEntry("Night Slash",
        new HighCriticalHitMove(PokemonType.T_DARK, 70, 1.0, 15)));

    m_moves.add(new MoveListEntry("Shadow Claw",
        new HighCriticalHitMove(PokemonType.T_GHOST, 70, 1.0, 15)));

    m_moves.add(new MoveListEntry("Psycho Cut",
        new HighCriticalHitMove(PokemonType.T_PSYCHIC, 70, 1.0, 20)));

    m_moves.add(new MoveListEntry("Stone Edge",
        new HighCriticalHitMove(PokemonType.T_ROCK, 100, 0.8, 5)));

    m_moves.add(new MoveListEntry("Attack Order",
        new HighCriticalHitMove(PokemonType.T_BUG, 90, 1.0, 15)));

    m_moves.add(new MoveListEntry("Spacial Rend",
        new HighCriticalHitMove(PokemonType.T_DRAGON, 100, 0.95, 5)));

    m_moves.add(new MoveListEntry("Aqua Tail",
        new PokemonMove(PokemonType.T_WATER, 90, 0.9, 10)));

    m_moves.add(new MoveListEntry("Seed Bomb",
        new PokemonMove(PokemonType.T_GRASS, 80, 1.0, 15)));

    m_moves.add(new MoveListEntry("X-Scissor",
        new PokemonMove(PokemonType.T_BUG, 80, 1.0, 15)));

    m_moves.add(new MoveListEntry("Dragon Pulse",
        new PokemonMove(PokemonType.T_DRAGON, 90, 1.0, 10)));

    m_moves.add(new MoveListEntry("Power Gem",
        new PokemonMove(PokemonType.T_ROCK, 70, 1.0, 20)));

    m_moves.add(new MoveListEntry("Power Whip",
        new PokemonMove(PokemonType.T_GRASS, 120, 0.85, 10)));

    m_moves.add(new MoveListEntry("Air Slash", new StatusMove(
        PokemonType.T_FLYING, 75, 0.95, 20, new StatusEffect[] {
            new FlinchEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Zen Headbutt", new StatusMove(
        PokemonType.T_PSYCHIC, 80, 0.9, 15, new StatusEffect[] {
            new FlinchEffect()
        },
        new boolean[] { false },
        new double[] { 0.2 }
    )));

    m_moves.add(new MoveListEntry("Dragon Rush", new StatusMove(
        PokemonType.T_DRAGON, 100, 0.75, 10, new StatusEffect[] {
            new FlinchEffect()
        },
        new boolean[] { false },
        new double[] { 0.2 }
    )));

    m_moves.add(new MoveListEntry("Iron Head", new StatusMove(
        PokemonType.T_STEEL, 80, 1.0, 15, new StatusEffect[] {
            new FlinchEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Bug Buzz", new StatusMove(
        PokemonType.T_BUG, 90, 1.0, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPDEFENCE, false)
        },
        new boolean[] { false },
        new double[] { 0.1 }
    )));

    m_moves.add(new MoveListEntry("Drain Punch",
        new AbsorbMove(PokemonType.T_FIGHTING, 60, 1.0, 5, 0.5)));

    m_moves.add(new MoveListEntry("Vacuum Wave",
        new PriorityMove(PokemonType.T_FIGHTING, 40, 1.0, 30, 1)));

    m_moves.add(new MoveListEntry("Bullet Punch",
        new PriorityMove(PokemonType.T_STEEL, 40, 1.0, 30, 1)));

    m_moves.add(new MoveListEntry("Ice Shard",
        new PriorityMove(PokemonType.T_ICE, 40, 1.0, 30, 1)));

    m_moves.add(new MoveListEntry("Shadow Sneak",
        new PriorityMove(PokemonType.T_GHOST, 40, 1.0, 30, 1)));

    m_moves.add(new MoveListEntry("Aqua Jet",
        new PriorityMove(PokemonType.T_WATER, 40, 1.0, 30, 1)));

    m_moves.add(new MoveListEntry("Focus Blast", new StatusMove(
        PokemonType.T_FIGHTING, 120, 0.7, 5, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPDEFENCE, false)
        },
        new boolean[] { false },
        new double[] { 0.1 }
    )));

    m_moves.add(new MoveListEntry("Energy Ball", new StatusMove(
        PokemonType.T_GRASS, 80, 1.0, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPDEFENCE, false)
        },
        new boolean[] { false },
        new double[] { 0.1 }
    )));

    m_moves.add(new MoveListEntry("Earth Power", new StatusMove(
        PokemonType.T_GROUND, 90, 1.0, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPDEFENCE, false)
        },
        new boolean[] { false },
        new double[] { 0.1 }
    )));

    m_moves.add(new MoveListEntry("Mirror Shot", new StatusMove(
        PokemonType.T_STEEL, 65, 0.85, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_ACCURACY, false)
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Flash Cannon", new StatusMove(
        PokemonType.T_STEEL, 80, 1.0, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPATTACK, false)
        },
        new boolean[] { false },
        new double[] { 0.1 }
    )));

    m_moves.add(new MoveListEntry("Rock Climb", new StatusMove(
        PokemonType.T_NORMAL, 90, 0.85, 20, new StatusEffect[] {
            new ConfuseEffect()
        },
        new boolean[] { false },
        new double[] { 0.2 }
    )));

    m_moves.add(new MoveListEntry("Switcheroo",
        new PokemonMove(PokemonType.T_DARK, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.hasSubstitute()) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        if ((target.hasAbility("Sticky Hold")) || (user.hasAbility("Sticky Hold"))) {
          if (user.hasAbility("Sticky Hold")) {
            user.getField().showMessage(user.getName() + " hung on with its Sticky Hold!");
          }
          if (target.hasAbility("Sticky Hold")) {
            user.getField().showMessage(target.getName() + " hung on with its Sticky Hold!");
          }
          return 0;
        }

        HoldItem targetItem = target.getItem();
        HoldItem item = user.getItem();
        /**if (item == null) {
                        user.getField().showMessage("But it failed!");
                        return 0;
                    }**/

        HoldItem userItem = (item == null) ? null : (HoldItem)item.clone();
        user.setItem(targetItem);
        target.setItem(userItem);
        if (targetItem != null) {
          user.getField().showMessage(user.getName() + " obtained " + targetItem.getName() + "!");
        }
        if (userItem != null) {
          user.getField().showMessage(target.getName() + " obtained " + userItem.getName() + "!");
        }
        return 0;
      }
      public boolean isAttack() {
        return true;
      }
      public boolean isDamaging() {
        return false;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Giga Impact", new StatusMove(
        PokemonType.T_NORMAL, 150, 0.9, 5, new StatusEffect[] {
            new RechargeEffect(1)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Rock Wrecker", new StatusMove(
        PokemonType.T_ROCK, 150, 0.9, 5, new StatusEffect[] {
            new RechargeEffect(1)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Roar Of Time", new StatusMove(
        PokemonType.T_DRAGON, 150, 0.9, 5, new StatusEffect[] {
            new RechargeEffect(1)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Nasty Plot", new StatusMove(
        PokemonType.T_DARK, 0, 1.0, 20, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPATTACK, true, 2)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    //todo: correct probabilities?
    m_moves.add(new MoveListEntry("Thunder Fang", new StatusMove(
        PokemonType.T_ELECTRIC, 65, 0.95, 15, new StatusEffect[] {
            new FlinchEffect(),
            new ParalysisEffect()
        },
        new boolean[] { false, false },
        new double[] { 0.1, 0.1 }
    )));

    m_moves.add(new MoveListEntry("Ice Fang", new StatusMove(
        PokemonType.T_ICE, 65, 0.95, 15, new StatusEffect[] {
            new FlinchEffect(),
            new FreezeEffect()
        },
        new boolean[] { false, false },
        new double[] { 0.1, 0.1 }
    )));

    m_moves.add(new MoveListEntry("Fire Fang", new StatusMove(
        PokemonType.T_FIRE, 65, 0.95, 15, new StatusEffect[] {
            new FlinchEffect(),
            new BurnEffect()
        },
        new boolean[] { false, false },
        new double[] { 0.1, 0.1 }
    )));

    m_moves.add(new MoveListEntry("Mud Bomb", new StatusMove(
        PokemonType.T_GROUND, 65, 0.85, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_ACCURACY, false)
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Defog", new StatusMove(
        PokemonType.T_NORMAL, 0, 1.0, 15, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_EVASION, false)
        },
        new boolean[] { false },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Draco Meteor", new StatusMove(
        PokemonType.T_DRAGON, 140, 0.90, 5, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPATTACK, false, 2)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Leaf Storm", new StatusMove(
        PokemonType.T_GRASS, 140, 0.90, 5, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPATTACK, false, 2)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Discharge", new StatusMove(
        PokemonType.T_ELECTRIC, 80, 1.0, 15, new StatusEffect[] {
            new ParalysisEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Lava Plume", new StatusMove(
        PokemonType.T_FIRE, 80, 1.0, 15, new StatusEffect[] {
            new BurnEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Cross Poison",
        new StatusMove(PokemonType.T_POISON, 70, 1.0, 20, new StatusEffect[] {
            new PoisonEffect()
        },
        new boolean[] { false },
        new double[] { 0.1 }
        ) {
      public boolean hasHighCriticalHitRate() { return true; }
    }
    ));

    m_moves.add(new MoveListEntry("Gunk Shot", new StatusMove(
        PokemonType.T_POISON, 120, 0.7, 5, new StatusEffect[] {
            new PoisonEffect()
        },
        new boolean[] { false },
        new double[] { 0.3 }
    )));

    m_moves.add(new MoveListEntry("Captivate",
        new StatusMove(PokemonType.T_NORMAL, 0, 1.0, 20, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPATTACK, false, 2)
        },
        new boolean[] { false },
        new double[] { 1.0 }
        ) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int userGender = user.getGender();
        int targetGender = target.getGender();
        if ((userGender == targetGender) || (userGender == PokemonSpecies.GENDER_NONE)
            || (targetGender == PokemonSpecies.GENDER_NONE)) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        return super.use(mech, user, target);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Chatter", new StatusMove(
        PokemonType.T_FLYING, 60, 1.0, 20, new StatusEffect[] {
            new ConfuseEffect()
        },
        new boolean[] { false },
        new double[] { 0.31 }
    )));

    m_moves.add(new MoveListEntry("Charge Beam", new StatusMove(
        PokemonType.T_ELECTRIC, 50, 0.9, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPATTACK, true)
        },
        new boolean[] { true },
        new double[] { 0.7 }
    )));

    m_moves.add(new MoveListEntry("Defend Order", new StatusMove(
        PokemonType.T_BUG, 0, 1.0, 10, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_DEFENCE, true),
            new StatChangeEffect(Pokemon.S_SPDEFENCE, true)
        },
        new boolean[] { true, true },
        new double[] { 1.0, 1.0 }
    )));

    m_moves.add(new MoveListEntry("Substitute",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!user.createSubstitute()) {
          user.getField().showMessage("But it failed!");
        } else {
          user.addStatus(user, new SubstituteEffect());
        }
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }));

    m_moves.add(new MoveListEntry("Heal Order", new StatusMove(
        PokemonType.T_BUG, 0, 1.0, 10, new StatusEffect[] {
            new PercentEffect(0.5, false, -1, null)
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Double Hit",
        new PokemonMove(PokemonType.T_NORMAL, 35, 0.9, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int damage = 0;
        for (int i = 0; i < 2; ++i) {
          final int partial = mech.calculateDamage(this, user, target);
          target.changeHealth(-partial);
          damage += partial;
        }
        user.getField().showMessage("Hit 2 time(s)!");
        return damage;
      }
    }
    ));

    PokemonMove crushGrip = new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 5) {
      //todo: this formula may not be exactly correct
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int power = (int)(110.0 *
            (((double)target.getHealth())
                / ((double)target.getStat(Pokemon.S_HP))));

        setPower(power);
        int damage = mech.calculateDamage(this, user, target);
        target.changeHealth(-damage);
        return damage;
      }
      public boolean isAttack() {
        return true;
      }
    };

    PokemonMove wringOut = (PokemonMove)crushGrip.clone();
    m_moves.add(new MoveListEntry("Crush Grip", crushGrip));
    m_moves.add(new MoveListEntry("Wring Out", wringOut));

    m_moves.add(new MoveListEntry("Feint",
        new PokemonMove(PokemonType.T_NORMAL, 50, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!target.hasEffect(CounterEffect.class)) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        return super.use(mech, user, target);                   
      }
    }
    ));

    m_moves.add(new MoveListEntry("Trump Card",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 5) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        //todo: these are estimated values for the powers
        int pp = 5;
        for (int i = 0; i < 4; ++i) {
          MoveListEntry entry = user.getMove(i);
          if (entry == null) continue;
          if (entry.getName().equals("Trump Card")) {
            pp = user.getPp(i);
            break;
          }
        }
        if (pp > 4) {
          setPower(35);
        } else if (pp == 4) {
          setPower(50);
        } else if (pp == 3) {
          setPower(60);
        } else if (pp == 2) {
          setPower(75);
        } else {
          setPower(190);
        }
        int damage = super.use(mech, user, target);
        setPower(0);
        return damage;
      }
      public boolean isAttack() {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Punishment",
        new PokemonMove(PokemonType.T_DARK, 0, 1.0, 5) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int raises = 0;
        List<StatusEffect> statuses = target.getNormalStatuses(0);
        Iterator<StatusEffect> i = statuses.iterator();
        while (i.hasNext()) {
          StatusEffect effect = (StatusEffect)i.next();
          if (!(effect instanceof StatChangeEffect)) continue;
          if (((StatChangeEffect)effect).isRaise()) {
            raises++;
          }
        }
        setPower(60 + 20 * raises);
        int damage = super.use(mech, user, target);
        setPower(0);
        return damage;
      }
      public boolean isAttack() {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Last Resort",
        new PokemonMove(PokemonType.T_NORMAL, 130, 1.0, 5) {
      class LastResortEffect extends StatusEffect {
        int[] m_pp;
        public LastResortEffect(int[] pp) {
          m_pp = pp;
        }
        public int getPp(int i) {
          return m_pp[i];
        }
      }
      public void switchIn(Pokemon p) {
        int[] pp = new int[4];
        for (int i = 0; i < 4; ++i) {
          pp[i] = p.getPp(i);
        }
        p.addStatus(p, new LastResortEffect(pp));
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        LastResortEffect effect = (LastResortEffect)
        user.getEffect(LastResortEffect.class);
        if (effect == null) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        boolean hasOtherMoves = false;
        for (int i = 0; i < 4; ++i) {
          MoveListEntry entry = user.getMove(i);
          if (entry == null) continue;
          if (!entry.getName().equals("Last Resort")) {
            hasOtherMoves = true;
            if (user.getPp(i) >= effect.getPp(i)) {
              hasOtherMoves = false;
              break;
            }
          }
        }
        if (!hasOtherMoves) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        return super.use(mech, user, target);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Magma Storm", new StatusMove(
        PokemonType.T_FIRE, 120, 0.70, 5, new StatusEffect[] {
            new RestrainingEffect("Magma Storm", "trapped in a vortex!")
        },
        new boolean[] { false },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Dark Void", new StatusMove(
        PokemonType.T_DARK, 0, 0.8, 10, new StatusEffect[] {
            new SleepEffect()
        },
        new boolean[] { false },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Seed Flare", new StatusMove(
        PokemonType.T_GRASS, 120, 0.85, 5, new StatusEffect[] {
            new StatChangeEffect(Pokemon.S_SPDEFENCE, false)
        },
        new boolean[] { false },
        new double[] { 0.4 }
    )));

    m_moves.add(new MoveListEntry("Protect", new ProtectMove(
        PokemonType.T_NORMAL, 10, new ProtectEffect() {
          public String getDescription() {
            return " protected itself!";
          }
        })));

    m_moves.add(new MoveListEntry("Endure", new ProtectMove(
        PokemonType.T_NORMAL, 10, new EndureEffect()
    )));

    m_moves.add(new MoveListEntry("Detect", new ProtectMove(
        PokemonType.T_FIGHTING, 5, new ProtectEffect() {
          public String getDescription() {
            return " braced itself!";
          }
        })));

    m_moves.add(new MoveListEntry("Taunt", new StatusMove(
        PokemonType.T_DARK, 0, 1.0, 20, new StatusEffect[] {
            new StatusEffect() {
              private int m_turns;
              public boolean apply(Pokemon p) {
                Random r = p.getField().getMechanics().getRandom();
                m_turns = r.nextInt(3) + 3;
                return true;
              }
              public String getDescription() {
                return " fell for the taunt!";
              }
              public String getName() {
                return "Taunt";
              }
              public int getTier() {
                return 1;
              }
              public boolean tick(Pokemon p) {
                if (--m_turns == 0) {
                  p.removeStatus(this);
                  p.getField().showMessage(p.getName() + "'s taunt wore off!");
                  return true;
                }
                return false;
              }
              public boolean isMoveTransformer(boolean enemy) {
                return !enemy;
              }
              public boolean hitsThroughSubstitute() {
                // TODO: NOTE: Does not hit through in advance!
                return true;
              }
              public boolean vetoesMove(Pokemon p, MoveListEntry entry) {
                String name = entry.getName();
                if (name.equals("Struggle")) {
                  return false;
                }
                HashSet<String> set = new HashSet<String>(Arrays.asList(new String[] {
                    "Nature Power", "Sleep Talk", "Assist", "Metronome"
                }));
                if (set.contains(name)) {
                  return true;
                }
                return !entry.getMove().isDamaging();
              }
              public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
                if (vetoesMove(p, entry)) {
                  BattleField field = p.getField();
                  String move = entry.getName();
                  field.informUseMove(p, move);
                  field.showMessage(p.getName() + " can't use " + move + " after the taunt!");
                  return null;
                }
                return entry;
              }
            }
        },
        new boolean[] { false },
        new double[] { 1.0 }
    ) {
      public boolean attemptHit(BattleMechanics mech, Pokemon source, Pokemon target) {
        return true;
      }
    }));

    m_moves.add(new MoveListEntry("Shadow Force", new StatusMove(
        PokemonType.T_GHOST, 0, 1.0, 5, new StatusEffect[] {
            new InvulnerableStateEffect(new String[0]),
            new ChargeEffect(1, "dissappeared from sight!", new MoveListEntry(
                "Shadow Force",
                new PokemonMove(PokemonType.T_GHOST, 120, 1.0, 5)
            )
            )
        },
        new boolean[] { true, true },
        new double[] { 1.0, 1.0 }
    )   {
      public boolean isAttack() {
        return true;
      }
      public boolean isDamaging() {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Ominous Wind", new StatusMove(
        PokemonType.T_GHOST, 60, 1.0, 5, new StatusEffect[] {
            new MultipleStatChangeEffect(new int[] {
                Pokemon.S_ATTACK,
                Pokemon.S_DEFENCE,
                Pokemon.S_SPEED,
                Pokemon.S_SPATTACK,
                Pokemon.S_SPDEFENCE
            }
            )
        },
        new boolean[] { true },
        new double[] { 0.1 }
    )));

    m_moves.add(new MoveListEntry("Toxic Spikes",
        new PokemonMove(PokemonType.T_POISON, 0, 1.0, 20) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        BattleField field = user.getField();
        ToxicSpikesEffect spikes = (ToxicSpikesEffect)SpikesEffect.getSpikes(field, ToxicSpikesEffect.class);
        if (spikes == null) {
          spikes = new ToxicSpikesEffect();
          field.applyEffect(spikes);
        }
        spikes.addSpikes(target);
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Stealth Rock",
        new PokemonMove(PokemonType.T_ROCK, 0, 1.0, 20) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        BattleField field = user.getField();
        StealthRockEffect spikes = (StealthRockEffect)SpikesEffect.getSpikes(field, StealthRockEffect.class);
        if (spikes == null) {
          spikes = new StealthRockEffect();
          field.applyEffect(spikes);
        }
        spikes.addSpikes(target);
        return 0;
      }
    }
    ));

    class MeFirstEffect extends StatusEffect {
      private MoveListEntry m_move;
      public MeFirstEffect(MoveListEntry move) {
        m_move = move;
      }
      public boolean isMoveTransformer(boolean enemy) {
        return !enemy;
      }
      public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
        p.getField().informUseMove(p, "Me First");
        return m_move;
      }
      public int getTier() {
        return 1;
      }
      public boolean tick(Pokemon p) {
        p.removeStatus(this);
        return true;
      }
      public String getName() {
        return null;
      }
      public String getDescription() {
        return null;
      }
    }

    m_moves.add(new MoveListEntry("Me First",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 20) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public void beginTurn(BattleTurn[] turn, int index, Pokemon source) {
        // Assume two pokemon
        /** Note: You cannot give PokemonMoves states
         * outside of their nature as a move - there is only one
         * copy for the whole program, not for each pokemon who
         * has the move! The latter would be a massive waste of
         * memory.
         */
        if ((index == 1) || source.hasEffect(SleepEffect.class) || source.hasEffect(FreezeEffect.class)) {
          return;
        }
        BattleTurn opp = turn[1 - index];
        Pokemon target = source.getOpponent();
        if (!opp.isMoveTurn()) return;
        MoveListEntry entry = (MoveListEntry)target.getMove(opp.getId()).clone();
        PokemonMove move = entry.getMove();
        int power = move.getPower();
        if (!move.isDamaging()) return;
        move.setPower(power * 3 / 2);
        source.addStatus(source, new MeFirstEffect(entry));
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().showMessage("But it failed!");
        return 0;
      }
    }
    ));

    class SuckerPunchEffect extends StatusEffect {
      public int getTier() {
        return 1;
      }
      public boolean tick(Pokemon p) {
        p.removeStatus(this);
        return true;
      }
      public String getName() {
        return null;
      }
      public String getDescription() {
        return null;
      }
    }

    m_moves.add(new MoveListEntry("Sucker Punch",
        new PokemonMove(PokemonType.T_DARK, 80, 1.0, 5) {
      public void beginTurn(BattleTurn[] turn, int index, Pokemon source) {
        // Assume two pokemon
        if (index == 1) {
          // User must be going first.
          return;
        }
        BattleTurn opp = turn[1 - index];
        if (opp.isMoveTurn() && opp.getMove(source.getOpponent()).isDamaging()) {
          source.addStatus(source, new SuckerPunchEffect());
        }
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!user.hasEffect(SuckerPunchEffect.class)) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        return super.use(mech, user, target);
      }
      public int getPriority() {
        return 1;
      }
    }
    ));

    class AssuranceEffect extends StatusEffect {
      private int m_health;
      public boolean apply(Pokemon p) {
        m_health = p.getOpponent().getHealth();
        return true;
      }
      public int getHealth() {
        return m_health;
      }
      public int getTier() {
        return 5;
      }
      public boolean tick(Pokemon p) {
        p.removeStatus(this);
        return true;
      }
    }

    m_moves.add(new MoveListEntry("Assurance",
        new PokemonMove(PokemonType.T_DARK, 50, 1.0, 10) {
      public void beginTurn(BattleTurn[] turn, int index, Pokemon source) {
        source.getOpponent().addStatus(source, new AssuranceEffect());
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int power = getPower();
        if (!target.hasEffect(AssuranceEffect.class)) {
          StatusEffect effect = target.getEffect(AssuranceEffect.class);
          AssuranceEffect eff = (AssuranceEffect) effect;
          if (target.getHealth() < eff.getHealth()) {
            setPower(power * 2);
          }
          int damage = super.use(mech, user, target);
          setPower(power);
          return damage;
        } else {
          return super.use(mech, user, target);
        }
      }
    }
    ));



    m_moves.add(new MoveListEntry("Judgement",
        new PokemonMove(PokemonType.T_NORMAL, 100, 1.0, 10)));

    m_moves.add(new MoveListEntry("Metal Burst",
        new CounterMove(PokemonType.T_STEEL, 1.0, 10, 3) {
      public int getPriority() {
        return 0;
      }
    }
    ));

    DamageListenerMove payback = new DamageListenerMove(PokemonType.T_DARK, 50, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        DamageListenerEffect listener = getListener(user);
        if ((listener == null) || (listener.getDamage() <= 0)) {
          return super.use(mech, user, target);
        }
        int power = getPower();
        setPower(power * 2);
        int damage = super.use(mech, user, target);
        setPower(power);
        return damage;
      }
    };

    DamageListenerMove avalanche = (DamageListenerMove)payback.clone();
    avalanche.setType(PokemonType.T_ICE);
    avalanche.setPower(60);
    avalanche.setPriority(-3);
    m_moves.add(new MoveListEntry("Payback", payback));
    m_moves.add(new MoveListEntry("Avalanche", avalanche));

    m_moves.add(new MoveListEntry("Roost", new StatusMove(
        PokemonType.T_FLYING, 0, 1.0, 10, new StatusEffect[] {
            new StatusEffect() {
              private PokemonType[] m_types;
              public boolean apply(Pokemon p) {
                m_types = p.getTypes();
                ArrayList<PokemonType> types = new ArrayList<PokemonType>(Arrays.asList(m_types));
                Iterator<PokemonType> i = types.iterator();
                while (i.hasNext()) {
                  PokemonType type = (PokemonType)i.next();
                  if (type.equals(PokemonType.T_FLYING)) {
                    i.remove();
                  }
                }
                p.setType((PokemonType[])types.toArray(new PokemonType[types.size()]));
                return true;
              }
              public String getName() {
                return "Roosting";
              }
              public int getTier() {
                return 5;
              }
              public String getDescription() {
                return null;
              }
              public void unapply(Pokemon p) {
                p.setType(m_types);
              }
              public boolean tick(Pokemon p) {
                p.removeStatus(this);
                return true;
              }
            }, new PercentEffect(0.5, false, -1, null)
        },
        new boolean[] { true, true },
        new double[] { 1.0, 1.0 }
    )));

    m_moves.add(new MoveListEntry("Grass Knot",
        new MassBasedMove(PokemonType.T_GRASS, 1.0, 20)));

    m_moves.add(new MoveListEntry("Guard Swap",
        new StatChangeSwapMove(PokemonType.T_PSYCHIC, 10, new int[] {
            Pokemon.S_DEFENCE,
            Pokemon.S_SPDEFENCE
        }
        )));

    m_moves.add(new MoveListEntry("Power Swap",
        new StatChangeSwapMove(PokemonType.T_PSYCHIC, 10, new int[] {
            Pokemon.S_ATTACK,
            Pokemon.S_SPATTACK
        }
        )));

    m_moves.add(new MoveListEntry("Heart Swap",
        new StatChangeSwapMove(PokemonType.T_PSYCHIC, 10, new int[] {
            Pokemon.S_DEFENCE,
            Pokemon.S_SPDEFENCE,
            Pokemon.S_ATTACK,
            Pokemon.S_SPATTACK,
            Pokemon.S_SPEED,
            Pokemon.S_ACCURACY,
            Pokemon.S_EVASION
        }
        )));

    m_moves.add(new MoveListEntry("Outrage",
        new RampageMove(PokemonType.T_DRAGON, 120, 1.0, 15) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        setPower((int)(((double)getPower()) / 120.0 * ((mech instanceof JewelMechanics) ? 120.0 : 90.0)));
        return super.use(mech, user, target);
      }
    }));

    m_moves.add(new MoveListEntry("Petal Dance",
        new RampageMove(PokemonType.T_GRASS, 70, 1.0, 20)
    ));

    m_moves.add(new MoveListEntry("Thrash",
        new RampageMove(PokemonType.T_NORMAL, 90, 1.0, 20)
    ));

    m_moves.add(new MoveListEntry("Fake Out",
        new PokemonMove(PokemonType.T_NORMAL, 40, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!user.isFirstTurn()) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        if ((getEffectiveness(user, target) != 0.0) && !target.hasSubstitute()) {
          target.addStatus(user, new FlinchEffect());
        }
        return super.use(mech, user, target);
      }
      public int getPriority() {
        return 1;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Magnet Rise",
        new PokemonMove(PokemonType.T_ELECTRIC, 0, 0, 10) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        StatusEffect eff = user.addStatus(user, new MagnetRiseEffect());
        if (eff == null) {
          user.getField().showMessage("But it failed!");
        }
        return 0;
      }
    }
    ));

    PokemonMove mirrorMove = new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 20) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.getLastMove() == null) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        return user.useMove(target.getLastMove(), target);
      }
    };

    m_moves.add(new MoveListEntry("Mirror Move", (PokemonMove)mirrorMove.clone()));
    m_moves.add(new MoveListEntry("Copycat", (PokemonMove)mirrorMove.clone()));

    m_moves.add(new MoveListEntry("Spite",
        new PokemonMove(PokemonType.T_GHOST, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        MoveListEntry move = target.getLastMove();
        if (move == null) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        for (int i = 0; i < 4; ++i) {
          if (move.equals(target.getMove(i))) {
            int number = (mech instanceof JewelMechanics) ? 4 :
              mech.getRandom().nextInt(3) + 2;
            target.setPp(i, target.getPp(i) - number);
            return 0;
          }
        }
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Destiny Bond", new StatusMove(
        PokemonType.T_GHOST, 0, 1.0, 5, new StatusEffect[] {
            new StatusEffect() {
              public String getName() {
                return "Destiny bond";
              }
              public String getDescription() {
                return " is trying to take its foe with it!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public void executeTurn(Pokemon p, BattleTurn turn) {
                p.removeStatus(this);
              }
              public boolean isListener() {
                return true;
              }
              public boolean hitsThroughSubstitute() {
                return true;
              }
              public void informDamaged(Pokemon source, Pokemon target, MoveListEntry move, int damage) {
                if (target.getHealth() <= 0) {
                  target.getField().showMessage(target.getName() + " took " +
                      source.getName() + " with it!");
                  source.faint();
                }
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Grudge", new StatusMove(
        PokemonType.T_GHOST, 0, 1.0, 5, new StatusEffect[] {
            new StatusEffect() {
              public String getName() {
                return "Grudge";
              }
              public String getDescription() {
                return " is bearing a Grudge!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean isListener() {
                return true;
              }
              public boolean hitsThroughSubstitute() {
                return true;
              }
              public void informDamaged(Pokemon source, Pokemon target, MoveListEntry move, int damage) {
                if (target.getHealth() <= 0) {
                  for (int i = 0; i < 4; i++) {
                    if (move.equals(source.getMove(i))) {
                      source.getField().showMessage(
                          move.getName() + " lost its PP due to the Grudge!");
                      source.setPp(i, 0);
                      break;
                    }
                  }
                }
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Miracle Eye", new StatusMove(
        PokemonType.T_PSYCHIC, 0, 1.0, 40, new StatusEffect[] {
            new StatusEffect() {
              public String getName() {
                return "Miracle";
              }
              public String getDescription() {
                return " indentified the enemy Pokemon!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean isEffectivenessTransformer(boolean enemy) {
                return !enemy;
              }
              public double getTransformedEffectiveness(PokemonType move, PokemonType pokemon) {
                if (move.equals(PokemonType.T_PSYCHIC) && pokemon.equals(PokemonType.T_DARK)) {
                  return 1.0;
                }
                return super.getTransformedEffectiveness(move, pokemon);
              }
            }
        },
        new boolean[] { false },
        new double[] { 1.0 }
    ) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        List<StatusEffect> statuses = target.getNormalStatuses(0);
        Iterator<StatusEffect> i = statuses.iterator();
        while (i.hasNext()) {
          StatusEffect effect = (StatusEffect)i.next();
          if (!(effect instanceof StatChangeEffect)) continue;
          StatChangeEffect eff = (StatChangeEffect)effect;
          if (eff.getStat() == Pokemon.S_EVASION) {
            target.removeStatus(eff);
          }
        }
        target.getEvasion().setSecondaryMultiplier(1);
        return super.use(mech, user, target);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Torment", new StatusMove(
        PokemonType.T_DARK, 0, 1.0, 15, new StatusEffect[] {
            new StatusEffect() {
              private MoveListEntry m_entry;
              public String getName() {
                return "Torment";
              }
              public String getDescription() {
                return " was subjected to Torment!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean apply(Pokemon p) {
                m_entry = p.getLastMove();
                return super.apply(p);
              }
              public boolean isMoveTransformer(boolean enemy) {
                return !enemy;
              }
              public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
                if (entry.equals(m_entry)) {
                  p.getField().showMessage(p.getName() + " couldn't use the move after" +
                      " the torment!");
                  return null;
                }
                m_entry = entry;
                return entry;
              }
              public boolean vetoesMove(Pokemon p, MoveListEntry entry) {
                if (m_entry == null) {
                  return false;
                }
                return m_entry.equals(entry);
              }
            }
        },
        new boolean[] { false },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Encore", new StatusMove(
        PokemonType.T_NORMAL, 0, 1.0, 5, new StatusEffect[] {
            new StatusEffect() {
              private int m_turns;
              private boolean m_transform = true;
              private MoveListEntry m_entry;
              public String getName() {
                return "Encore";
              }
              public String getDescription() {
                return " got an encore!";
              }
              public int getTier() {
                return 5;
              }
              public boolean hitsThroughSubstitute() {
                return true;
              }
              public boolean apply(Pokemon p) {
                MoveListEntry entry = p.getLastMove();
                if (entry == null) {
                  p.getField().showMessage("But it failed!");
                  return false;
                }
                m_entry = entry;
                m_turns = p.getField().getRandom().nextInt(5) + 5;
                return true;
              }

              public boolean tick(Pokemon p) {
                if (--m_turns <= 0) {
                  p.getField().showMessage(p.getName() + "'s encore ended.");
                  p.removeStatus(this);
                  return true;
                }
                return false;
              }
              public boolean isMoveTransformer(boolean enemy) {
                return !enemy;
              }
              public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
                if (m_transform) {
                  m_transform = false;
                  return m_entry;
                }
                return entry;
              }
              public boolean vetoesMove(Pokemon p, MoveListEntry entry) {
                return !entry.equals(m_entry);
              }
            }
        },
        new boolean[] { false },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Disable", new StatusMove(
        PokemonType.T_NORMAL, 0, 0.55, 20, new StatusEffect[] {
            new StatusEffect() {
              private int m_turns;
              private MoveListEntry m_entry;
              public String getName() {
                return "Disabled: " + m_entry.getName();
              }
              public String getDescription() {
                return " was disabled!";
              }
              public int getTier() {
                return 5;
              }
              public boolean apply(Pokemon p) {
                MoveListEntry entry = p.getLastMove();
                if (entry == null) {
                  p.getField().showMessage("But it failed!");
                  return false;
                }
                m_entry = entry;
                m_turns = p.getField().getRandom().nextInt(3) + 2;
                return true;
              }
              public boolean isMoveTransformer(boolean enemy) {
                return !enemy;
              }
              public MoveListEntry getEnemyTransformedMove(Pokemon p, MoveListEntry entry) {
                if (entry.equals(m_entry)) {
                  p.getField().showMessage(p.getName() + "'s " + entry.getName() +
                  " is disabled!");
                  return null;
                }
                return entry;
              }
              public boolean tick(Pokemon p) {
                if (--m_turns <= 0) {
                  p.removeStatus(this);
                  return true;
                }
                return false;
              }
              public boolean vetoesMove(Pokemon p, MoveListEntry entry) {
                return entry.equals(m_entry);
              }
              public boolean hitsThroughSubstitute() {
                return true;
              }
            }
        },
        new boolean[] { false },
        new double[] { 1.0 }
    ) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        setAccuracy(mech instanceof JewelMechanics ? 80 : 55);
        return super.attemptHit(mech, user, target);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Imprison", new StatusMove(
        PokemonType.T_PSYCHIC, 0, 1.0, 15, new StatusEffect[] {
            new StatusEffect() {
              public String getName() {
                return "Imprison";
              }
              public String getDescription() {
                return "'s moves were sealed!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean vetoesMove(Pokemon p, MoveListEntry entry) {
                Pokemon target = p.getOpponent();
                for (int i = 0; i < 4; ++i) {
                  MoveListEntry move = target.getMove(i);
                  if ((move != null) && move.equals(entry)) {
                    return true;
                  }
                }
                return false;
              }
              public boolean hitsThroughSubstitute() {
                return true;
              }
            }
        },
        new boolean[] { false },
        new double[] { 1.0 }
    ) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Stockpile", new PokemonMove(
        PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        StockpileEffect eff = (StockpileEffect)(user.getEffect(StockpileEffect.class));
        if (eff == null) {
          eff = (StockpileEffect)user.addStatus(user, new StockpileEffect());
        }
        eff.incrementLevel(user);
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Spit Up",
        new StockpileMove(PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int levels = getLevels(user);
        if (levels <= 0) {
          user.getField().showMessage("But it failed to spit up anything!");
          return 0;
        }
        setPower(100 * levels);
        int damage = super.use(mech, user, target);
        setPower(0);
        user.removeStatus(getStockpileEffect(user));
        return damage;
      }
      public boolean isAttack() {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Swallow",
        new StockpileMove(PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int levels = getLevels(user);
        if (levels <= 0) {
          user.getField().showMessage("But it failed to swallow anything!");
          return 0;
        }
        double[] percents = new double[] {0.25, 0.5, 1.0};
        double percent = percents[levels];

        user.addStatus(user, new PercentEffect(percent, false, -1, null));
        user.removeStatus(getStockpileEffect(user));
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Tailwind",
        new PokemonMove(PokemonType.T_FLYING, 0, 1.0, 30) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().applyEffect(new TailwindEffect(user.getParty()));
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Bide", new StatusMove(
        PokemonType.T_NORMAL, 0, 1.0, 10, new StatusEffect[] {
            new StatusEffect() {
              private int m_damage = 0;
              private int m_turns = 2;
              public String getName() {
                return "Bide";
              }
              public String getDescription() {
                return " is storing energy!";
              }
              public int getTier() {
                return -1;
              }
              public boolean deactivates(Pokemon p) {
                return true;
              }
              public boolean isListener() {
                return true;
              }
              public void informDamaged(Pokemon source, Pokemon target, MoveListEntry move, int damage) {
                m_damage += damage;
              }
              public boolean immobilises(Pokemon p) {
                if (--m_turns <= 0) {
                  p.getField().showMessage(p.getName() + " unleashed energy!");
                  p.useMove(new PokemonMove(PokemonType.T_TYPELESS, 0, 1.0, 1) {
                    public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
                      int change = 2 * m_damage;
                      target.changeHealth(-change);
                      return change;
                    }
                  }, p.getOpponent());
                  p.removeStatus(this);
                }
                return true;
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    ) {
      public int getPriority() {
        // todo: This should also only be in D/P.
        return 1;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    class MimicEffect extends StatusEffect {
      private MoveListEntry m_entry;
      public MimicEffect(MoveListEntry entry) {
        m_entry = entry;
      }
      public String getName() {
        return "Mimicking " + m_entry.getName();
      }
      public String getDescription() {
        return " mimicked the foe's move!";
      }
      public boolean isMoveTransformer(boolean enemy) {
        return !enemy;
      }
      public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
        if (entry.getName().equals("Mimic")) {
          return m_entry;
        }
        return entry;
      }
    }

    m_moves.add(new MoveListEntry("Mimic",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        MoveListEntry move = target.getLastMove();
        if (move == null) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        user.addStatus(user, new MimicEffect(move));
        return 0;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Mist",
        new PokemonMove(PokemonType.T_ICE, 0, 1.0, 30) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        StatusEffect eff = user.getField().getEffectByType(MistEffect.class);
        if (eff == null) {
          user.getField().applyEffect(new MistEffect());
        }
        eff = user.getField().getEffectByType(MistEffect.class);
        if (eff != null) {
          MistEffect effect = (MistEffect)eff;
          effect.activateParty(user);
        }
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Safeguard",
        new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 25) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        StatusEffect eff = user.getField().getEffectByType(SafeguardEffect.class);
        if (eff == null) {
          user.getField().applyEffect(new SafeguardEffect());
        }
        eff = user.getField().getEffectByType(SafeguardEffect.class);
        if (eff != null) {
          SafeguardEffect effect = (SafeguardEffect)eff;
          effect.activateParty(user);
        }
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }
    ));

    m_moves.add(new MoveListEntry("Gastro Acid",
        new PokemonMove(PokemonType.T_POISON, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.hasSubstitute()) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        IntrinsicAbility ability = target.getAbility();
        if ((ability != null) && ability.isActive()) {
          ability.unapply(target);
          ability.deactivate();
        }
        user.getField().showMessage(target.getName() + "'s ability was nullified.");
        target.addStatus(user, new StatusEffect() {
          public String getName() {
            return "Gastro Acid";
          }
        });
        return 0;
      }
    }));

    m_moves.add(new MoveListEntry("Gravity",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 5) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().applyEffect(new FieldEffect() {
          private int m_turns = 5;
          public int getTier() {
            return 1;
          }
          public boolean applyToField(BattleField field) {
            // Completely made up message.
            field.showMessage("Gravity intensified!");
            return true;
          }
          public boolean apply(Pokemon p) {
            if (p.hasAbility("Levitate")) {
              p.getAbility().deactivate();
            }
            BattleField field = p.getField();
            field.setNarrationEnabled(false);
            p.removeStatus(MagnetRiseEffect.class);
            field.setNarrationEnabled(true);
            p.getMultiplier(Pokemon.S_ACCURACY).multiplyBy(1.7);
            return true;
          }
          public void unapply(Pokemon p) {
            /** This will interfere with mold breaker and gastro acid,
             *  but we will address that later. */
            IntrinsicAbility ability = p.getAbility();
            if ((ability != null) && ability.getName().equals("Levitate")) {
              ability.activate();
            }
            p.getMultiplier(Pokemon.S_ACCURACY).divideBy(1.7);
          }
          public boolean tickPokemon(Pokemon p) {
            return false;
          }
          public boolean isEffectivenessTransformer(boolean enemy) {
            return !enemy;
          }
          public double getTransformedEffectiveness(PokemonType move, PokemonType defender) {
            if (PokemonType.T_GROUND.equals(move) && PokemonType.T_FLYING.equals(defender)) {
              // Ground is neutral aganist flying under the effects of gravity.
              return 1.0;
            }
            return super.getTransformedEffectiveness(move, defender);
          }
          public boolean isMoveTransformer(boolean enemy) {
            return !enemy;
          }
          public boolean vetoesMove(Pokemon p, MoveListEntry entry) {
            return !canUseMove(entry.getName());
          }
          private boolean canUseMove(String move) {
            // Moves that involve going up into the air are forbidden.
            Set<String> forbidden = new HashSet<String>(Arrays.asList(new String[] {
                "Fly", "Bounce", "Hi Jump Kick", "Jump Kick", "Magnet Rise"
            }));
            return !forbidden.contains(move);
          }
          public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
            String name = entry.getName();
            if (!canUseMove(name)) {
              BattleField field = p.getField();
              field.showMessage(p.getName() + " can't use " + name + " because of the Gravity.");
              return null;
            }
            return entry;
          }

          public boolean tickField(BattleField field) {
            if (--m_turns == 0) {
              field.removeEffect(this);
              return true;
            }
            return false;
          }
          public String getName() {
            return "Gravity";
          }
          public void unapplyToField(BattleField field) {
            field.showMessage("Gravity returned to normal!");
          }
        });
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    }));

    m_moves.add(new MoveListEntry("Embargo",
        new PokemonMove(PokemonType.T_DARK, 0, 1.0, 15) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (target.hasSubstitute()) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        target.addStatus(user, new StatusEffect() {
          public boolean apply(Pokemon p) {
            HoldItem item = p.getItem();
            if ((item != null) && item.isActive()) {
              item.unapply(p);
              item.deactivate();
            }
            return true;
          }
          public String getDescription() {
            return "'s item was nullified.";
          }
          public void unapply(Pokemon p) {
            HoldItem item = p.getItem();
            if ((item != null) && !item.isRemovable()) {
              item.activate();
              item.apply(p);
            }
          }
          public String getName() {
            return "Embargo";
          }
        });
        return 0;
      }
    }));

    class SnatchEffect extends StatusEffect {
      private StatusEffect[] m_effects;
      public SnatchEffect(StatusEffect[] effects) {
        m_effects = effects;
      }
      public String getName() {
        return "Snatch";
      }
      public String getDescription() {
        return null;
      }
      public boolean tick(Pokemon p) {
        p.removeStatus(this);
        return true;
      }
      public boolean isMoveTransformer(boolean enemy) {
        return enemy;
      }
      public MoveListEntry getEnemyTransformedMove(Pokemon p, MoveListEntry entry) {
        return null;
      }
      public StatusEffect[] getEffects() {
        return m_effects;
      }
    }

    m_moves.add(new MoveListEntry("Snatch",
        new PokemonMove(PokemonType.T_DARK, 0, 1.0, 10) {
      @SuppressWarnings("unused")
      public void beginTurn(BattleTurn[] turn, Pokemon p, int index) {
        if (p.hasEffect(SleepEffect.class) || p.hasEffect(FreezeEffect.class)) {
          return;
        }
        BattleTurn opp = turn[1 - index];
        if (!opp.isMoveTurn()) return;
        MoveListEntry entry = p.getOpponent().getMove(opp.getId());
        PokemonMove move = entry.getMove();
        if (!(move instanceof StatusMove)) return;
        StatusMove statusMove = (StatusMove)move;
        if (statusMove.isAttack()) return;
        StatusEffect[] effects = statusMove.getEffects();
        p.addStatus(p, new SnatchEffect(effects));
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.getField().showMessage(user.getName() + " awaits the foe's move!");
        SnatchEffect eff = (SnatchEffect)user.getEffect(SnatchEffect.class);
        if (eff == null) {
          return 0;
        }
        StatusEffect[] effects = eff.getEffects();
        if (effects.length > 0) {
          user.getField().showMessage(user.getName() + " snatched the foe's effects!");
          for (int i = 0; i < effects.length; ++i) {
            user.addStatus(user, effects[i]);
          }
        }
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int getPriority() {
        return 3;
      }
    }
    ));

    PokemonMove lockOn = new PokemonMove(PokemonType.T_NORMAL, 0, 1.0, 5) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        user.addStatus(user, new LockOnEffect());
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
    };
    m_moves.add(new MoveListEntry("Lock-on", (PokemonMove)lockOn.clone()));
    m_moves.add(new MoveListEntry("Mind Reader", (PokemonMove)lockOn.clone()));

    m_moves.add(new MoveListEntry("Conversion 2", new StatusMove(
        PokemonType.T_NORMAL, 0, 1.0, 30, new StatusEffect[] {
            new StatusEffect() {
              private PokemonType[] m_types;

              public String getName() {
                return "Conversion 2";
              }
              public String getDescription() {
                return null;
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean apply(Pokemon p) {
                m_types = p.getTypes();
                MoveListEntry entry = p.getOpponent().getLastMove();
                if (entry == null) {
                  p.getField().showMessage("But it failed!");
                  return false;
                }
                PokemonType moveType = entry.getMove().getType();
                ArrayList<PokemonType> types = new ArrayList<PokemonType>(Arrays.asList(PokemonType.getTypes()));
                Iterator<PokemonType> i = types.iterator();
                while (i.hasNext()) {
                  PokemonType type = (PokemonType)i.next();
                  if (moveType.getMultiplier(type) >= 1) {
                    i.remove();
                  }
                }
                int random = p.getField().getRandom().nextInt(types.size());
                p.setType(new PokemonType[] { (PokemonType)types.get(random) });
                return true;                           
              }
              public void unapply(Pokemon p) {
                p.setType(m_types);
              }
              public boolean switchOut(Pokemon p) {
                p.setType(m_types);
                return true;
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Rage", new StatusMove(
        PokemonType.T_NORMAL, 20, 1.0, 20, new StatusEffect[] {
            new StatusEffect() {                       
              public String getName() {
                return "Rage";
              }
              public String getDescription() {
                return " went into a rage!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public void executeTurn(Pokemon p, BattleTurn turn) {
                p.removeStatus(this);
              }
              public boolean isListener() {
                return true;
              }
              public void informDamaged(Pokemon source, Pokemon target, MoveListEntry move, int damage) {
                target.getField().showMessage(target.getName() + " is angry!");
                target.addStatus(target, new StatChangeEffect(Pokemon.S_ATTACK, true));
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    class FuryCutterEffect extends StatusEffect {
      public int m_turns = 0;
      public String getName() {
        return "Fury cutter";
      }
      public String getDescription() {
        return null;
      }
      public int getTier() {
        return -1;
      }
      public boolean tick(Pokemon p) {
        m_turns++;
        return false;
      }
      public void executeTurn(Pokemon p, BattleTurn turn) {
        if (p.getField().getMechanics() instanceof JewelMechanics) {
          return;
        }
        if (!p.getMove(turn.getId()).getName().equals("Fury Cutter")) {
          p.removeStatus(this);
        }
      }
      public boolean isMoveTransformer(boolean enemy) {
        return !enemy;
      }
      public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
        if (!entry.getName().equals("Fury Cuttter")) return entry;
        PokemonMove move = entry.getMove();
        int power = move.getPower() * (1 << m_turns);
        if (power > 160) power = 160;
        move.setPower(power);
        return entry;
      }
      public boolean isSingleton() {
        return true;
      }
      public void informDuplicateEffect(Pokemon p) {
      }
    }

    m_moves.add(new MoveListEntry("Fury Cutter", new StatusMove(
        PokemonType.T_BUG, 10, 0.95, 20, new StatusEffect[] {
            new FuryCutterEffect()
        },
        new boolean[] { true },
        new double[] { 1.0 }
    ) {
      public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
        return true;
      }
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        if (!super.attemptHit(mech, user, target)) {
          user.removeStatus(FuryCutterEffect.class);
        }
        return super.use(mech, user, target);
      }
    }
    ));

    m_moves.add(new MoveListEntry("Power Trick", new StatusMove(
        PokemonType.T_PSYCHIC, 0, 1.0, 10, new StatusEffect[] {
            new StatusEffect() {                       
              private int m_attack;
              private int m_defence;
              public String getName() {
                return "Power Trick";
              }
              public String getDescription() {
                return " swapped its stats!";
              }
              public int getTier() {
                return -1;
              }
              public boolean tick(Pokemon p) {
                return false;
              }
              public boolean apply(Pokemon p) {
                m_attack = p.getRawStat(Pokemon.S_ATTACK);
                m_defence = p.getRawStat(Pokemon.S_DEFENCE);
                p.setRawStat(Pokemon.S_ATTACK, m_defence);
                p.setRawStat(Pokemon.S_DEFENCE, m_attack);
                return super.apply(p);
              }
              public void unapply(Pokemon p) {
                p.setRawStat(Pokemon.S_ATTACK, m_attack);
                p.setRawStat(Pokemon.S_DEFENCE, m_defence);
              }
            }
        },
        new boolean[] { true },
        new double[] { 1.0 }
    )));

    m_moves.add(new MoveListEntry("Uproar", new FixedAttackMove(
        PokemonType.T_NORMAL, 50, 1.0, 20, new FixedAttackEffect("Uproar",
            " caused an uproar!", " calmed down."))));

    m_moves.add(new MoveListEntry("Rollout", new FixedAttackMove(
        PokemonType.T_ROCK, 30, 0.9, 20, new RolloutEffect("Rollout"))));

    m_moves.add(new MoveListEntry("Ice Ball", new FixedAttackMove(
        PokemonType.T_ICE, 30, 0.9, 20, new RolloutEffect("Ice Ball"))));

    /** If you had bothered to read the Smogon analysis, you would have learned that
     *  this is actually nearly a clone of Lunar Dance (except that it does not heal
     *  PP); it is not at all like Destiny Bond. Fortunately the move is rare
     *  enough that it has yet to matter.
     */
    m_moves.add(new MoveListEntry("Healing Wish",
        new PokemonMove(PokemonType.T_PSYCHIC, 0, 1.0, 10) {
      public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
        int party = user.getParty();
        BattleField field = user.getField();
        if (field.getAliveCount(party) == 1) {
          user.getField().showMessage("But it failed!");
          return 0;
        }
        user.faint();
        field.requestAndWaitForSwitch(party);
        target = field.getActivePokemon()[party];
        target.changeHealth(target.getStat(Pokemon.S_HP));
        target.removeStatus(StatusEffect.SPECIAL_EFFECT_LOCK);
        return 0;
      }
      public boolean attemptHit(BattleMechanics mech, Pokemon source, Pokemon target) {
View Full Code Here

    private static class AirLockAbility extends IntrinsicAbility {
        public AirLockAbility(String name) {
            super(name);
        }
        public void switchIn(Pokemon p) {
            BattleField field = p.getField();
            FieldEffect eff = field.getEffectByType(WeatherEffect.class);
            if (eff != null) {
                eff.unapply(p);
                eff.unapply(p.getOpponent());
            }
        }
View Full Code Here

                eff.unapply(p.getOpponent());
            }
        }
        public boolean switchOut(Pokemon p) {
            p.setAbility(null, true);
            BattleField field = p.getField();
            FieldEffect eff = field.getEffectByType(WeatherEffect.class);
            if (eff != null) {
                eff.apply(p);
                eff.apply(p.getOpponent());
            }
            return super.switchOut(p);
View Full Code Here

        super(name);
        m_type = type;
    }
   
    public void switchIn(Pokemon p) {
        BattleField field = p.getField();
        if (p.hasAbility("Multitype") && (field != null)) {
            field.showMessage("The foe's " + p.getName()
                    + " transformed into the " + m_type + " type!");
        }
    }
View Full Code Here

            poke.getField().showMessage(poke.getName()
                + " snapped out of confusion!");
            return false;
        }
       
        BattleField field = poke.getField();
       
        field.showMessage(poke.getName() + " is confused!");
        if (field.getRandom().nextDouble() <= 0.5) {
            return false;
        }
       
        field.showMessage("It hurt itself in its confusion!");
        poke.useMove(new PokemonMove(PokemonType.T_TYPELESS, 40, 1.0, 1) {
                public int use(BattleMechanics mech, Pokemon source, Pokemon target) {
                    int damage = mech.calculateDamage(this, source, target);
                    target.changeHealth(-damage, true);
                    return damage;
View Full Code Here

   
    /**
     * Paralysis has a 25% chance of immobolising the afflicted pokemon.
     */
    public boolean immobilises(Pokemon poke) {
        BattleField field = poke.getField();
        if (field.getRandom().nextDouble() <= 0.25) {
            field.showMessage(poke.getName() + " is paralysed! It can't move!");
            return true;
        }
        return false;
    }
View Full Code Here

   
    /**
     * Freeze immolilises the pokemon.
     */
    public boolean immobilises(Pokemon poke) {
        BattleField field = poke.getField();
        if (field.getRandom().nextDouble() <= 0.25) {
            poke.removeStatus(this);
            return false;
        }
        field.showMessage(poke.getName() + " is frozen solid!");
        return true;
    }
View Full Code Here

   
    /**
     * Awesome immobilises 40% of the time.
     */
    public boolean immobilises(Pokemon poke) {
        BattleField field = poke.getField();
       
        if (++m_turns >= 4) {
            field.showMessage("God struck down " + poke.getName() + " with all his might!");
            poke.useMove(new PokemonMove(PokemonType.T_TYPELESS, 10000, 1.0, 1), poke);
            field.showMessage("God forgave " + poke.getName());
            poke.removeStatus(this);
            return true;
        }
       
        if (field.getRandom().nextDouble() <= 0.6) {
            return false;
        }
       
        field.showMessage(poke.getName() + " was too god-fearing to move!");
        return true;
    }
View Full Code Here

TOP

Related Classes of org.pokenet.server.battle.BattleField$PokemonWrapper

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.