Huge changes

Refactoring of Game
Adds and improves all comments
Restructures files
Improves items
Makes project into a maven project
This commit is contained in:
2020-02-16 02:36:26 +01:00
parent 72fc38b309
commit c5c4420ac0
26 changed files with 2087 additions and 1664 deletions

419
src/main/java/Game.java Normal file
View File

@@ -0,0 +1,419 @@
import items.*;
import pokemon.Pokemon;
import storage.Inventory;
import storage.Trainer;
import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.lang.NumberFormatException;
import java.text.NumberFormat;
import java.text.ParseException;
/** Simulates the game Pokémon */
public class Game {
public static final Scanner in = new Scanner(System.in);
private static Pokemon opponentPokemon;
private static List<Pokemon> availableOpponentPokemon;
private static Pokemon playersCurrentPokemon;
private static Trainer player;
public static void main(String[] args) {
availableOpponentPokemon = readPokemon();
int initialPokemon = availableOpponentPokemon.size();
System.out.println("What is your name?");
String name = in.nextLine();
player = new Trainer(name, randomTeam(), createInventory());
boolean done = false;
triggerNewEncounter();
while (!done) {
if (opponentPokemon == null) {
System.out.printf("You have brutally murdered %d pokemon.%n"
+ "The only ones left are the ones in your possession.%n"
+ "There really is nothing more for you to do here.%n", initialPokemon);
return;
}
if (player.getConsciousPokemon().size() < 1) {
System.out.println("All your pokemon have fainted. Your journey ends here.");
return;
}
while (playersCurrentPokemon == null || !playersCurrentPokemon.isConscious()) {
player.listAvailablePokemon(true);
playersCurrentPokemon = player.choosePokemon(true);
}
System.out.printf("Opponent: %s%nWhat will you do?%n", opponentPokemon);
System.out.printf("b: battle"
+ "%nh: heal or revive"
+ "%nt: throw pokeball"
+ "%nc: change pokemon"
+ "%nf: flee"
+ "%nv: view my pokemon"
+ "%ns: save"
+ "%nl: load"
+ "%nq: quit%n>");
char command = in.next().toLowerCase().charAt(0);
switch (command) {
case 'b':
battle();
break;
case 'h':
healPokemon();
break;
case 't':
throwPokeBall();
break;
case 'c':
choosePokemon();
break;
case 's':
save();
break;
case 'l':
load();
break;
case 'f':
flee();
break;
case 'v':
showPokemon();
break;
case 'q':
done = true;
break;
default:
System.out.println("[Invalid command]");
}
}
}
/**
* Lists all of the player's pokemon
*/
private static void showPokemon() {
player.printPokemon();
}
/**
* Tries to flee from the current opponent
*/
private static void flee() {
boolean fleeSuccessful = playersCurrentPokemon.flee(opponentPokemon);
if (fleeSuccessful) {
System.out.println("You fled the battle.");
triggerNewEncounter();
} else {
System.out.printf("Failed to flee from %s.%n", opponentPokemon.getName());
opponentPokemon.attack(playersCurrentPokemon);
}
}
/**
* Loads game information from a save
*/
private static void load() {
List<Pokemon> loadedPokemon = loadPokemon("pokemon.save");
List<Pokemon> loadedUsersPokemon = loadPokemon("user.save");
Inventory loadedInventory = loadInventory("inventory.save");
if (loadedPokemon == null || loadedUsersPokemon == null || loadedInventory == null) {
System.out.println("One or more savefiles seem corrupt or missing. Please delete, create or fix the affected file(s).");
} else {
availableOpponentPokemon = loadedPokemon;
player.setPokemon(loadedUsersPokemon);
player.setInventory(loadedInventory);
if (availableOpponentPokemon.size() > 0 && player.getPokemon().size() > 0) {
do {
player.listAvailablePokemon(true);
playersCurrentPokemon = player.choosePokemon(true);
} while (playersCurrentPokemon == null || !playersCurrentPokemon.isConscious());
opponentPokemon = randomPokemon(availableOpponentPokemon);
}
}
}
/**
* Saves all stats about the game
*/
private static void save() {
savePokemon(availableOpponentPokemon, "pokemon.save");
savePokemon(player.getPokemon(), "user.save");
saveInventory(player.getInventory(), "inventory.save");
}
/**
* Chooses a new pokemon from the player's available pokemon
*/
private static void choosePokemon() {
player.listAvailablePokemon(true);
playersCurrentPokemon = player.choosePokemon(true);
while (playersCurrentPokemon == null) {
player.listAvailablePokemon(true);
playersCurrentPokemon = player.choosePokemon(true);
}
opponentPokemon.attack(playersCurrentPokemon);
}
/**
* Makes the player's pokemon attack the enemy pokemon
*/
private static void battle() {
if (opponentPokemon.isConscious() && playersCurrentPokemon.isConscious()) {
playersCurrentPokemon.attack(opponentPokemon);
if (opponentPokemon.isConscious()) {
opponentPokemon.attack(playersCurrentPokemon);
if (!playersCurrentPokemon.isConscious()) {
System.out.println("Your pokemon fainted.");
}
} else {
pokemonFainted(availableOpponentPokemon, opponentPokemon);
System.out.println("The opponent pokemon fainted.");
triggerNewEncounter();
}
}
}
/**
* Heals a pokemon if possible
*/
private static void healPokemon() {
if (player.getInventory().getPotions().size() > 0) {
player.getInventory().availablePotions();
AbstractPotion currentPotion = player.getInventory().getChosenPotion();
if (currentPotion == null) {
in.nextLine();
System.out.println("Invalid potion.");
} else {
Pokemon pokemonToHeal;
if (currentPotion.needsAlive()) {
player.listAvailablePokemon(true);
pokemonToHeal = player.choosePokemon(true);
} else {
player.listAvailablePokemon(false);
pokemonToHeal = player.choosePokemon(false);
}
if (pokemonToHeal == null) {
System.out.println("That is not a valid pokemon");
} else {
if (currentPotion.use(pokemonToHeal)) {
player.getInventory().addItem(currentPotion, -1);
opponentPokemon.attack(playersCurrentPokemon);
}
}
}
} else {
System.out.println("You have used all your healing items.");
}
}
/**
* Tries throwing a poke ball at the enemy pokemon
*/
private static void throwPokeBall() {
if (player.getInventory().getPokeBalls().size() > 0) {
player.getInventory().availablePokeBalls();
AbstractPokeBall currentPokeBall = player.getInventory().getChosenPokeBall();
if (currentPokeBall == null) {
in.nextLine();
System.out.println("Invalid pokeball.");
} else {
boolean captured = currentPokeBall.use(opponentPokemon, availableOpponentPokemon, player);
player.getInventory().addItem(currentPokeBall, -1);
if (captured) {
triggerNewEncounter();
} else {
opponentPokemon.attack(playersCurrentPokemon);
}
}
} else {
System.out.println("You have used all your pokeballs.");
}
}
/**
* Triggers an encounter with a new wild pokemon
*/
private static void triggerNewEncounter() {
opponentPokemon = randomPokemon(availableOpponentPokemon);
System.out.printf("A wild %s appeared.%n", opponentPokemon.getName());
}
/**
* Removes a fainted pokemon from encounter-able pokemon
* @param pokemonList <p>List of pokemon to search</p>
* @param target <p>The pokemon to remove</p>
*/
public static void pokemonFainted(List<Pokemon> pokemonList, Pokemon target) {
pokemonList.removeIf(pokemon -> pokemon.equals(target));
}
/**
* Gives a trainer necessary starting items
* @return <p>A list of items</p>
*/
public static Inventory createInventory() {
Inventory inventory = new Inventory();
inventory.addItem(new PokeBall(), 15);
inventory.addItem(new GreatBall(), 10);
inventory.addItem(new UltraBall(), 5);
inventory.addItem(new MasterBall(), 1);
inventory.addItem(new Potion(), 20);
inventory.addItem(new SuperPotion(), 10);
inventory.addItem(new HyperPotion(), 5);
inventory.addItem(new MaxPotion(), 1);
inventory.addItem(new Revive(), 2);
return inventory;
}
/**
* Chooses a random pokemon from a list
* @param pokemon <p>The list to choose from</p>
* @return <p>A pokemon.Pokemon object, or null if the list is empty</p>
*/
public static Pokemon randomPokemon(List<Pokemon> pokemon) {
if (pokemon.size() > 0) {
return pokemon.get((int)(Math.random() * pokemon.size()));
} else {
throw new IllegalArgumentException("Can't get random pokemon from empty list");
}
}
/**
* Reads pokemon from pokemon.Pokemon.txt to an ArrayList.
* @return <p>An ArrayList of pokemon objects</p>
*/
public static ArrayList<Pokemon> readPokemon() {
ArrayList<Pokemon> pokemon = new ArrayList<>();
try (Scanner file = new Scanner(new File("config/Pokemon.txt"))) {
while (file.hasNextLine()) {
pokemon.add(new Pokemon(file.nextLine()));
}
} catch (FileNotFoundException e) {
/* If the file is compiled as jar, this will prevent an empty list. */
try (Scanner file = new Scanner(Game.class.getResourceAsStream("config/Pokemon.txt"))) {
while (file.hasNextLine()) {
pokemon.add(new Pokemon(file.nextLine()));
}
}
}
return pokemon;
}
/**
* Picks a random pokemon from a list
* @param pokemon <p>A list of pokemon objects</p>
* @return <p>A pokemon object which exists in the input list</p>
*/
public static Pokemon pickRandomPokemon(ArrayList<Pokemon> pokemon) {
int index = (int)(Math.random() * (pokemon.size()));
Pokemon randomPokemon = pokemon.get(index);
pokemon.remove(index);
return randomPokemon;
}
/**
* Saves all pokemon in a list to a text file
* @param pokemonList <p>List of pokemon.Pokemon objects to save</p>
* @param saveFile <p>The file to write to</p>
*/
public static void savePokemon(List<Pokemon> pokemonList, String saveFile) {
try (PrintWriter file = new PrintWriter(saveFile)) {
for (Pokemon pokemon : pokemonList) {
file.println(pokemon.saveString());
}
System.out.println("Successfully saved pokemon.");
} catch (FileNotFoundException e) {
System.out.println("The saveFile could not be written.");
}
}
/**
* Saves the inventory to a text file
* @param inventory <p>The inventory to save</p>
* @param saveFile <p>The file to write to</p>
*/
public static void saveInventory(Inventory inventory, String saveFile) {
try (PrintWriter file = new PrintWriter(saveFile)) {
file.println(inventory.getSaveString());
System.out.println("Successfully saved inventory.");
} catch (FileNotFoundException e) {
System.out.println("The saveFile could not be written.");
}
}
/**
* Loads pokemon from a text file
* @param saveFile <p>The file to read</p>
* @return <p>A list of pokemon or null on failure</p>
*/
public static ArrayList<Pokemon> loadPokemon(String saveFile) {
ArrayList<Pokemon> pokemon = new ArrayList<>();
try (Scanner file = new Scanner(new File(saveFile))) {
NumberFormat format = NumberFormat.getInstance(Locale.ENGLISH);
while (file.hasNextLine()) {
String[] data = file.nextLine().split(";");
try {
pokemon.add(new Pokemon(data[0], Integer.parseInt(data[1]), Integer.parseInt(data[2]),
Integer.parseInt(data[3]), format.parse(data[4]).doubleValue(),
Integer.parseInt(data[5]), Integer.parseInt(data[6]), Integer.parseInt(data[7])));
} catch (NumberFormatException | ParseException e) {
System.out.println("Malformed number " + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid saveFile: " + saveFile);
return null;
}
}
System.out.println("Successfully loaded pokemon.");
} catch (FileNotFoundException e) {
System.out.println("Missing saveFile " + saveFile);
return null;
}
return pokemon;
}
/**
* Loads inventory from a text file
* @param saveFile <p>The file to write to</p>
* @return <p>A list of items or null on failure</p>
*/
public static Inventory loadInventory(String saveFile) {
Inventory inventory = new Inventory();
try (Scanner file = new Scanner(new File(saveFile))) {
while (file.hasNextLine()) {
try {
String line = file.nextLine();
if (line.isEmpty()) {
break;
}
String[] data = line.split(";");
inventory.addItem(Item.getItemByName(data[0]), Integer.parseInt(data[1]));
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid saveFile: " + saveFile);
return null;
}
}
System.out.println("Successfully loaded items.");
} catch (FileNotFoundException e) {
System.out.println("Missing saveFile " + saveFile);
return null;
}
return inventory;
}
/**
* Returns a random list of 6 pokemon
* @return <p>A list of pokemon.Pokemon</p>
*/
public static ArrayList<Pokemon> randomTeam() {
ArrayList<Pokemon> temporary = readPokemon();
ArrayList<Pokemon> pokemon = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
pokemon.add(pickRandomPokemon(temporary));
}
return pokemon;
}
}

View File

@@ -0,0 +1,31 @@
package items;
import pokemon.Pokemon;
import storage.Trainer;
import java.util.List;
/**
* An abstract class representing a poke ball
*/
public abstract class AbstractPokeBall extends Item {
/**
* Instantiates a new poke ball
* @param name <p>The name of the poke ball</p>
* @param description <p>The description of the poke ball</p>
*/
public AbstractPokeBall(String name, String description) {
super(name, description);
}
/**
* Uses a poke ball on an opponent
* @param target <p>Which pokemon to target</p>
* @param current <p>Current list the pokemon belongs to</p>
* @param catcher <p>Where we send the pokemon on a successful capture</p>
* @return <p>True if nothing went wrong. False otherwise</p>
*/
public boolean use(Pokemon target, List<Pokemon> current, Trainer catcher) {
return false;
}
}

View File

@@ -0,0 +1,67 @@
package items;
import pokemon.Pokemon;
/**
* An abstract class representing a potion
*/
public abstract class AbstractPotion extends Item {
final boolean alive;
/**
* Instantiates a new potion
* @param name <p>The name of the potion</p>
* @param description <p>The description of the potion</p>
*/
public AbstractPotion(String name, String description) {
super(name, description);
this.alive = true;
}
/**
* Instantiates a new potion
* @param name <p>The name of the potion</p>
* @param description <p>The description of the potion</p>
* @param alive <p>Whether the pokemon needs to be alive to use the potion</p>
*/
public AbstractPotion(String name, String description, boolean alive) {
super(name, description);
this.alive = alive;
}
/** Checks if an item should be used on alive or fainted pokemon. */
public boolean needsAlive() {
return alive;
}
/**
* Uses an item and does something based on the type of item
* @param target <p>Which pokemon should the item be used on</p>
* @return <p>True if nothing went wrong. False otherwise</p>
*/
public boolean use(Pokemon target) {
return false;
}
/**
* Checks if a pokemon is able to, and in need of a potion. If it is, heal it
* @param target <p>The pokemon to heal</p>
* @param amount <p>The amount to heal the pokemon</p>
* @return <p>True if nothing went wrong. False otherwise</p>
*/
boolean potion(Pokemon target, int amount) {
if (target.isConscious()) {
if (target.isDamaged()) {
int healed = target.heal(amount);
System.out.printf("%s was healed for %d HP and now has %d HP.%n", target.getName(), healed, target.getHP());
return true;
} else {
System.out.printf("%s has not taken damage, and does not require a potion.%n", target.getName());
return false;
}
} else {
System.out.println("You can't heal a fainted pokemon.");
return false;
}
}
}

View File

@@ -0,0 +1,22 @@
package items;
import pokemon.Pokemon;
import storage.Trainer;
import java.util.List;
/**
* This class represents a great ball item
*/
public class GreatBall extends AbstractPokeBall {
public GreatBall() {
super("Great ball",
"A good, high-performance Poké Ball that provides a higher Pokémon catch rate than a " +
"standard Poké Ball.");
}
@Override
public boolean use(Pokemon target, List<Pokemon> current, Trainer catcher) {
return target.tryCapture(current, catcher, 200);
}
}

View File

@@ -0,0 +1,17 @@
package items;
import pokemon.Pokemon;
/**
* This class represents a hyper potion item
*/
public class HyperPotion extends AbstractPotion {
public HyperPotion() {
super("Hyper Potion", "Heals a pokemon for 200 HP.");
}
@Override
public boolean use(Pokemon target) {
return potion(target, 200);
}
}

View File

@@ -0,0 +1,82 @@
package items;
import java.util.ArrayList;
import java.util.List;
/**
* This class represents a general item which can be stored in an inventory
*/
public abstract class Item {
final String name;
final String description;
static List<Item> availableItems = new ArrayList<>();
/**
* Instantiates a new item
* @param name <p>The name of the item</p>
* @param description <p>The description of the item</p>
*/
public Item(String name, String description) {
this.name = name;
this.description = description;
}
/**
* Returns an item by the given name
* @param name <p>The name of the item to get</p>
* @return <p>An item with the name, or null if no such item exists</p>
*/
public static Item getItemByName(String name) {
if (availableItems.isEmpty()) {
initializeItems();
}
for (Item item : availableItems) {
if (item.name.equals(name)) {
return item;
}
}
return null;
}
/**
* Initializes all known items so that they are usable
*/
private static void initializeItems() {
availableItems.add(new PokeBall());
availableItems.add(new GreatBall());
availableItems.add(new HyperPotion());
availableItems.add(new MasterBall());
availableItems.add(new MaxPotion());
availableItems.add(new Potion());
availableItems.add(new Revive());
availableItems.add(new SuperPotion());
availableItems.add(new UltraBall());
}
/**
* Makes a nice string describing the item
* @return <p>Name: Description</p>
*/
public String toString() {
return String.format("%s: %s", this.name, this.description);
}
/**
* Returns a string used for saving the item
* @return <p>Name;Description</p>
*/
public String saveString() {
return String.format("%s", this.name);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!Item.class.isAssignableFrom(obj.getClass())) {
return false;
}
return this.name.equals(((Item) obj).name);
}
}

View File

@@ -0,0 +1,21 @@
package items;
import pokemon.Pokemon;
import storage.Trainer;
import java.util.List;
/**
* This class represents a master ball item
*/
public class MasterBall extends AbstractPokeBall {
public MasterBall() {
super("Master ball", "The best Poké Ball with the ultimate level of performance. With it, " +
"you will catch any wild Pokémon without fail.");
}
@Override
public boolean use(Pokemon target, List<Pokemon> current, Trainer catcher) {
return target.tryCapture(current, catcher, 0);
}
}

View File

@@ -0,0 +1,17 @@
package items;
import pokemon.Pokemon;
/**
* This class represents a max potion item
*/
public class MaxPotion extends AbstractPotion {
public MaxPotion() {
super("Max Potion", "Fully heals a pokemon.");
}
@Override
public boolean use(Pokemon target) {
return potion(target, -1);
}
}

View File

@@ -0,0 +1,21 @@
package items;
import pokemon.Pokemon;
import storage.Trainer;
import java.util.List;
/**
* This class represents a poke ball item
*/
public class PokeBall extends AbstractPokeBall {
public PokeBall() {
super("Poke Ball", "A device for catching wild Pokémon. It's thrown like a ball at a " +
"Pokémon, comfortably encapsulating its target.");
}
@Override
public boolean use(Pokemon target, List<Pokemon> current, Trainer catcher) {
return target.tryCapture(current, catcher, 255);
}
}

View File

@@ -0,0 +1,20 @@
package items;
import pokemon.Pokemon;
/**
* This class represents potion item
*/
public class Potion extends AbstractPotion {
/**
* Instantiates a potion
*/
public Potion() {
super("Potion", "Heals a pokemon for 20 HP.");
}
@Override
public boolean use(Pokemon target) {
return potion(target, 20);
}
}

View File

@@ -0,0 +1,24 @@
package items;
import pokemon.Pokemon;
/**
* This class represents a revive item
*/
public class Revive extends AbstractPotion {
public Revive() {
super("Revive", "Revives a fainted pokemon.", true);
}
@Override
public boolean use(Pokemon target) {
if (!target.isConscious()) {
target.revive();
System.out.printf("%s was revived.%n", target.getName());
return true;
} else {
System.out.println("You can't revive a conscious pokemon.");
return false;
}
}
}

View File

@@ -0,0 +1,17 @@
package items;
import pokemon.Pokemon;
/**
* This class represents a super potion item
*/
public class SuperPotion extends AbstractPotion {
public SuperPotion() {
super("Super Potion", "Heals a pokemon for 50 HP.");
}
@Override
public boolean use(Pokemon target) {
return potion(target, 50);
}
}

View File

@@ -0,0 +1,21 @@
package items;
import pokemon.Pokemon;
import storage.Trainer;
import java.util.List;
/**
* This class represents an ultra ball item
*/
public class UltraBall extends AbstractPokeBall {
public UltraBall() {
super("Ultra ball", "An ultra-high-performance Poké Ball that provides a higher success rate " +
"for catching Pokémon than a Great Ball.");
}
@Override
public boolean use(Pokemon target, List<Pokemon> current, Trainer catcher) {
return target.tryCapture(current, catcher, 150);
}
}

View File

@@ -0,0 +1,243 @@
package pokemon;
import storage.Trainer;
import java.util.List;
import java.util.Random;
/**
* This class represents a pokemon
*/
public class Pokemon {
private final String name;
private int healthPoints;
private int maxHealthPoints;
private int strength;
private final double criticalChance;
private final Random random;
private final int catchRate;
private int exp;
private int level;
private int fleeCount;
/**
* Instantiates a new pokemon with random stats
* @param name <p>The name of the pokemon</p>
*/
public Pokemon(String name) {
this.random = new Random();
this.name = name;
this.healthPoints = 30 + random.nextInt(70);
this.maxHealthPoints = this.healthPoints;
this.criticalChance = Math.abs(0.1 * random.nextGaussian());
this.catchRate = (int)(Math.random() * 256);
this.exp = 0;
this.level = (int)(Math.abs(2 * random.nextGaussian()) + 1);
this.strength = random.nextInt(7) + this.level;
this.fleeCount = 0;
}
/**
* Instantiates a pokemon with set stats
* @param name <p>The name of the pokemon</p>
* @param healthPoints <p>The current HP of the pokemon</p>
* @param maxHealthPoints <p>The max HP of the pokemon</p>
* @param strength <p>The strength of the pokemon</p>
* @param criticalChance <p>The critical hit chance of the pokemon</p>
* @param catchRate <p>The catch rate of the pokemon. A higher rate makes it easier to catch</p>
* @param exp <p>The current xp of the pokemon</p>
* @param level <p>The current level of the pokemon</p>
*/
public Pokemon(String name, int healthPoints, int maxHealthPoints, int strength, double criticalChance, int catchRate, int exp, int level) {
this.random = new Random();
this.name = name;
this.healthPoints = healthPoints;
this.maxHealthPoints = maxHealthPoints;
this.criticalChance = criticalChance;
this.catchRate = catchRate;
this.exp = exp;
this.level = level;
this.strength = strength;
this.fleeCount = 0;
}
/**
* Makes a string containing all information about the pokemon
* @return <p>A descriptive string</p>
*/
public String toString() {
return String.format("Level %d %s HP: (%d/%d) STR: %d CHC: %.0f%%", this.level, this.name, this.healthPoints,
this.maxHealthPoints, this.strength, (this.criticalChance*100));
}
/**
* Returns a string containing all the pokemon's data in a save-able format
*/
public String saveString() {
return String.format("%s;%d;%d;%d;%f;%d;%d;%d", this.name, this.healthPoints, this.maxHealthPoints,
this.strength, this.criticalChance, this.catchRate, this.exp, this.level);
}
/**
* Gets the name of the pokemon
* @return <p>The name of the pokemon</p>
*/
public String getName() {
return this.name;
}
/**
* Gets the current hit points of the pokemon
* @return <p>The current HP of the pokemon</p>
*/
public int getHP() {
return this.healthPoints;
}
/**
* Checks whether two pokemon are equal
* @param target <p>The pokemon to check against</p>
* @return <p>True if they are equal. False otherwise</p>
*/
public boolean equals(Pokemon target) {
return target == this;
}
/**
* Heals a pokemon
* @param amount <p>How many hit points to heal</p>
* @return <p>The exact amount of hit points healed</p>
*/
public int heal(int amount) {
if (amount < 0) {
amount = this.maxHealthPoints - this.healthPoints;
} else {
amount = Math.min(this.maxHealthPoints - this.healthPoints, amount);
}
this.healthPoints += amount;
return amount;
}
/**
* Checks if a pokemon has not taken any damage or is fully healed
* @return <p>True if health is full. False otherwise</p>
*/
public boolean isDamaged() {
return this.healthPoints < this.maxHealthPoints;
}
/**
* Tries to catch a pokemon
* @param current <p>The list where the pokemon currently belongs</p>
* @param catcher <p>The list to send the pokemon on successful capture</p>
* @return <p>True on successful capture. False otherwise</p>
*/
public boolean tryCapture(List<Pokemon> current, Trainer catcher, int range) {
if (range == 0) {
this.capture(current, catcher);
System.out.printf("%s was caught.%n", this.name);
return true;
}
if ((int)(Math.random() * (range + 1)) < Math.max((3 * this.maxHealthPoints - 2 * this.healthPoints) *
this.catchRate / (3 * this.maxHealthPoints), 1)) {
this.capture(current, catcher);
System.out.printf("%s was caught.%n", this.name);
return true;
} else {
System.out.printf("%s escaped from the pokeball.%n", this.name);
return false;
}
}
/**
* Captures a wild pokemon
* @param current <p>The pokemon list the pokemon belongs to</p>
* @param trainer <p>The trainer capturing the pokemon</p>
*/
private void capture(List<Pokemon> current, Trainer trainer) {
trainer.addPokemon(this);
current.removeIf(pokemon -> pokemon == this);
}
/**
* Restores the health of a fainted pokemon
*/
public void revive() {
this.healthPoints = this.maxHealthPoints;
}
/**
* Checks if the pokemon has any HP left
* @return <p>True if any HP is left. False otherwise</p>
*/
public boolean isConscious() {
return this.healthPoints > 0;
}
/**
* Damages a pokemon
* @param damageTaken <p>How many hit points are to be deducted</p>
*/
public void damage(int damageTaken) {
this.healthPoints = Math.max(this.healthPoints -= damageTaken, 0);
System.out.printf("%s takes %d damage and is left with %d/%d HP%n", this.name, damageTaken, this.healthPoints, this.maxHealthPoints);
}
/**
* Gives a pokemon exp after each successful battle. Also handles leveling up
* @param target <p>Which pokemon did we beat</p>
*/
private void giveEXP(Pokemon target) {
int exp = (100 * target.level)/7;
this.exp += exp;
System.out.printf("%s gained %d exp.%n", this.name, exp);
if (this.exp > (4 * Math.pow(this.level, 3)) / 5) {
this.level++;
this.maxHealthPoints += 5;
this.healthPoints = maxHealthPoints;
this.strength += 1;
System.out.printf("%s is now level %d. Health has been increased and restored. Strength has been increased.%n", this.name, this.level);
}
}
/**
* Makes a pokemon attack another pokemon
* @param target <p>The pokemon to take damage</p>
*/
public void attack(Pokemon target) {
if (this.healthPoints > 0) {
System.out.printf("%s attacks %s.%n", this.getName(), target.getName());
double critical = 1;
if (Math.random() < this.criticalChance) {
System.out.println("Critical hit!");
critical = (2.0 * this.level +5) / (this.level + 5);
}
double randomDouble = 0.85 + (1.0 - 0.85) * random.nextDouble();
int moveDamage = (int)(Math.random() * 60 + 40);
int damageInflicted = this.level + (int)((((((2 * this.strength) / 5) + 2) * moveDamage * 1.75) / 50 + 2) * critical * randomDouble);
target.damage(damageInflicted);
if (!target.isConscious()) {
System.out.printf("%s is defeated by %s.%n", target.getName(), this.getName());
this.giveEXP(target);
this.fleeCount = 0;
}
} else {
System.out.println("No cheating!");
}
}
/**
* The trainer may flee if the battle is too hard
* @param target <p>Who are we trying to flee from</p>
* @return <p>True on successful escape. False otherwise</p>
*/
public boolean flee(Pokemon target) {
if (random.nextInt(256) < (this.level * 128 / target.level) + (30 * this.fleeCount % 256)) {
this.fleeCount = 0;
return true;
} else {
this.fleeCount++;
return false;
}
}
}

View File

@@ -0,0 +1,136 @@
package storage;
import items.*;
import java.util.*;
/**
* This class represents a pokemon trainer's inventory
*/
public class Inventory {
public static final Scanner in = new Scanner(System.in);
private final Map<Item, Integer> items;
/**
* Initializes a new empty inventory
*/
public Inventory() {
this.items = new HashMap<>();
}
/**
* Adds a new item to the inventory
*
* <p>If the inventory already contains the item, the amount will be added to the existing amount.</p>
*
* @param item <p>The item to be added to the inventory</p>
* @param amount <p>The amount of the item to add</p>
*/
public void addItem(Item item, Integer amount) {
if (items.get(item) != null) {
amount += items.get(item);
}
items.put(item, amount);
}
/**
* Gets all available poke balls from the inventory
* @return <p>A list of poke balls</p>
*/
public List<AbstractPokeBall> getPokeBalls() {
List<AbstractPokeBall> pokeBalls = new ArrayList<>();
for (Item item : items.keySet()) {
if (AbstractPokeBall.class.isAssignableFrom(item.getClass()) && items.get(item) > 0) {
pokeBalls.add((AbstractPokeBall) item);
}
}
return pokeBalls;
}
/**
* Gets all available potions from the inventory
* @return <p>A list of potions</p>
*/
public List<AbstractPotion> getPotions() {
List<AbstractPotion> potions = new ArrayList<>();
for (Item item : items.keySet()) {
if (AbstractPotion.class.isAssignableFrom(item.getClass()) && items.get(item) > 0) {
potions.add((AbstractPotion) item);
}
}
return potions;
}
/**
* Prints out information about available poke balls
*/
public void availablePokeBalls() {
System.out.println("You may choose from these items:");
List<AbstractPokeBall> pokeBalls = getPokeBalls();
for (int i = 0; i < pokeBalls.size(); i++) {
System.out.printf("%d: (%d) %s%n", i + 1, items.get(pokeBalls.get(i)), pokeBalls.get(i));
}
System.out.print(">");
}
/**
* Prints out information about available potions
*/
public void availablePotions() {
System.out.println("You may choose from these items:");
List<AbstractPotion> potionList = getPotions();
for (int i = 0; i < potionList.size(); i++) {
System.out.printf("%d: (%d) %s%n", i + 1, items.get(potionList.get(i)), potionList.get(i));
}
System.out.print(">");
}
/**
* Gets a potion according to the user's input
* @return <p>The potion the user chose, or null on invalid choice</p>
*/
public AbstractPotion getChosenPotion() {
List<AbstractPotion> potions = getPotions();
if (in.hasNextInt()) {
int choice = in.nextInt() - 1;
if (choice >= 0 && choice < potions.size()) {
in.nextLine();
return potions.get(choice);
}
} else {
in.nextLine();
}
return null;
}
/**
* Gets a poke ball according to the user's input
* @return <p>The poke ball the user chose, or null on invalid choice</p>
*/
public AbstractPokeBall getChosenPokeBall() {
List<AbstractPokeBall> pokeBalls = getPokeBalls();
if (in.hasNextInt()) {
int choice = in.nextInt() - 1;
if (choice >= 0 && choice < pokeBalls.size()) {
in.nextLine();
return pokeBalls.get(choice);
}
} else {
in.nextLine();
}
return null;
}
/**
* Gets a save-able string containing all non-empty items in the inventory
* @return <p>A save string Name;Amount</p>
*/
public String getSaveString() {
StringBuilder saveString = new StringBuilder();
for (Item item : items.keySet()) {
saveString.append(item.saveString()).append(";").append(items.get(item));
saveString.append("\n");
}
return saveString.toString();
}
}

View File

@@ -0,0 +1,147 @@
package storage;
import pokemon.Pokemon;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* This class represents a pokemon trainer
*/
public class Trainer {
public static final Scanner in = new Scanner(System.in);
final String name;
private List<Pokemon> pokemon;
private Inventory inventory;
/**
* Instantiates a new trainer
* @param name <p>The name of the trainer</p>
* @param pokemon <p>The pokemon belonging to the trainer</p>
* @param inventory <p>The inventory belonging to the trainer</p>
*/
public Trainer(String name, ArrayList<Pokemon> pokemon, Inventory inventory) {
this.name = name;
this.pokemon = pokemon;
this.inventory = inventory;
}
/**
* Sets the list of pokemon belonging to the trainer
* @param pokemon <p>A list of pokemon</p>
*/
public void setPokemon(List<Pokemon> pokemon) {
this.pokemon = pokemon;
}
/**
* Sets the inventory belonging to the trainer
* @param inventory <p>An inventory</p>
*/
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
/**
* Gets the list of pokemon belonging to the trainer
* @return <p>A list of pokemon</p>
*/
public List<Pokemon> getPokemon() {
return this.pokemon;
}
/**
* Adds a pokemon to the trainer's list of pokemon
* @param pokemon <p>A pokemon</p>
*/
public void addPokemon(Pokemon pokemon) {
this.pokemon.add(pokemon);
}
/**
* Gets all conscious pokemon belonging to the trainer
* @return <p>A list of pokemon</p>
*/
public ArrayList<Pokemon> getConsciousPokemon() {
ArrayList<Pokemon> pokemon = new ArrayList<>();
for (Pokemon singlePokemon : this.pokemon) {
if (singlePokemon.isConscious()) {
pokemon.add(singlePokemon);
}
}
return pokemon;
}
/**
* Gets all fainted pokemon belonging to the trainer
* @return <p>A list of pokemon</p>
*/
public ArrayList<Pokemon> getFaintedPokemon() {
ArrayList<Pokemon> pokemon = new ArrayList<>();
for (Pokemon singlePokemon : this.pokemon) {
if (!singlePokemon.isConscious()) {
pokemon.add(singlePokemon);
}
}
return pokemon;
}
/**
* Gets the inventory of the user
* @return <p>An inventory</p>
*/
public Inventory getInventory() {
return this.inventory;
}
/**
* Lists all currently available pokemon for the trainer
* @param alive <p>Whether to list alive pokemon or dead</p>
*/
public void listAvailablePokemon(boolean alive) {
ArrayList<Pokemon> pokemonList;
if (alive) {
pokemonList = this.getConsciousPokemon();
} else {
pokemonList = this.getFaintedPokemon();
}
System.out.println("You may choose from these pokemon:");
for (int i = 0; i < pokemonList.size(); i++) {
System.out.printf("%d: %s%n", i + 1, pokemonList.get(i));
}
System.out.print(">");
}
/**
* Prints all pokemon belonging to the trainer
*/
public void printPokemon() {
for (Pokemon pokemon : this.pokemon) {
System.out.println(pokemon);
}
}
/**
* Asks the user for the name of a pokemon and returns it
* @param alive <p>Whether the chosen pokemon has to be alive</p>
* @return <p>A pokemon object or null</p>
*/
public Pokemon choosePokemon(boolean alive) {
ArrayList<Pokemon> pokemonList;
if (alive) {
pokemonList = this.getConsciousPokemon();
} else {
pokemonList = this.getFaintedPokemon();
}
if (in.hasNextInt()) {
int choice = in.nextInt() - 1;
if (choice >= 0 && choice < pokemonList.size()) {
in.nextLine();
return pokemonList.get(choice);
}
}
in.nextLine();
return null;
}
}