Search code examples
javagame-enginetext-based

Text-Based Game in Java. Need advice with Inventory Implementation and general coding advice


I'm having trouble figuring out how to deal with an Inventory for my text based java game. I just finished Data Structures and Algorithms, so I figured this would be a good project for my resume.

Currently, I create the inventory in the constructor of the player class. I would like to instantiate the inventory with 3 potion items, from the item class. I try to do that in the player constructor, but I can't figure out why its not working.

My question is, how should I go about instantiating every character with 3 potions in his/her inventory?


Player class:

package projectmoria;


import java.util.ArrayList;
import java.util.List;


public class Player {

    private final String name;
    private final String description;
    private final int maxHitPoints;
    private int hitPoints;
    private final int minDamage;
    private final int maxDamage;
    private final int defense;
    private double critChance;
    private int currX;
    private int currY;
    private Room currRoom;
    private List<Item> inventory;

    public Player(String name, String description, int maxHitPoints,
            int minDamage, int maxDamage, int defense, double critChance) {
        this.name = name;
        this.description = description;
        this.maxHitPoints = maxHitPoints;
        this.hitPoints = maxHitPoints;
        this.minDamage = minDamage;
        this.maxDamage = maxDamage;
        this.defense = defense;
        this.critChance = critChance;
        this.currX = 14;
        this.currY = 14;
        inventory = new ArrayList<>();
        inventory.add(Item.addPotion(3, this.player)); //This is the line I need help with
    }

    public int attack() {
        return ProjectMoria.RAND.nextInt(maxDamage - minDamage + 1);
    }

    public int defend(Monster monster) {
        int incomingAttack = monster.attack();
        int random = ProjectMoria.RAND.nextInt(99) + 1;
        if (random <= monster.getCritChance()) {
            incomingAttack = incomingAttack * 2;
            IO.monsterCrit(); //TODO - move to different spot
        }
        IO.playerHitPointsMessage(incomingAttack, monster);
        hitPoints = (hitPoints * defense > incomingAttack)
                ? hitPoints - incomingAttack : 0;
        return hitPoints;
    }

    public void heal(Item potion){
        this.hitPoints =+ 20;
        inventory.remove(potion);
        IO.heal(this.hitPoints);
    }

    public static Player newWarrior() {
        return new Player("Warrior", "A tough, well-rounded fighter with"
                + " a balanced skillset.", 100, 20, 30, 3, 10);
    }

    public static Player newDuelist() {
        return new Player("Duelist", "A quick, nimble duelist with an"
                + " aptitude for landing critical attacks.", 8000, 10, 50, 2, 
                18);
    }

     public String getDescription() {
        return description;
    }

    public int getHitPoints() {
        return hitPoints;
    }

    public boolean isAlive() {
        return hitPoints > 0;
    }

    public String getName() {
        return name;
    }

    public int getMaxHitPoints() {
        return maxHitPoints;
    }

    public int getMinDamage() {
        return minDamage;
    }

    public int getMaxDamage() {
        return maxDamage;
    }

    public int getDefense() {
        return defense;
    }

    public double getCritChance() {
        return critChance;
    }

    public int getCurrX() {
        return currX;
    }

    public int getCurrY() {
        return currY;
    }

    public List<Item> getInventory() {
        return inventory;
    }


    public Room getCurrRoom() {
        return currRoom;
    }

    public void setCurrRoom(Room room) {
        currRoom = room;
    }

    public void setCurrX(int currX) {
        this.currX = currX;
    }

    public void setCurrY(int currY) {
        this.currY = currY;
    }
}

Item class:

package projectmoria;


public class Item {

    private final String name;
    private final String type;
    private final String description;

    public Item(String name, String type, String description){
        this.name = name;
        this.type = type;
        this.description = description;
    }

    public void use(Player player, Item item){
        if(item.type.equals("Potion")){
            player.heal(item);
        }
    }

    public void addPotion(int numOfPotions, Player player){
        for(int i = 0; i < numOfPotions; i ++){
            player.getInventory().add(potion());
        }
    }

    public Item potion(){
        return new Item ("Potion", "Potion", " a small vial filled with a "
                + "translucent red liquid");
    }
}

Solution

  • Actually in Player constructor :

    inventory = new ArrayList<>();
    inventory.add(Item.addPotion(3, this.player)); 
    

    you are invoking :

    public void addPotion(int numOfPotions, Player player){
    

    This is an instance method.
    You can invoke instance methods only on an instance.

    Your addPotion() method looks like to be a factory method to create potion Items :

    public void addPotion(int numOfPotions, Player player){
        for(int i = 0; i < numOfPotions; i ++){
            player.getInventory().add(potion());
        }
    }
    
    public Item potion(){
        return new Item ("Potion", "Potion", " a small vial filled with a "
                + "translucent red liquid");
    }
    

    So, you should do static addPotion() and potion() and it should solve your problem.
    Besides, as potion() is only invoked by addPotion(), you can reduce it level access by making it private.