Author Topic: keeping track of multiple enemies health?  (Read 15026 times)

puddinhead

  • Newcomer
  • Posts: 9
  • Karma: +0/-0
    • View Profile
    • Email
keeping track of multiple enemies health?
« on: September 07, 2012, 07:30:04 AM »
heyy guys!

So, ive been working on a simple rougelike for awhile now, I have items and inventory down, but once I started adding monsters I got stuck on this one problem. Pretty much I want to have 2 instances of say a goblin, but right now when I attack one of them it changes the health for all of them. what kind of system should I use to do this?

thanks!

Leaf

  • Rogueliker
  • ***
  • Posts: 64
  • Karma: +0/-0
    • View Profile
    • Email
Re: keeping track of multiple enemies health?
« Reply #1 on: September 07, 2012, 08:14:51 AM »
You need to define a data structure that contains information about a monster, and then instantiate an instance of that data structure for each monster you want to create in the dungeon, and then store those instances in some way that allows you to retrieve them (perhaps a 2d array corresponding to cell locations in the dungeon or something).

If you're using an object oriented language like C++, Java, C#, Python, PHP, etc, you'll want to create a class and instantiate objects with "new".  If you're using C, you'll want to create a struct, possibly typedef it to a struct*, and allocate memory with malloc, although that's pretty medieval.

Don't forget to free the allocated memory or delete the instantiated objects when you are done with them, if you are using a language that doesn't do it's own garbage collection.

I hope you are using a language that /does/ do its own garbage collection.  That'll make your life a lot easier (most OO languages other than C++).

99% of the challenge of programming stuff like this is figuring out how to arrange your data (we like to call this data arrangement the "object graph" in newer OO-type languages).  Once you get that designed, everything else kind of falls into place.

Leaf

  • Rogueliker
  • ***
  • Posts: 64
  • Karma: +0/-0
    • View Profile
    • Email
Re: keeping track of multiple enemies health?
« Reply #2 on: September 07, 2012, 08:27:35 AM »
Perhaps this wikibook (which I really ought to get back to work on) will help a bit.  It doesn't go as far as making "monsters" per se, though it does roll a couple of characters and have them bash it out over a couple of combat rounds, using the sorts of data structures mentioned above.

http://www.dizzydragon.net/rustybox/book/start

guest509

  • Guest
Re: keeping track of multiple enemies health?
« Reply #3 on: September 07, 2012, 08:42:28 AM »
Hey Puddin', welcome. What language are you using? There are some great coders here that will tell you exactly where you are tripping up.

What you are doing wrong is you aren't tracking stats for each instance, you are applying things directly to the object or class. So it hits all your instances at once.

I'm not the greatest coder around, opinions differ on who is, but if you link some of your code we can fix it easy. Link the code where you apply the hitpoint deductions. Just cut and paste that part.

All languages will have a way to ascertain the exact ID of the instance you are dealing with. So, in pseudo code, you can do something this.
  Get_Instance_ID (Exact_Instance)
  Exact_Instance.Hit_Points = Exact_Instance.Hit_Points - Attack_Value;

Right now you are probably doing something like this:
  Goblin.Hit_Points = Goblin.Hit_Points - Attack_Value;

In that last line of code 'Goblin' is an entire class or object, not a specific instance.

I hope that helps. I tend to be shitty enough of a programmer that new people understand what I say. The advanced guys, man, they can really talk over your head.

Good luck!

requerent

  • Rogueliker
  • ***
  • Posts: 355
  • Karma: +0/-0
    • View Profile
Re: keeping track of multiple enemies health?
« Reply #4 on: September 07, 2012, 10:23:39 AM »
I would guess that either you are sharing the same referenced variable among multiple objects or your collision detection is wonky.


Where you define your goblins, where your goblins are collided, and where your goblins receive damage would all be useful.

AgingMinotaur

  • Rogueliker
  • ***
  • Posts: 805
  • Karma: +2/-0
  • Original Discriminating Buffalo Man
    • View Profile
    • Land of Strangers
Re: keeping track of multiple enemies health?
« Reply #5 on: September 07, 2012, 10:51:34 AM »
I had the exact same symptom when I was starting out in python. As has been pointed out, the problem was that I accidentally assigned stats to a dictionary that was shared between all class instances. Ie:

Code: [Select]
class Goblin:
   stats={'attack':3, 'defend':2, 'health':2}
g1=Goblin()
g2=Goblin()
g1.stats['health'] -= 1 # this even reduces the health of g2
print(g2.stats) # qed

Instead, traits and stats which are individual, should be defined when every single class instance is initiated, to be on the safe side:

Code: [Select]
class Goblin:
   base_atk, base_def, base_hp = 3, 2, 2
   def __init__(self):
      self.stats={'attack':self.base_atk, 'defend':self.base_def, 'health':self.base_hp}
g1=Goblin()
g2=Goblin()
g1.stats['health'] -= 1 # now the stats of g2 are left alone
print(g2.stats)

Like Jo, I'd like to point out that I suck at programming :) And of course, it all depends on what language, which kinds of data structures, etc. you are using, so if you need more help, just provide some more specific information.

As always,
Minotauros
« Last Edit: September 07, 2012, 10:53:48 AM by AgingMinotaur »
This matir, as laborintus, Dedalus hous, hath many halkes and hurnes ... wyndynges and wrynkelynges.

puddinhead

  • Newcomer
  • Posts: 9
  • Karma: +0/-0
    • View Profile
    • Email
Re: keeping track of multiple enemies health?
« Reply #6 on: February 12, 2013, 06:30:52 AM »
thanks for all the help guys :)!
I haven't been on here for some time,
jeeze it was a while a ago when I was trying to figure that out,
I'm using C++, and this is how I do it now:
Entity* entities = new Entity[10]; // well I actually use a vector
entities[5]->hp -= player.atk;

PTrefall

  • 7DRL Reviewer
  • Rogueliker
  • *
  • Posts: 94
  • Karma: +0/-0
    • View Profile
Re: keeping track of multiple enemies health?
« Reply #7 on: February 12, 2013, 01:46:46 PM »
I'd recommend taking a look at the libtcod C++ tutorial. It might give you some decent pointers on how you can structure your code.
http://codeumbra.eu/complete-roguelike-tutorial-using-c-and-libtcod-part-1-setting-up

puddinhead

  • Newcomer
  • Posts: 9
  • Karma: +0/-0
    • View Profile
    • Email
Re: keeping track of multiple enemies health?
« Reply #8 on: February 14, 2013, 04:26:07 AM »
yeah I've checked them out, their really helpful!
one thing though, when I get around to dividing my project up into multiple headers and sources like in the tutorial I always have a lot of trouble with global variables and end up sticking to one source and header, for now.
does anyone know a good way to get around this? should I just pass the information I need in arguments? or..?

NON

  • Rogueliker
  • ***
  • Posts: 349
  • Karma: +0/-0
    • View Profile
    • Infra Arcana
    • Email
Re: keeping track of multiple enemies health?
« Reply #9 on: February 14, 2013, 12:08:04 PM »
I always have a lot of trouble with global variables [...]
does anyone know a good way to get around this? should I just pass the information I need in arguments? or..?
Are you actually talking about global constants? In that case, just use a header file for them with include guards. I have some headers like that in my project, I name them with the prefix "const", for example "constDungeonSettings.h":
Code: [Select]
#ifndef CONST_DUNGEON_SETTINGS_H
#define CONST_DUNGEON_SETTINGS_H

const int NR_DUNGEON_LEVELS = 25;

const int MAP_X_CELLS = 80;
const int MAP_Y_CELLS = 27;

// et c

#endif

Then you can include this file wherever you need the information.

I also have a header file for some data structures which may be used in many places. Stuff like a coordinate class (very very useful, I highly recommend you make one, you can do stuff like overload "==" and "!=" to compare two coordinates, or overload the "+=" operator to add offset coordinates... also it's nicer to pass around a coordinate instance in parameters, than to pass around two integers), or a rectangle class (containing two coordinate values... this is useful in the map generation, for example as a parameter for a room creator method).

As for global variables... don't use them. Ever. Let this data belong to some class, and make it class private, with appropriate get/set methods. For example, I have a class called Config, which keeps stuff like map cell dimensions (which may change if user picks another font). The map cell dimensions are class-private, with public get methods.
« Last Edit: February 14, 2013, 05:31:39 PM by NON »
Happy is the tomb where no wizard hath lain and happy the town at night whose wizards are all ashes.

puddinhead

  • Newcomer
  • Posts: 9
  • Karma: +0/-0
    • View Profile
    • Email
Re: keeping track of multiple enemies health?
« Reply #10 on: February 14, 2013, 06:05:42 PM »
ah yes, well I have a couple constants that I put in the header like that with the header define guards, but that's not where I go wrong(for all that I know :p). I have a map class that is pretty much used by every function, when it comes down to declaring the  instance of that class a then passing it too every function that needs it,  that's where I get lost. how do I declare and use the same instance throughout the whole project?

Omnomnom

  • Rogueliker
  • ***
  • Posts: 79
  • Karma: +0/-0
    • View Profile
    • Email
Re: keeping track of multiple enemies health?
« Reply #11 on: February 14, 2013, 09:25:07 PM »
From what I remember of C++ the problem is you can do this:
Code: [Select]
Globals.h
CMap map;

-----------------
Main.cpp
include "Globals.h"
void main()
{
   map.UsingMyMap();
}

But as soon as you add another source file and try to include Globals.h you get "CMap map is already defined" errors, because both source files are including a header which defines CMap map and you can only define it once.

What you can do is use the keyword extern in the header:
Code: [Select]
Globals.h
extern CMap map;


This is no longer declaring the variable it's saying the variable is declared elsewhere, ie external to the header file.

You then declare variable in a single source file:
Code: [Select]
Main.cpp
include "Globals.h"
CMap map;
void main()
{
   map.UsingMyMap();
}

You can then access the same global map variable from other source files by including Globals.h:
Code: [Select]
SourceFile2.cpp
include "Globals.h"

void func1()
{
   map.AlsoUsingMyMap();
}

Because by including globals.h, globals.h tells the source file that the CMap map variable exists and is defined somewhere and the compiler is happy with that.

TheCreator

  • Rogueliker
  • ***
  • Posts: 370
  • Karma: +0/-0
    • View Profile
    • Fame
    • Email
Re: keeping track of multiple enemies health?
« Reply #12 on: February 15, 2013, 06:45:32 AM »
You could use the singleton pattern:

http://en.wikipedia.org/wiki/Singleton_pattern

But I don't think it's a good idea to have only one instance of a map. Eventually you'll start to need multiple locations in the game, so that better do something like this:

Code: [Select]
class CGame
{
    vector<CMap*> m_Maps;
};

...and make the CGame class a singleton (or have a global variable of this class, using the 'extern' trick).
Fame (Untitled) - my game. Everything is a roguelike.

kraflab

  • Rogueliker
  • ***
  • Posts: 454
  • Karma: +0/-0
    • View Profile
    • kraflab.com
Re: keeping track of multiple enemies health?
« Reply #13 on: February 15, 2013, 10:56:20 AM »
look up the keywords static and extern

Paul Jeffries

  • 7DRL Reviewer
  • Rogueliker
  • *
  • Posts: 257
  • Karma: +1/-0
    • View Profile
    • Vitruality.com
Re: keeping track of multiple enemies health?
« Reply #14 on: February 15, 2013, 03:25:03 PM »
The way I tend to do this is to have one overall 'AppManager' class which is implemented as a singleton and which contains everything else in the program.  One of the AppManager's properties is called 'ActiveState' and this contains an instance of a 'State' class, which basically contains all the gameplay logic and information for whichever mode the game is in right now.  So for instance each level in the game is a separate state object that contains the map for that floor and all the enemies, items etc. that are on that level.  So in order to move between levels all I need to do is change the ActiveState from one state instance to another and I can also have different subclasses of state for different things (one for normal gameplay, one for the main menu, one for the credits, whatever).  Things like instantiating the map and so on are just done in the constuctor for it's parent state.  All I need to do then in order to get the map of the current level from anywhere in the code is call:

Code: [Select]
AppManager::GetInstance()->ActiveState->map