0

I'm working on a text-based RPG for one of my classes. There's a random chance for combat to occur, at which time the player must fight a randomly generated monster. I have an ArrayList of monsters, but I'm running into a problem. If the character is level 1, it will always fight one of four level 1 monsters, chosen at random. Say for example the character has to fight a skeleton, and defeats it by depleting the skelton's health to 0. Now say the character once again has to fight, and a skeleton is randomly generated. Combat is skipped, because the skeleton still has 0 health from the previous fight

It appears that my code is referring to the object that resides in the ArrayList, but what I want to happen is to instantiate a new copy of the Monster such that the scope is onlythe method where the Monster is created. I understand what's going wrong, but I don't exactly understand why, and I also don't know how I can tweak my program to fix it. My short-term fix is to reset the monster's health to full after combat, but I'd like to understand my problem and hopefully learn from it.

Here is the method that initiates combat. I have a feeling my problem has to do with the way I'm creating the Monster object in the few lines below:

public void monsterEncounter(Player player)
{
    Monster monster = World.retrieveMonster(random.nextInt(4), player.getLevel());
    System.out.println("You were ambushed by a " + monster.getName() + "!  Prepare to defend yourself!");

The ArrayLists defining the monsters in the game, as well as the method to retrieve them, are defined in another class:

// ArrayList holding all monsters
static ArrayList<ArrayList<Monster>> monsters = new ArrayList<ArrayList<Monster>>();

// ArrayLists holding monsters by level
static ArrayList<Monster> levelOneMonsters = new ArrayList<Monster>(0);
static ArrayList<Monster> levelTwoMonsters = new ArrayList<Monster>(0);
static ArrayList<Monster> levelThreeMonsters = new ArrayList<Monster>(0);

public static void declareMonsters()
{
    levelOneMonsters.add(new Monster("Skeleton", 1, 50, 1, 4, 50, 25));
    levelOneMonsters.add(new Monster("Zombie", 1, 75, 1, 4, 60, 30));
    levelOneMonsters.add(new Monster("Rabid Dog", 1, 35, 2, 3, 40, 20));
    levelOneMonsters.add(new Monster("Goblin", 1, 65, 2, 3, 75, 40));
    monsters.add(levelOneMonsters);

    levelTwoMonsters.add(new Monster("Brown Bear", 2, 100, 2, 6, 100, 40));
    levelTwoMonsters.add(new Monster("Goblin Captain", 2, 125, 4, 3, 80, 35));
    levelTwoMonsters.add(new Monster("Giant Snake", 2, 110, 1, 3, 95, 75));
    levelTwoMonsters.add(new Monster("Lizard Man", 2, 130, 4, 4, 125, 100));
    monsters.add(levelTwoMonsters);

    levelThreeMonsters.add(new Monster("Gargoyle", 3, 150, 4, 6, 120, 100));
    levelThreeMonsters.add(new Monster("Psychotic Farmer", 3, 160, 7, 6, 125, 125));
    levelThreeMonsters.add(new Monster("Cultust", 3, 175, 1, 8, 175, 200));
    levelThreeMonsters.add(new Monster("Mutated Harpy", 3, 180, 6, 6, 150, 180));
    monsters.add(levelThreeMonsters);
}

public static Monster retrieveMonster(int index, int level)
{
    return monsters.get(level - 1).get(index);
}

I hope this question makes sense. I sincerely appreciate any insight anybody can provide.

Bloog
  • 171
  • 1
  • 1
  • 7

2 Answers2

0

To always instantiate a new Monster-object you have to either use clone() to make a copy or (if your Monster Constructor would be too much for the clone-method proided by the Object-class) you have to make a real deep copy of your Monster.

So try to change

public static Monster retrieveMonster(int index, int level)
{
   return monsters.get(level - 1).get(index);
}

to

public static Monster retrieveMonster(int index, int level)
{
   return monsters.get(level - 1).get(index).clone();
}
Community
  • 1
  • 1
puchmu
  • 109
  • 11
  • Thanks for the response. I was toying about with the clone method earlier, mainly because it was the only potential solution I could think of. Unfortunately, I get an error when I try to add clone() to the end of the return statement. The error: "Type mismatch: cannot convert from Object to Monster." But when I try to cast the returned object to a Monster, I get this error: "The method clone() from the type object is not visible". Any ideas? – Bloog Nov 10 '14 at 07:12
  • I just realized the clone() method has protected access. I think I can figure it out from here ^.^ – Bloog Nov 10 '14 at 07:15
  • You can try to make a deep copy by creating really new Monster() and pass the values that you have for your your Monsters in the Arraylist – puchmu Nov 10 '14 at 07:16
  • I am not allowed to make a comment to your answer, so I put it here: Your answer is exactly what a deep copy is – puchmu Nov 10 '14 at 07:44
0

After reading a bit about the clone() method, I decided to take a different approach. I was able to solve my problem by tweaking the retrieveMonster() method as follows:

public static Monster retrieveMonster(int index, int level)
{
    String monsterName = monsters.get(level - 1).get(index).getName();
    int monsterLevel = monsters.get(level - 1).get(index).getLevel();
    int monsterHealth = monsters.get(level - 1).get(index).getTotalHealth();
    int monsterArmor = monsters.get(level - 1).get(index).getTotalArmor();
    int monsterDamage = monsters.get(level - 1).get(index).getTotalDamage();
    int monsterXP = monsters.get(level - 1).get(index).getExperienceGranted();
    int monsterGP = monsters.get(level - 1).get(index).getMaxGoldGranted();

    return new Monster(monsterName, monsterLevel, monsterHealth, monsterArmor, monsterDamage, monsterXP, monsterGP);
}

This way I'm returning a new Monster object each time the method is called.

And this is the post that tipped me off to some of the inconsistency of the clone() method: https://stackoverflow.com/a/2326801/3224659

Community
  • 1
  • 1
Bloog
  • 171
  • 1
  • 1
  • 7