package org.pokenet.server.feature;
import java.util.ArrayList;
import java.util.Random;
import org.pokenet.server.battle.DataService;
import org.pokenet.server.battle.Pokemon;
import org.pokenet.server.battle.PokemonEgg;
import org.pokenet.server.battle.PokemonSpecies;
import org.pokenet.server.battle.mechanics.PokemonNature;
import org.pokenet.server.battle.mechanics.moves.MoveList;
import org.pokenet.server.battle.mechanics.moves.MoveListEntry;
/**
*
* @author ZombieBear
*
*/
public class BreedingLogic {
private Pokemon malePoke;
private Pokemon femalePoke;
/**
* Constructor
* @param poke1
* @param poke2
* @return
* @throws Exception
*/
public PokemonEgg generateEgg(Pokemon poke1, Pokemon poke2) throws Exception{
Pokemon poke = null;
if (canBreed(poke1, poke2)) {
try{
poke = generateHatchling(generateEggSpecies());
return new PokemonEgg(poke, 200);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("BreedingException: Egg generation issue");
}
} else {
throw new Exception("BreedingException: The given pokemon can't breed");
}
}
/**
* Returns true if the given pokemon are able to breed.
* @param poke1
* @param poke2
* @return
*/
public boolean canBreed(Pokemon poke1, Pokemon poke2) {
for (int i : PokemonSpecies.getDefaultData().getPokemonByName(
poke1.getName()).getCompatibility()) {
for (int x : PokemonSpecies.getDefaultData().getPokemonByName(
poke2.getName()).getCompatibility()) {
if (i == x) {
if (poke1.getGender() == Pokemon.GENDER_MALE
&& (poke2.getGender() == Pokemon.GENDER_FEMALE)
|| poke2.getSpeciesName() == "Ditto") {
malePoke = poke1;
femalePoke = poke2;
return true;
} else if (poke2.getGender() == Pokemon.GENDER_MALE
&& (poke1.getGender() == Pokemon.GENDER_FEMALE || poke1
.getSpeciesName() == "Ditto")) {
malePoke = poke2;
femalePoke = poke1;
return true;
} else if (poke1.getGender() == Pokemon.GENDER_NONE
&& poke2.getSpeciesName() == "Ditto") {
malePoke = poke1;
femalePoke = poke2;
return true;
}
}
}
}
return false;
}
/**
* Generates the new egg's species based on the parents
* @return the species number
*/
private int generateEggSpecies() {
// TODO: Add code for incenses!
// If the female pokemon is a ditto, species is set by the male parent
if (femalePoke.getSpeciesName() != "Ditto") {
// Nidoran species
if (femalePoke.getSpeciesName() == "NidoranF"
|| femalePoke.getSpeciesName() == "Nidorina"
|| femalePoke.getSpeciesName() == "Nidoqueen") {
if (DataService.getBattleMechanics().getRandom().nextInt(2) == 0)
return PokemonSpecies.getDefaultData().getPokemonByName("NidoranM").getSpeciesNumber();
else
return PokemonSpecies.getDefaultData().getPokemonByName("NidoranF").getSpeciesNumber();
}
// Volbeat and Illumise
else if (femalePoke.getSpeciesName() == "Illumise") {
if (DataService.getBattleMechanics().getRandom().nextInt(2) == 0)
return PokemonSpecies.getDefaultData().getPokemonByName("Illumise").getSpeciesNumber();
else
return PokemonSpecies.getDefaultData().getPokemonByName("Volbeat").getSpeciesNumber();
}
// Normal case
else
return femalePoke.getSpeciesNumber();
}
return malePoke.getSpeciesNumber();
}
/**
* Generates the baby pokemon's moves
* @param species
* @return
*/
public MoveListEntry[] getBabyMoves(int species) {
MoveListEntry[] moves = new MoveListEntry[4];
MoveList moveList = MoveList.getDefaultData();
ArrayList<MoveListEntry> possibleMoves = new ArrayList<MoveListEntry>();
PokemonSpecies s = PokemonSpecies.getDefaultData().getSpecies(species);
// List of moves by level 5
for (int i = 1; i <= 5; i++) {
if (s.getLevelMoves().containsKey(i)) {
possibleMoves.add(moveList.getMove(s.getLevelMoves().get(i)));
}
}
int moveNum = possibleMoves.size();
if (possibleMoves.size() <= 4) {
for (int i = 0; i < possibleMoves.size(); i++) {
moves[i] = possibleMoves.get(i);
}
} else {
for (int i = 0; i < moves.length; i++) {
if (possibleMoves.size() == 0)
moves[i] = null;
moves[i] = possibleMoves.get(moveNum);
moveNum--;
if (moveNum == 0)
break;
}
}
// Moves that both parents know
// List of egg moves
possibleMoves.clear();
for (int i = 0; i < s.getEggMoves().length; i++) {
for (int x = 0; i < 4; i++) {
if (malePoke.getMove(x) == moveList.getMove(s.getEggMoves()[i])) {
possibleMoves.add(moveList.getMove(s.getEggMoves()[i]));
}
}
}
for (int i = 0; i < 4; i++) {
if (moves[i] == null && possibleMoves.size() < i) {
moves[i] = possibleMoves.get(i);
}
}
return moves;
}
/**
* Generates the baby pokemon to hatch from the egg.
* @param species
* @return
* @throws Exception
*/
private Pokemon generateHatchling(int species) throws Exception{
Pokemon hatchling;
try{
PokemonSpecies speciesData = PokemonSpecies.getDefaultData()
.getSpecies(species);
Random random = DataService.getBattleMechanics().getRandom();
// get Nature if female or ditto is holding an everstone, 50% chance
String nature = "";
if (femalePoke.getItemName() == "Everstone") {
if (random.nextInt(2) == 0) {
nature = femalePoke.getNature().getName();
}
} else
nature = PokemonNature.getNature(
random.nextInt(PokemonNature.getNatureNames().length))
.getName();
int natureIndex = 0;
for (String name : PokemonNature.getNatureNames()) {
if (name == nature) {
break;
}
natureIndex++;
}
// Get 3 random IVS from parents
int[] ivs = new int[6];
for (int iv : ivs) {
ivs[iv] = speciesData.getBaseStats()[iv];
}
int[] attempt = new int[3];
for (int i = 0; i < 3; i++) {
int randomNum = DataService.getBattleMechanics().getRandom()
.nextInt(2);
attempt[i] = randomNum;
if (i == 2) {
if (attempt[0] == 0 && attempt[1] == 0) {
randomNum = 1;
} else if (attempt[0] == 1 && attempt[1] == 1) {
randomNum = 0;
}
}
int iv = DataService.getBattleMechanics().getRandom().nextInt(6);
if (randomNum == 0) {
ivs[iv] = malePoke.getBaseStats()[iv];
} else {
ivs[iv] = femalePoke.getBaseStats()[iv];
}
}
hatchling = new Pokemon(DataService.getBattleMechanics(),
PokemonSpecies.getDefaultData().getSpecies(species),
PokemonNature.getNature(natureIndex),
speciesData.getPossibleAbilities(PokemonSpecies.getDefaultData())[random
.nextInt(speciesData.getPossibleAbilities(
PokemonSpecies.getDefaultData()).length)], "", Pokemon
.generateGender(speciesData.getPossibleGenders()), 5,
ivs, new int[6], getBabyMoves(species), new int[4]);
} catch (Exception e) {
throw new Exception("BreedingException: Hatchling generation issue");
}
return hatchling;
}
}