Welcome Guest [Log In] [Register]
We hope you enjoy your visit.


You're currently viewing our forum as a guest. This means you are limited to certain areas of the board and there are some features you can't use. If you join our community, you'll be able to access member-only sections, and use many member-only features such as customizing your profile, sending personal messages, and voting in polls. Registration is simple, fast, and completely free.


Join our community!


If you're already a member please log in to your account to access all of our features:

Username:   Password:
Add Reply
PT8Sceptile's results on adding pokemon to Shoddy; Only lacking sprites!
Topic Started: Apr 19 2008, 03:34 AM (1,382 Views)
+PT8Sceptile
Member Avatar
Allergic to bananas
[ *  *  * ]
I have now successfully tested my method of adding new Pokemon to Shoddybattle on a server I downloaded and edited. I still haven't figured out how to add sprites, though, but I assume this is a good enough start.

The code you have to add is the following:

To PokemonSpeciesData (Adds the new species to the data) :

Code:
 
   public void addSpecies(PokemonSpecies s) {
       PokemonSpecies[] sp = new PokemonSpecies[m_database.length + 1];
       for (int i = 0; i < m_database.length; i++) {
           sp[i] = m_database[i];
       }
       sp[sp.length - 1] = s;
       m_database = sp;
   }


To MoveSetData (Creates an empty slot for a moveset. Moves will be added through mods, just like abilities) :

Code:
 
   public void newSpecies() {
       MoveSet[] ms = new MoveSet[m_movesets.length + 1];
       for (int i = 0; i < m_movesets.length; i++) {
           ms[i] = m_movesets[i];
       }
       ms[ms.length - 1] = new MoveSet(new String[0],
               new int[0],
               new String[0],
               new String[0],
               new String[0],
               new String[0]);
       m_movesets = ms;
   }


To ModData (Reads the new species from the Mod data file) :

Code:
 
   private void addPokemonSpecies(String[] parts) {
       int species = m_species.getSpeciesCount();
       String name = parts[0];
       //Create base stats. Might need some modification to check for
       //negative stats, but this does well enough for now.
       int[] base = new int[6];
       base[Pokemon.S_HP] = Integer.valueOf(parts[1]).intValue();
       base[Pokemon.S_ATTACK] = Integer.valueOf(parts[2]).intValue();
       base[Pokemon.S_DEFENCE] = Integer.valueOf(parts[3]).intValue();
       base[Pokemon.S_SPEED] = Integer.valueOf(parts[4]).intValue();
       base[Pokemon.S_SPATTACK] = Integer.valueOf(parts[5]).intValue();
       base[Pokemon.S_SPDEFENCE] = Integer.valueOf(parts[6]).intValue();
       //Create type(s)
       mechanics.PokemonType[] types;
       mechanics.PokemonType t1 = mechanics.PokemonType.getType(parts[7]);
       mechanics.PokemonType t2 = mechanics.PokemonType.getType(parts[8]);
       if (t1 == null) {
           System.out.println("Incorrect type for " + name + ". Creation failed.");
           return;
       }
       if (t2 == null) {
           types = new mechanics.PokemonType[]{
               t1
           };
       } else {
           types = new mechanics.PokemonType[]{
               t1, t2
           };
       }
       //Create gender
       String str = parts[9];
       int gen;
       if (str.equals("Male")) {
           gen = PokemonSpecies.GENDER_MALE;
       } else if (str.equals("Female")) {
           gen = PokemonSpecies.GENDER_FEMALE;
       } else if (str.equals("Both")) {
           gen = PokemonSpecies.GENDER_BOTH;
       } else if (str.equals("None")) {
           gen = PokemonSpecies.GENDER_NONE;
       } else {
           System.out.println("Incorrect gender for " + name + ". Creation failed.");
           return;
       }
       //Add the new PokemonSpecies to the existing ones
       m_species.addSpecies(new PokemonSpecies(species, name, base, types, gen));
       m_moveSets.newSpecies();
   }


And finally, the method parsePatchLine in ModData must be edited (to find the addition lines from the Mod data file). The whole method isn't posted, just the beginning part (seeing as the method is pretty long). New code is seperated by comments starting and ending with two -'s :

Code:
 
   private void parsePatchLine(String line, int category) {
       // Collapse white space.
       line = line.replaceAll("[ \\n\\r\\t]+", " ");
       // Find the colon between the pokemon name and the data.
       int idx = line.indexOf(':');
       if (idx == -1) {
           System.out.println("Malformed patch file statement: " + line);
           return;
       }
       String species = line.substring(0, idx).trim();
       //--New code: Checks if we're adding a Pokemon--
       if (species.equals("Add Pokemon")) {
           String[] parts = line.substring(idx + 1).trim().split(" *, *");
           addPokemonSpecies(parts);
           return;
       }
       //--End of new code.--
       int id = m_species.getPokemonByName(species);
       if (id == -1) {
           System.out.println("Warning: no existing species of " + species + ".");
           return;
       }
       //...


Then, all the necessary changes are done in the modData file. I tested this by creating the pokemon Red X (you can start guessing where I got my inspiration from). The mod data for creating it is the following:

Code:
 
Add Pokemon: Red X, 110, 110, 110, 110, 110, 110, Normal, None, Both;
Red X: a+Levitate, a+Drizzle, Spore, Surf, Dragon Pulse, Power Gem, Return, Hidden Power, Flash Cannon;


Now, here's the creation progress step-by-step.

Code:
 
Add Pokemon:

Commands the code to add a pokemon. Must be capitalized correctly!

Code:
 
Red X,

The name.

Code:
 
110, 110, 110, 110, 110, 110,

Base stats, in the order of Hp, Attack, Defense, Speed, Sp.Attack, Sp.Defense.

Code:
 
Normal,

First type. Remember correct capitalization!

Code:
 
None,

Second type. For Monotyped pokemon, just put None in here (or well, anything that isn't a type). Remember correct capitalization!

Code:
 
Both;

Gender. Options are Male, Female, Both and None. Remember correct capitalization!

Code:
 
Red X: a+Levitate, a+Drizzle, Spore, Surf, Dragon Pulse, Power Gem, Return, Hidden Power, Flash Cannon;


Mods the pokemon to add moves and abilities to it. Thanks to it having no abilities to start with, shoddy posts "Warning: problematic abilities for <insert name here>." This doesn't hinder the creation progress at all, as long as you have remembered to give the pokemon abilities (haven't tried without, but there's really no point to use it without adding an ability).

AA edit: The standard commands for altering a mod file are

Pokemon Name: Move, Move2, a+Ability, a+Ability2, a+Ability3, -RemovedMove, ~IllegalMove+Combination;

Back to PT8Sceptile's excellent post now.

There are still some side-effects for not having a sprite, but battling is entirely possible with pokemon created like this. I have only tested battling with it three times, though, so I might have overlooked something.
There's no sig here at all. I ate it.
(and that means that I couldn't think of any good sig ideas >_>)
Offline Profile Quote Post Goto Top
 
+Amazing Ampharos
Tangela
[ *  *  *  *  *  *  *  * ]
Code:
 
/*
* ModData.java
*
* Created on May 12, 2007, 5:31 PM
*
* This file is a part of Shoddy Battle.
* Copyright (C) 2007  Colin Fitzpatrick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* The Free Software Foundation may be visited online at http://www.fsf.org.
*/

package shoddybattle;
import java.util.*;
import java.util.prefs.Preferences;
import java.io.*;
import mechanics.moves.*;
import mechanics.statuses.items.*;
import mechanics.statuses.abilities.IntrinsicAbility;

/**
* <p>This class encapsulates a complete set of "moddata". Mod data does not
* just include a patch against the pokemon data. In fact, a ModData object
* contains all of the following:
*
* <ul>
* <li>A UUID identifying the server the ModData came from
* <li>A pokemon species database
* <li>A move sets database
* <li>An items database
* <li>A list of moves
* </ul>
*
* @author Colin
*/
public class ModData {
   
   /**
    * An illegal moveset.
    */
   private static class IllegalMoveSet implements Serializable {
       public String[] move;
       public String ability;
   }
   
   /**
    * The mod data file name on the server.
    */
   public static final File MOD_DATA_FILE = new File("moddata");
   
   /**
    * The registry key holding the storage location on the client.
    */
   private static final String REGISTRY_KEY = "storage_location";
   
   /**
    * Cache of mod data.
    */
   private static final Map m_map = Collections.synchronizedMap(new HashMap());
   private static final ModData m_default;
   
   /**
    * Length of the mod data file.
    */
   private long m_dataLength = 0;
   
   /**
    * The actual mod data.
    */
   private String m_uuid;
   private PokemonSpeciesData m_species;
   private MoveSetData m_moveSets;
   private HoldItemData m_items;
   private MoveList m_moves;
   private Map m_illegal;
   
   static {
       m_default = new ModData();
       m_default.m_species = PokemonSpecies.getDefaultData();
       m_default.m_moveSets = MoveSet.getDefaultData();
       m_default.m_items = HoldItem.getDefaultData();
       m_default.m_moves = MoveList.getDefaultData();
       m_default.m_illegal = new HashMap();
       m_map.put(null, m_default);
   }
   
   /**
    * Get the name of the ModData.
    */
   public String getName() {
       return m_uuid;
   }
   
   /**
    * Return the ModData object corresponding to the given name, attempting
    * to load from disc if required.
    */
   public static ModData getModData(String name) {
       Object o = m_map.get(name);
       if (o != null) {
           return (ModData)o;
       }
       File f = new File(getStorageLocation() + name);
       if (!f.exists()) {
           return null;
       }
       return new ModData(f);
   }
   
   /**
    * Get the default ModData.
    */
   public static ModData getDefaultData() {
       return m_default;
   }
   
   /**
    * Get the species data.
    */
   public PokemonSpeciesData getSpeciesData() {
       return m_species;
   }
   
   /**
    * Get the move set data.
    */
   public MoveSetData getMoveSetData() {
       return m_moveSets;
   }
   
   /**
    * Get the hold item data.
    */
   public HoldItemData getHoldItemData() {
       return m_items;
   }
   
   /**
    * Get the move data.
    */
   public MoveList getMoveData() {
       return m_moves;
   }
   
   /**
    * Save mod data (species, abilities, move sets, and items) to a file
    * which can be opened by a client to allow for creating items that
    * will play on this mod server.
    */
   public void saveModData(OutputStream output) {
       try {
           m_species.saveSpeciesDatabase(output, true);
           m_moveSets.saveToFile(output);
           m_items.saveItemData(output);
           m_moves.saveMoveList(output);
           output.write(0); // Allows for simple EOF testing.
           ObjectOutputStream stream = new ObjectOutputStream(output);
           stream.writeObject(m_illegal);
           stream.flush();
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
   
   /**
    * Set the length of the mod data file.
    */
   public void setModDataLength(long length) {
       m_dataLength = length;
   }
   
   /**
    * Get the length of the mod data file.
    */
   public long getModDataLength() {
       return m_dataLength;
   }
   
   /**
    * Private constructor.
    */
   private ModData() {
       
   }
   
   /**
    * Construct a new ModData object via a file.
    */
   public ModData(File f) {
       loadModData(f);
   }
   
   /**
    * Load mod data (@see saveModData) from a file.
    */
   public void loadModData(File f) {
       try {
           FileInputStream input = new FileInputStream(f);
           m_uuid = f.getName();
           m_species = new PokemonSpeciesData();
           m_species.loadSpeciesDatabase(input, false);
           m_moveSets = new MoveSetData();
           m_moveSets.loadFromFile(input);
           m_moveSets.pruneMoveSet(); // Slow, but avoids errors.
           m_items = new HoldItemData();
           m_items.loadItemData(input);
           m_moves = new MoveList(false);
           m_moves.loadMoveList(input);
           if (input.read() != -1) {
               ObjectInputStream stream = new ObjectInputStream(input);
               try {
                   m_illegal = (Map)stream.readObject();
               } catch (Exception e) {
                   e.printStackTrace();
               }
           } else {
               m_illegal = new HashMap();
           }
           input.close();
           
           m_species.cacheMoveSets(m_moves, m_moveSets, false);
           m_map.put(m_uuid, this);
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
   
   /**
    * Remove a set of items from an array.
    */
   private void removeMoves(String[][] haystack, String[] needles) {
       for (int i = 0; i < haystack.length; ++i) {
           String[] layer = haystack[i];
           for (int j = 0; j < layer.length; ++j) {
               String strand = layer[j];
               for (int k = 0; k < needles.length; ++k) {
                   if (needles[k].equalsIgnoreCase(strand)) {
                       layer[j] = null;
                       break;
                   }
               }
           }
       }
   }
   
   /**
    * Handle the moves from a mod data line.
    */
   private void handleMoves(int species, ArrayList moves, int category) {
       MoveSet set = m_moveSets.getMoveSet(species);
       ArrayList removals = new ArrayList();
       ArrayList additions = new ArrayList();
       Iterator i = moves.iterator();
       while (i.hasNext()) {
           String item = (String)i.next();
           char c = item.charAt(0);
           if (c == '-') {
               removals.add(item.substring(1).trim());
           } else {
               String move;
               if (c == '+') {
                   move = item.substring(1);
               } else {
                   move = item;
               }
               additions.add(move.trim());
           }
       }
       String[][] arr = set.getMoves();
       removeMoves(arr, (String[])removals.toArray(new String[removals.size()]));
       ArrayList update = new ArrayList(Arrays.asList(arr[category]));
       update.addAll(additions);
       arr[category] = (String[])update.toArray(new String[update.size()]);
   }
   
   /**
    * Handle the abilities in a mod data line.
    */
   private void handleAbilities(String species, ArrayList abilities) {
       String arr[] = m_species.getAbilityNames(species);
       if (arr == null) {
           System.out.println("Warning: problematic abilities for " + species + ".");
           arr = new String[0];
       }
       ArrayList names =
               new ArrayList(Arrays.asList(arr));
       Iterator i = abilities.iterator();
       while (i.hasNext()) {
           String item = (String)i.next();
           char c = item.charAt(1);
           String name = item.substring(2).trim();
           if (c == '+') {
               /**if (IntrinsicAbility.getInstance(name) == null) {
                   System.out.println("Warning: no such ability: " + name);
               }**/
               names.add(name);
           } else {
               names.remove(name);
           }
       }
       m_species.setAbilities(species,
               (String[])names.toArray(new String[names.size()]),
               true);
   }
   
   /**
    * Handle the items in a mod data line.
    */
   private void handleItems(String species, ArrayList items) {
       Iterator i = items.iterator();
       while (i.hasNext()) {
           String item = (String)i.next();
           char c = item.charAt(1);
           String name = item.substring(2).trim();
           if (c == '+') {
               m_items.addExclusiveItem(name, species);
           } else {
               m_items.removeExclusiveItem(name, species);
           }
       }
   }
   
   /**
    *  Handle a stat modification.
    */
   private void modifyStat(int species, String part) {
       String[] parts = part.split(" *: *");
       String stat = parts[0].toLowerCase();
       final String[] stats = { "hp", "atk", "def", "spd", "satk", "sdef" };
       int value = Integer.valueOf(parts[1]).intValue();
       int i = 0;
       for (; i < stats.length; ++i) {
           if (stats[i].equalsIgnoreCase(stat)) {
               break;
           }
       }
       if (i != stats.length) {
           int[] base = m_species.getSpecies(species).getBaseStats();
           base[i] = value;
       } else {
           System.out.println("Could not identify stat: " + stat);
       }
   }
   
   /**
    * Validate a particular moveset.
    */
   public void validateMoveSet(int species, String[] move, String ability)
           throws ValidationException {
       Object o = m_illegal.get(new Integer(species));
       if (o == null) {
           return;
       }
       List l = (List)o;
       Iterator i = l.iterator();
       while (i.hasNext()) {
           IllegalMoveSet ms = (IllegalMoveSet)i.next();
           if (ms.ability != null) {
               if (!ms.ability.equals(ability)) {
                   continue;
               }
           }
           boolean legal = false;
           for (int j = 0; j < ms.move.length; ++j) {
               String entry = ms.move[j];
               boolean hasMove = false;
               for (int k = 0; k < move.length; ++k) {
                   if (entry.equals(move[k])) {
                       hasMove = true;
                       break;
                   }
               }
               if (!hasMove) {
                   legal = true;
                   break;
               }
           }
           if (!legal) {
               StringBuffer buffer = new StringBuffer("It is illegal for "
                       + "this pokemon to have the combination of ");
               buffer.append(ms.move[0]);
               for (int j = 1; j < ms.move.length; ++j) {
                   buffer.append(", ");
                   buffer.append(ms.move[j]);
               }
               if (ms.ability != null) {
                   buffer.append(", ");
                   buffer.append(ms.ability);
               }
               buffer.append(".");
               throw new ValidationException(new String(buffer));
           }
       }
   }
   
   /**
    * Handle an illegal moveset.
    */
   private void handleIllegalMoveSet(int species, String moveset) {
       String[] parts = moveset.split(" *\\+ *");
       List move = new ArrayList();
       String ability = null;
       for (int i = 0; i < parts.length; ++i) {
           String part = parts[i].trim();
           if (part.startsWith("[a]")) {
               ability = part.substring(3);
           } else {
               move.add(part);
           }
       }
       IllegalMoveSet item = new IllegalMoveSet();
       item.move = (String[])move.toArray(new String[move.size()]);
       item.ability = ability;
       Integer i = new Integer(species);
       Object o = m_illegal.get(i);
       if (o != null) {
           List l = (List)o;
           l.add(item);
       } else {
           List l = new ArrayList();
           l.add(item);
           m_illegal.put(i, l);
       }
   }
   
   /**
    * Handle one line of a data patch file.
    */
   private void parsePatchLine(String line, int category) {
       // Collapse white space.
       line = line.replaceAll("[ \\n\\r\\t]+", " ");
       // Find the colon between the pokemon name and the data.
       int idx = line.indexOf(':');
       if (idx == -1) {
           System.out.println("Malformed patch file statement: " + line);
           return;
       }
       String species = line.substring(0, idx).trim();
       if (species.equals("Add Pokemon")) {
           String[] parts = line.substring(idx + 1).trim().split(" *, *");
           addPokemonSpecies(parts);
           return;
       }
       int id = m_species.getPokemonByName(species);
       if (id == -1) {
           System.out.println("Warning: no existing species of " + species + ".");
           return;
       }
       ArrayList moves = new ArrayList();
       ArrayList abilities = new ArrayList();
       ArrayList items = new ArrayList();
       String[] parts = line.substring(idx + 1).trim().split(" *, *");
       for (int i = 0; i < parts.length; ++i) {
           String part = parts[i];
           int length = part.length();
           if (length == 0) {
               //System.out.println("Warning: empty element: " + line);
               continue;
           }
           if (part.charAt(0) == '~') {
               handleIllegalMoveSet(id, part.substring(1).trim());
               continue;
           }
           if (part.indexOf(':') != -1) {
               modifyStat(id, part.trim());
               continue;
           }
           char s = (length > 1) ? part.charAt(1) : '\0';
           boolean sign = (length > 1) ? ((s == '+') || (s == '-')) : false;
           switch (part.charAt(0)) {
               case 'a':
                   if (sign) {
                       // It's an ability.
                       abilities.add(part);
                       break;
                   }
               case 'i':
                   if (sign) {
                       // It's an item.
                       items.add(part);
                       break;
                   }
               default:
                   // It's a move.
                   moves.add(part);
                   break;
           }
       }
       handleMoves(id, moves, category);
       handleAbilities(species, abilities);
       handleItems(species, items);
   }
   
   public void applyPatch(InputStream stream) throws IOException {
       applyPatch(stream, 0);
   }
   
   /**
    * Apply a mod data patch to this ModData object.
    */
   public void applyPatch(InputStream stream, int category) throws IOException {
       DataInputStream in = new DataInputStream(stream);
       while (true) {
           StringBuffer buffer = new StringBuffer();
           while (true) {
               try {
                   byte c = in.readByte();
                   if (c == ';') {
                       break;
                   }
                   buffer.append((char)(c & 0xff));
               } catch (EOFException e) {
                   return;
               }
           }
           try {
               parsePatchLine(buffer.toString(), category);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
   }
   
   /**
    * Get the location where mod data is stored on the hard disc.
    */
   public static String getStorageLocation() {
       Preferences prefs = Preferences.userRoot();
       return prefs.get(REGISTRY_KEY, null);
   }
   
   /**
    * Set the location where mod data is stored on the hard disc.
    */
   public static void setStorageLocation(String value) {
       Preferences prefs = Preferences.userRoot();
       value.replace('/', File.separatorChar);
       value.replace('\\', File.separatorChar);
       if (!value.endsWith(File.separator)) {
           value += File.separator;
       }
       prefs.put(REGISTRY_KEY, value);
   }
   
   /**
    * Add a server to the map of uuid -> server name.
    */
   public static void addServer(String uuid, String name) {
       Preferences.userRoot().put("map." + uuid, name);
   }
   
   /**
    * Find a server name given its uuid.
    */
   public static String getServerName(String uuid) {
       return Preferences.userRoot().get("map." + uuid, null);
   }
   
   /**
    * Add a new Pokemon Species via a mod file.
    */
   private void addPokemonSpecies(String[] parts) {
       int species = m_species.getSpeciesCount();
       String name = parts[0];
       //Create base stats. Might need some modification to check for
       //negative stats, but this does well enough for now.
       int[] base = new int[6];
       base[Pokemon.S_HP] = Integer.valueOf(parts[1]).intValue();
       base[Pokemon.S_ATTACK] = Integer.valueOf(parts[2]).intValue();
       base[Pokemon.S_DEFENCE] = Integer.valueOf(parts[3]).intValue();
       base[Pokemon.S_SPEED] = Integer.valueOf(parts[4]).intValue();
       base[Pokemon.S_SPATTACK] = Integer.valueOf(parts[5]).intValue();
       base[Pokemon.S_SPDEFENCE] = Integer.valueOf(parts[6]).intValue();
       //Create type(s)
       mechanics.PokemonType[] types;
       mechanics.PokemonType t1 = mechanics.PokemonType.getType(parts[7]);
       mechanics.PokemonType t2 = mechanics.PokemonType.getType(parts[8]);
       if (t1 == null) {
           System.out.println("Incorrect type for " + name + ". Creation failed.");
           return;
       }
       if (t2 == null) {
           types = new mechanics.PokemonType[]{
               t1
           };
       } else {
           types = new mechanics.PokemonType[]{
               t1, t2
           };
       }
       //Create gender
       String str = parts[9];
       int gen;
       if (str.equals("Male")) {
           gen = PokemonSpecies.GENDER_MALE;
       } else if (str.equals("Female")) {
           gen = PokemonSpecies.GENDER_FEMALE;
       } else if (str.equals("Both")) {
           gen = PokemonSpecies.GENDER_BOTH;
       } else if (str.equals("None")) {
           gen = PokemonSpecies.GENDER_NONE;
       } else {
           System.out.println("Incorrect gender for " + name + ". Creation failed.");
           return;
       }
       //Add the new PokemonSpecies to the existing ones
       m_species.addSpecies(new PokemonSpecies(species, name, base, types, gen));
       m_moveSets.newSpecies();
   }
   
}


Code:
 
/*
* MoveSetData.java
*
* Created on May 19, 2007, 4:36 PM
*
* This file is a part of Shoddy Battle.
* Copyright (C) 2007  Colin Fitzpatrick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* The Free Software Foundation may be visited online at http://www.fsf.org.
*/

package mechanics.moves;
import java.io.*;
import java.util.*;
import java.net.URL;

/**
*
* @author Colin
*/
public class MoveSetData {
   
   /**
    * Set of all move sets.
    */
   private MoveSet[] m_movesets = null;
   
   /**
    * Save the move sets to a file.
    */
   public void saveToFile(File f) {
       try {
           FileOutputStream file = new FileOutputStream(f);
           saveToFile(file);
           file.close();
       } catch (FileNotFoundException e) {
           
       } catch (IOException e) {
           
       }
   }
   
   /**
    * Save the move sets to an arbitrary output stream.
    */
   public void saveToFile(OutputStream output) {
       try {
           ObjectOutputStream obj = new ObjectOutputStream(output);
           obj.writeObject(m_movesets);
           obj.flush();
       } catch (IOException e) {
           System.out.println(e.getMessage());
       }
   }
   
   /**
    * Prune the move set of null entries.
    * This is slow and shoddy.
    */
   public void pruneMoveSet() {
       for (int i = 0; i < m_movesets.length; ++i) {
           if (m_movesets[i] == null) {
               continue;
           }
           String[][] categories = m_movesets[i].getMoves();
           for (int j = 0; j < categories.length; ++j) {
               ArrayList moves = new ArrayList(Arrays.asList(categories[j]));
               Iterator k = moves.iterator();
               while (k.hasNext()) {
                   if (k.next() == null) {
                       k.remove();
                   }
               }
               categories[j] = (String[])moves.toArray(new String[moves.size()]);
           }
       }
   }
   
   /**
    * Load the move sets in from a URL.
    */
   public void loadFromFile(URL url) {
       try {
           InputStream input = url.openStream();
           loadFromFile(input);
           input.close();
       } catch (IOException e) {
           
       }
   }
   
   /**
    * Load the move sets in from a file.
    */
   public void loadFromFile(String str) {
       try {
           File f = new File(str);
           InputStream file = new FileInputStream(f);
           loadFromFile(file);
           file.close();
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
   
   /**
    * Load the move sets from an input stream.
    */
   public void loadFromFile(InputStream file) {
       try {
           ObjectInputStream obj = new ObjectInputStream(file);
           m_movesets = (MoveSet[])obj.readObject();
       } catch (IOException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
   }
   
   /**
    * Return the number of move sets.
    */
   public int getMoveSetCount() {
       return m_movesets.length;
   }
   
   /**
    * Merge the full advance and d/p move databases together.
    */
   public static void main(String[] args) throws Exception {
       class Pair {
           public String first, second;
           Pair(String f, String s) {
               first = f;
               second = s;
           }
       }
       
       /**Pair[] inheritance = {
           new Pair("Sneasel", "Weavile"),
           new Pair("Magneton", "Magnezone"),
           new Pair("Lickitung", "Lickilicky"),
           new Pair("Rhydon", "Rhyperior"),
           new Pair("Tangela", "Tangrowth"),
           new Pair("Electabuzz", "Electivire"),
           new Pair("Magmar", "Magmortar"),
           new Pair("Togetic", "Togekiss"),
           new Pair("Yanma", "Yanmega"),
           new Pair("Eevee", "Leafeon"),
           new Pair("Eevee", "Glaceon"),
           new Pair("Gligar", "Gliscor"),
           new Pair("Piloswine", "Mamoswine"),
           new Pair("Porygon2", "Porygonz"),
           new Pair("Kirlia", "Gallade"),
           new Pair("Nosepass", "Probopass"),
           new Pair("Dusclops", "Dusknoir"),
           new Pair("Budew", "Roselia"),
           new Pair("Roselia", "Roserade"),
           new Pair("Aipom", "Ambipom"),
           new Pair("Misdreavus", "Mismagius"),
           new Pair("Murkrow", "Honchkrow"),
           new Pair("Chingling", "Chimecho"),
           new Pair("Bonsly", "Sudowoodo"),
           new Pair("Mime Jr.", "Mr. Mime"),
           new Pair("Happiny", "Chansey"),
           new Pair("Chansey", "Blissey"),
           new Pair("Munchlax", "Snorlax"),
           new Pair("Mantyke", "Mantine"),
       };
       
       Properties props = shoddybattle.Main.getProperties("server.properties");
       shoddybattle.Main.initialise(props);
       shoddybattle.ModData data = shoddybattle.ModData.getDefaultData();
       data.applyPatch(new FileInputStream(new File("movesetfixes.patch")));
       shoddybattle.PokemonSpeciesData species = data.getSpeciesData();
       MoveSetData moves = data.getMoveSetData();
       
       for (int i = 0; i < inheritance.length; ++i) {
           Pair pair = inheritance[i];
           System.out.println(pair.second + " inherits from " + pair.first);
           MoveSet base = moves.getMoveSet(species.getPokemonByName(pair.first));
           MoveSet extension = moves.getMoveSet(species.getPokemonByName(pair.second));
           String[][] moveset = base.getMoves();
           for (int j = 0; j < 5; ++j) {
               extension.mergeMoves(j, moveset[j]);
           }
       }
       
       moves.saveToFile(new File("dpmovesets.db"));
       
       if (Math.abs(0) == 0)
           return;*/
       
       Pair[] changes = {
           new Pair("Ancient Power", "Ancientpower"),
           new Pair("Bubble Beam", "Bubblebeam"),
           new Pair("Double Edge", "Double-edge"),
           new Pair("Self Destruct", "Selfdestruct"),
           new Pair("Sketch", null),
           new Pair("Snore Swagger", "Swagger"),
           new Pair("Will-O-Wisp", "Will-o-wisp"),
           new Pair("Lock-On", "Lock-on"),
           new Pair("X-scissor", "X-Scissor"),
           new Pair("Sand-attack", "Sand-Attack"),
           new Pair("Fly~ Surf + Reversal", null),
           new Pair("Roar of Time", "Roar Of Time"),
           new Pair("Mud-slap", "Mud-Slap")
       };
       
       Properties props = shoddybattle.Main.getProperties("server.properties");
       shoddybattle.Main.initialise(props);
       shoddybattle.ModData data = shoddybattle.ModData.getDefaultData();
       //data.getMoveSetData().loadFromFile("dpmovesets.db");
       data.applyPatch(new FileInputStream(new File("morefixes.patch")), 1);
       //data.applyPatch(new FileInputStream(new File("movesetfixes.patch")), 1);
       //data.applyPatch(new FileInputStream(new File("nypc.patch")));
       //data.applyPatch(new FileInputStream(new File("smeargle.mod")));
       //data.applyPatch(new FileInputStream(new File("magneton.patch")), 4);
       /**MoveSetData moves = data.getMoveSetData();
       MoveSetData dp = new MoveSetData();
       dp.loadFromFile("dpmovesets.db");
       moves.pruneMoveSet();
       dp.pruneMoveSet();
       data.getMoveSetData().pruneMoveSet();
       int count = data.getMoveSetData().getMoveSetCount();
       for (int i = 0; i < count; ++i) {
           MoveSet set = data.getMoveSetData().getMoveSet(i);
           //MoveSet advanceSet = moves.getMoveSet(i);
           for (int j = 0; j < 5; ++j) {
               if (j == 3) continue; // Do not pass HMs!
               //if (advanceSet != null) {
                   //set.mergeMoves(j, advanceSet.getMoves()[j]);
                   String[] strs = set.getMoves()[j];
                   if (strs == null)
                       continue;
                   for (int k = 0; k < strs.length; ++k) {
                       for (int l = 0; l < changes.length; ++l) {
                           if (strs[k].equals(changes[l].first)) {
                               strs[k] = changes[l].second;
                               break;
                           }
                       }
                   }
               //}
           }
       }**/
       data.getMoveSetData().saveToFile(new File("dpmovesets.db"));
   }
   
   /**
    * Get the move set identified by the parameter.
    */
   public MoveSet getMoveSet(int i) throws IllegalArgumentException {
       if ((i < 0) || (i >= m_movesets.length)) {
           throw new IllegalArgumentException("Index out of range.");
       }
       return m_movesets[i];
   }
   
   /**
    *Allows for new species to have new movepools.
    */
   public void newSpecies() {
       MoveSet[] ms = new MoveSet[m_movesets.length + 1];
       for (int i = 0; i < m_movesets.length; i++) {
           ms[i] = m_movesets[i];
       }
       ms[ms.length - 1] = new MoveSet(new String[0],
           new int[0],
           new String[0],
           new String[0],
           new String[0],
           new String[0]);
       m_movesets = ms;
   }
   
}
Offline Profile Quote Post Goto Top
 
+Amazing Ampharos
Tangela
[ *  *  *  *  *  *  *  * ]
Code:
 
/*
* PokemonSpeciesData.java
*
* Created on May 19, 2007, 4:49 PM
*
* This file is a part of Shoddy Battle.
* Copyright (C) 2007  Colin Fitzpatrick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* The Free Software Foundation may be visited online at http://www.fsf.org.
*/

package shoddybattle;
import mechanics.PokemonType;
import mechanics.moves.*;
import java.io.*;
import java.util.*;
import mechanics.statuses.abilities.IntrinsicAbility;

/**
*
* @author Colin
*/
public class PokemonSpeciesData {
   
   private HashMap m_abilities = new HashMap();
   private HashMap m_ablNames = new HashMap();
   private TreeSet m_unimplemented = new TreeSet();
   private long m_lastModified;
   
   /**
    * A cache of movesets for each species where the origin of the move
    * has been removed, as this information is not relevant for the purpose
    * of validating pokemon. To speed the latter operation up, this cache
    * is useful. Call cacheMoveSets() to create this cache.
    */
   private TreeSet[] m_movesets = null;
   
   /**
    * Database of all pokemon species.
    */
   private PokemonSpecies[] m_database;
   
   /**
    * Get the date when the database was last modified.
    */
   public long getLastModified() {
       return m_lastModified;
   }

   /**
    * Save a database of pokemon species to a file.
    */
   public void saveSpeciesDatabase(File f) throws IOException {
       FileOutputStream output = new FileOutputStream(f);
       saveSpeciesDatabase(output, false);
       output.close();
   }
   
   /**
    * Save a database of pokemon speices to an arbitrary file.
    */
   public void saveSpeciesDatabase(OutputStream out, boolean requireImplementation) throws IOException {
       ObjectOutputStream stream = new ObjectOutputStream(out);
       stream.writeInt(m_database.length);
       for (int i = 0; i < m_database.length; ++i) {
           PokemonSpecies s = m_database[i];
           stream.writeObject(s.m_name);
           stream.writeObject(s.m_type);
           stream.writeObject(s.m_base);
           stream.writeInt(s.m_genders);
           if (requireImplementation) {
               TreeSet set = (TreeSet)m_abilities.get(s.m_name);
               String[] abilities = (String[])set.toArray(new String[set.size()]);
               stream.writeObject(abilities);
           } else {
               stream.writeObject((String[])m_ablNames.get(s.m_name));
           }
       }
       stream.flush();
   }
   
   /**
    * Load a database of pokemon species in from a file, and require that
    * abilities have been implemented.
    */
   public void loadSpeciesDatabase(File file)
           throws IOException, FileNotFoundException {
       loadSpeciesDatabase(file, true);
   }
   
   /**
    * Load a database of pokemon species in from a file.
    */
   public void loadSpeciesDatabase(File file, boolean requireImplementation)
           throws IOException, FileNotFoundException {
       m_lastModified = file.lastModified();
       FileInputStream input = new FileInputStream(file);
       loadSpeciesDatabase(input, requireImplementation);
       input.close();
   }
   
   /**
    * Load a database of pokemon species in from an input stream.
    */
   public void loadSpeciesDatabase(InputStream input,
           boolean requireImplementation) throws IOException {
       ObjectInputStream stream = new ObjectInputStream(input);
       int size = stream.readInt();
       m_abilities = new HashMap();
       m_ablNames = new HashMap();
       m_unimplemented = new TreeSet();
       m_database = new PokemonSpecies[size];
       for (int i = 0; i < size; ++i) {
           try {
               String name = (String)stream.readObject();
               PokemonType[] type = (PokemonType[])stream.readObject();
               int[] base = (int[])stream.readObject();
               int genders = stream.readInt();
               String[] ability = (String[])stream.readObject();
               
               setAbilities(name, ability, requireImplementation);
               m_database[i] = new PokemonSpecies(i, name, base, type, genders);
           } catch (ClassNotFoundException e) {
               throw new InternalError();
           }
       }
       
       Iterator i = m_unimplemented.iterator();
       while (i.hasNext()) {
           String ability = (String)i.next();
           System.out.println("Unimplemented intrinsic ability: " + ability);
       }
       m_unimplemented = null;
   }
   
   /**
    * Cache the move sets of all of the pokemon.
    */
   public void cacheMoveSets(MoveList moveList,
           MoveSetData moveSet,
           boolean requireImplementation) {
       // This function will double as an error catching mechanism for
       // unimplemented moves.
       TreeSet unimplemented = new TreeSet();
       HashSet implemented = new HashSet();
       
       m_movesets = new TreeSet[m_database.length];
       for (int i = 0; i < m_database.length; ++i) {
           MoveSet set = null;
           try {
               set = moveSet.getMoveSet(i);
           } catch (IllegalArgumentException e) { }
           if (set == null) {
               m_movesets[i] = null;
               continue;
           }
           String[][] moves = set.getMoves();
           TreeSet list = new TreeSet();
           for (int j = 0; j < moves.length; ++j) {
               if (!requireImplementation) {
                   list.addAll(Arrays.asList(moves[j]));
                   continue;
               }
               String[] entries = moves[j];
               for (int k = 0; k < entries.length; ++k) {
                   // We enter these manually rather than using addAll()
                   // so that we can verify that the moves are actually
                   // implemented.
                   String move = entries[k];
                   if (moveList.getMove(move) != null) {
                       // It is actually implemented.
                       list.add(move);
                       implemented.add(move);
                   } else {
                       /**
                        * Add this to the list of unimplemented moves for the
                        * sole purpose of calculating the percent that are
                        * implemented.
                        */
                        if (move != null) {
                           unimplemented.add(move);
                        }
                       
                       /**
                        * Remove this unimplemented move from this list so
                        * that the server doesn't send the client a list of
                        * moves containing unimplemented entries.
                        */
                       entries[k] = null;
                   }
               }
           }
           m_movesets[i] = list;
       }
       
       // Print out moves that were unimplemented.
       Iterator i = unimplemented.iterator();
       while (i.hasNext()) {
           String str = (String)i.next();
           System.out.println("Unimplemented move: " + str);
       }
       
       if (unimplemented.size() != 0) {
           System.out.println("There are "
                   + String.valueOf(unimplemented.size())
                   + " unimplemented moves.");
           double total = (double)(implemented.size() + unimplemented.size());
           double perc = ((double)implemented.size() / total) * 100.0;
           System.out.println("The move library is "
                   + String.valueOf(Math.round(perc))
                   + "% implemented.");
       }
   }
   
   /**
    * Add a pokemon's abilities to the HashMap.
    */
   public void setAbilities(String name, String[] abilities, boolean impl) {
       m_ablNames.put(name, abilities);
       SortedSet set = new TreeSet();
       if (abilities == null) {
           abilities = new String[0];
       }
       for (int i = 0; i < abilities.length; ++i) {
           String ability = abilities[i];
           if (impl && (IntrinsicAbility.getInstance(ability) == null)) {
               if (m_unimplemented != null) {
                   m_unimplemented.add(ability);
               }
           } else {
               set.add(ability);
           }
       }
       m_abilities.put(name, set);
   }
   
   /**
    * Return whether an ability is implemented.
    */
   public boolean isAbilityImplemented(String ability) {
       if (ability == null) {
           return false;
       }
       return !m_unimplemented.contains(ability);
   }
   
   /**
    * Return whether a pokemon can have a particular ability.
    */
   public boolean canUseAbility(String name, String ability) {
       if (ability == null) {
           return false;
       }
       SortedSet set = (SortedSet)m_abilities.get(name);
       if (set == null) {
           return false;
       }
       return set.contains(ability);
   }
   
   /**
    * Return an array of the names of the possible abilities a given pokemon
    * can have. Note that this will return unimplemented abilities as well
    * as implemented ones.
    */
   public String[] getAbilityNames(String name) {
       return (String[])m_ablNames.get(name);
   }
   
   /**
    * Return a TreeSet of possible abilities. This only includes abilities
    * that are actually implemented.
    */
   public SortedSet getPossibleAbilities(String name) {
       return (SortedSet)m_abilities.get(name);
   }
   
   /**
    * Get the species database.
    */
   public PokemonSpecies[] getSpecies() {
       return m_database;
   }
   
   /**
    * Get a single species.
    */
   public PokemonSpecies getSpecies(int i) throws PokemonException {
       if ((i < 0) || (i >= m_database.length))
           throw new PokemonException();
       return m_database[i];
   }
   
   /**
    * Get the whole list of species names.
    * Note: this call is *expensive*.
    */
   public String[] getSpeciesNames() {
       String[] names = new String[m_database.length];
       for (int i = 0; i < names.length; ++i) {
           names[i] = m_database[i].m_name;
       }
       return names;
   }
   
   /**
    * Return the number of species.
    */
   public int getSpeciesCount() {
       return m_database.length;
   }
   
   /**
    * Find a pokemon by name.
    */
   public int getPokemonByName(String name) {
       for (int i = 0; i < m_database.length; ++i) {
           if (m_database[i].getName().equalsIgnoreCase(name)) {
               return i;
           }
       }
       return -1;
   }
   
   /**
    * Return a TreeSet of moves that the pokemon can learn.
    */
   public TreeSet getLearnableMoves(int i) {
       return m_movesets[i];
   }
   
   /**
    * Return whether this species can learn a particular move.
    */
   public boolean canLearn(int i, String move) {
       TreeSet set = m_movesets[i];
       if (set == null) {
           return false;
       }
       return set.contains(move);
   }
   
   /**
    * Adds a new species.
    */
   public void addSpecies(PokemonSpecies s) {
       PokemonSpecies[] sp = new PokemonSpecies[m_database.length + 1];
       for (int i = 0; i < m_database.length; i++) {
           sp[i] = m_database[i];
       }
       sp[sp.length - 1] = s;
       m_database = sp;
  }
   
}
Offline Profile Quote Post Goto Top
 
1 user reading this topic (1 Guest and 0 Anonymous)
« Previous Topic · Server Suggestions and Announcements · Next Topic »
Add Reply