/* PokemonMoves.java * * Created April 7, 2009 * * This file is a part of Shoddy Battle. * Copyright (C) 2009 Catherine Fitzpatrick and Benjamin Gwin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, visit the Free Software Foundation, Inc. * online at http://gnu.org. */ package shoddybattleclient.shoddybattle; import java.util.ArrayList; import java.util.List; import shoddybattleclient.shoddybattle.PokemonSpecies.IllegalCombo; /** * * @author ben */ public class Pokemon implements Cloneable { public static enum Gender { GENDER_MALE ("Male", 1), GENDER_FEMALE ("Female", 2), GENDER_NONE ("No Gender", 0), GENDER_BOTH ("Both", 3); private String m_name; private int m_value; Gender(String name, int value) { m_name = name; m_value = value; } public String getName() { return m_name; } public int getValue() { return m_value; } public static Gender getGender(int value) { for (Gender g : Gender.values()) { if (g.getValue() == value) return g; } return null; } @Override public String toString() { return m_name; } } public static final int S_HP = 0; public static final int S_ATTACK = 1; public static final int S_DEFENCE = 2; public static final int S_SPEED = 3; public static final int S_SPATTACK = 4; public static final int S_SPDEFENCE = 5; public static final int S_ACCURACY = 6; public static final int S_EVASION = 7; public static final int MOVE_COUNT = 4; public static final int STAT_COUNT = 6; public String species; public String nickname; public boolean shiny; public Gender gender; public int level; public String item; public String ability; public String nature; public String[] moves = new String[MOVE_COUNT]; public int[] ppUps = new int[MOVE_COUNT]; public int[] ivs = new int[STAT_COUNT]; public int[] evs = new int[STAT_COUNT]; public int happiness = 255; public Pokemon(String species, String nickname, boolean shiny, Gender gender, int level, int happiness, String item, String ability, String nature, String[] moves, int[] ppUps, int[] ivs, int[] evs) { this.species = species; this.nickname = nickname; this.shiny = shiny; this.gender = gender; this.level = level; this.happiness = happiness; this.item = item; this.ability = ability; this.nature = nature; this.moves = moves; this.ppUps = ppUps; this.ivs = ivs; this.evs = evs; } public Pokemon() { } @Override public String toString() { return this.species; } @Override public Pokemon clone() { return new Pokemon(species, nickname, shiny, gender, level, happiness, item, ability, nature, moves.clone(), ppUps.clone(), ivs.clone(), evs.clone()); } public int calculateStat(int i, Generation generation, int level) { PokemonSpecies s = generation.getSpeciesByName(species); PokemonNature n = PokemonNature.getNature(nature); return calculateStat(this, i, s, n, level); } private static double[] MULTIPLIERS = new double[] {0.25, 0.2857, 0.3333, 0.4, 0.5, 0.6667, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0}; public static int calculateStat(Pokemon pokemon, int i, PokemonSpecies species, PokemonNature nature) { return calculateStat(pokemon, i, species, nature, 0); } public static int calculateStat(Pokemon pokemon, int i, PokemonSpecies species, PokemonNature nature, int level) { int base = species.getBase(i); int common = (int)((int)(((2 * base) + pokemon.ivs[i] + (pokemon.evs[i] / 4))) * pokemon.level / 100); if (i == Pokemon.S_HP) { if (base == 1) { // Shedinja always has 1 hp. return 1; } else { return common + 10 + pokemon.level; } } double effect = (nature == null) ? 1.0 : nature.getEffect(i); int stat = (int)((common + 5) * effect); return (i == S_HP) ? stat : (int)(stat * MULTIPLIERS[6 + level]); } public static String getStatName(int idx) { switch(idx) { case S_HP: return "HP"; case S_ATTACK: return "Atk"; case S_DEFENCE: return "Def"; case S_SPEED: return "Spd"; case S_SPDEFENCE: return "SpDef"; case S_SPATTACK: return "SpAtk"; case S_EVASION: return "Evas"; case S_ACCURACY: return "Acc"; default: return "Bad stat index"; } } // Returns all illegal combinations that contain this moveset public List<IllegalCombo> getViolatedMovesets(Generation gen) { PokemonSpecies s = gen.getSpeciesByName(species); if (s == null) { return new ArrayList<IllegalCombo>(); } List<IllegalCombo> allCombos = s.getIllegalCombos(); ArrayList<IllegalCombo> illegal = new ArrayList<IllegalCombo>(); comboLoop: for (IllegalCombo combo : allCombos) { moveLoop: for (String move : combo.getMoves()) { for (String ownedMove : moves) { if (ownedMove == null) { continue; } if (ownedMove.equals(move)) { continue moveLoop; } } // Discard this combo if the move was not found continue comboLoop; } illegal.add(combo); } return illegal; } // Returns all combinations that are an exact match public List<IllegalCombo> getViolatedCombos(Generation gen) { List<IllegalCombo> allCombos = getViolatedMovesets(gen); ArrayList<IllegalCombo> illegal = new ArrayList<IllegalCombo>(); for (IllegalCombo combo : allCombos) { // Check the nature/ability if ((combo.getNature() != null) && !combo.getNature().equals(nature)) { continue; } if ((combo.getAbility() != null) && !combo.getAbility().equals(ability)) { continue; } if ((combo.getGender() != null) && (gender != combo.getGender())) { continue; } illegal.add(combo); } return illegal; } public String toXML() { StringBuffer buf = new StringBuffer(); buf.append("<pokemon species=\""); buf.append(species); buf.append("\">\n"); buf.append("<nickname>"); buf.append(nickname); buf.append("</nickname>\n"); if (shiny) { buf.append("<shiny />\n"); } buf.append("<level>"); buf.append(level); buf.append("</level>\n"); buf.append("<happiness>"); buf.append(happiness); buf.append("</happiness>\n"); buf.append("<gender>"); buf.append(gender.getName()); buf.append("</gender>\n"); buf.append("<nature>"); buf.append(nature); buf.append("</nature>\n"); buf.append("<item>"); buf.append(item); buf.append("</item>\n"); buf.append("<ability>"); buf.append(ability); buf.append("</ability>\n"); buf.append(("<moveset>\n")); for (int i = 0; i < moves.length; i++) { if (moves[i] == null) continue; buf.append(("\t<move pp-up=\"")); buf.append(ppUps[i]); buf.append("\">"); buf.append(moves[i]); buf.append("</move>\n"); } buf.append("</moveset>\n"); buf.append("<stats>\n"); for (int i = 0; i < STAT_COUNT; i++) { buf.append("\t<stat name=\""); buf.append(getStatName(i)); buf.append("\" iv=\""); buf.append(ivs[i]); buf.append("\" ev=\""); buf.append(evs[i]); buf.append("\" />\n"); } buf.append("</stats>\n"); buf.append("</pokemon>\n"); return new String(buf); } public String toTeamText() { StringBuffer buf = new StringBuffer(); String nick = nickname.trim(); if(!nick.equals(species) && nick.length() != 0) { buf.append(nick); buf.append(" ("); buf.append(species); buf.append(")"); } else buf.append(species); if(gender != Gender.GENDER_NONE) { buf.append(" ("); if(gender == Gender.GENDER_MALE) buf.append("M"); else buf.append("F"); buf.append(")"); } buf.append(" @ "); buf.append(item); buf.append("\nAbility: "); buf.append(ability); buf.append("\nEVs: "); for(int i = 0; i < evs.length; i++) { if(evs[i] != 0) { buf.append(evs[i]); buf.append(" "); buf.append(Pokemon.getStatName(i)); buf.append("/"); } } buf.setLength(buf.length()-1); //Remove the last / PokemonNature n = PokemonNature.getNature(nature); buf.append("\n"); buf.append(nature); buf.append(" nature ("); if (n.getBenefits() < 0) { buf.append("Neutral"); } else { buf.append("+"); buf.append(Pokemon.getStatName(n.getBenefits())); buf.append(",-"); buf.append(Pokemon.getStatName(n.getHarms())); } buf.append(")"); for(String move : moves) { buf.append("\n- "); buf.append(move); } return buf.toString(); } }