Advertisement

Dynamic monster object generation help

Started by January 04, 2019 01:45 AM
16 comments, last by Alberth 5 years, 11 months ago

Hello everyone, I need some help with my Java text-based dungeon crawler. My issue is that i want to spawn a monster with random specs every time a player enters a new room, pending an encounter roll. I am trying to figure out the best way to do this, logic wise. Should I (can I) just recreate the same object each time like,  Monster monster=new Monster(); and have the class constructor use random number modifiers to construct the object each time. Is there a way to destroy the object so I can remake it with the same variable name?  

 

Any help is appreciated here. Thanks

Just re-use the same variable then you have less garbage in your memory. ;)  Unless I'm missing something, I'm not a Java programmer, but I'm pretty sure that would be just fine.  If you only ever have 1 monster active, then just declare the variable with enough scope to be seen by all the code needing to interact with it.  Then each time you monster = new Monster, you'll be re-using the same bit of memory and saving yourself the allocation time and garbage collection.  If you have multiple monsters, then use an array or something similar instead.

And then yeah, just pass in the new random specs into the constructor and you'll have a new different monster. ;)

Advertisement
16 minutes ago, Septopus said:

Just re-use the same variable then you have less garbage in your memory. ;)  Unless I'm missing something, I'm not a Java programmer, but I'm pretty sure that would be just fine.  If you only ever have 1 monster active, then just declare the variable with enough scope to be seen by all the code needing to interact with it.  Then each time you monster = new Monster, you'll be re-using the same bit of memory and saving yourself the allocation time and garbage collection.  If you have multiple monsters, then use an array or something similar instead.

And then yeah, just pass in the new random specs into the constructor and you'll have a new different monster. ;)

Sweet, I was hoping that might work but i was worried about the first class object being stuck in memory after reassigning the variable to a new class object. But if the previous "new Monster()"s will get cleaned up since they are no longer bound to a variable then it should work fine. I'm not the greatest at memory managment :/

I'm fairly certain it will work just fine.  Once you have declared the variable, it grabs all the memory it could ever need, then when you take that same variable and RE-new Monster() it just reuses the old memory instead of finding a new free location and then cleaning up the old one.

If however you are using a local Monster variable within a class that itself gets recreated frequently then it will still be fine, but it will use more memory and create more garbage for the collector. ;)

I'll offer some of my own thoughts. They may differ a little from what's already been said, but I'll leave it to the OP to research and figure things out as needed :)

First, I think it's worth considering whether garbage is even a problem. To the best of my knowledge there are two potential issues at play with respect to garbage here: fragmentation, and garbage collector pauses.

With respect to fragmentation, I believe most Java GCs are compacting, in which case it shouldn't be a problem. Possible exceptions would be mobile platforms like Android, but if I remember correctly, more recent versions of Android include a compacting collector (readers should of course feel free to correct me if I'm wrong about that). In any case, if you can determine that the implementations you're targeting have compacting collectors, fragmentation shouldn't be a concern, I don't think.

Regarding GC pauses, I've read that Java GC implementations have gotten better over time about this, and that (perhaps) techniques like pooling (that is, reuse of existing objects) are no longer thought to be necessary or best practice, generally speaking. Again, this might differ on mobile platforms. But if your game is text-based and not real time, it seems unlikely that pauses would be an issue.

So first, I'd consider whether garbage is even something you need to worry about.

14 hours ago, Septopus said:

Then each time you monster = new Monster, you'll be re-using the same bit of memory and saving yourself the allocation time and garbage collection.

14 hours ago, Septopus said:

Once you have declared the variable, it grabs all the memory it could ever need, then when you take that same variable and RE-new Monster() it just reuses the old memory instead of finding a new free location and then cleaning up the old one.

Although I may be misinterpreting, I'm not sure if this is exactly right as stated. Similar to e.g. C++, I don't think repeatedly new'ing new objects, even if assigned to the same variable, is guaranteed to reuse the same memory.

A bit of conceptual evidence for this is that even if you 'new' a new object and assign it to a variable, the VM isn't necessarily done with the previous object yet (it still needs to be collected, finalized, etc.). So it seems unlikely that the same memory would or could be used for the new object.

14 hours ago, blesseddisciple said:

Sweet, I was hoping that might work but i was worried about the first class object being stuck in memory after reassigning the variable to a new class object. But if the previous "new Monster()"s will get cleaned up since they are no longer bound to a variable then it should work fine.

They won't get stuck (under normal circumstances at least). As you suggest, objects will be collected (eventually) once they're no longer reachable.

Again though, I wouldn't necessarily worry about garbage at all unless you have good reason to think that fragmentation and/or GC pauses are likely to be an issue. Further, I'd suggest that working around the garbage collector (e.g. by pooling or whatever) can sometimes lead to poorer quality code. This post is long enough as is, so I'm not going to elaborate on that here, but if I'm right about that, it might be a reason not to worry about garbage unless you have good reason to.

14 minutes ago, Zakwayda said:

it might be a reason not to worry about garbage unless you have good reason to.

Premature optimization I believe it's called.  Like I said, I'm not a Java programmer I suppose it has more to do with the Java VM inner workings then..  It is best practice to avoid garbage collection in most other languages that I'm familiar with that have the facility(certainly helps in c#). ;)  I may have to expand my understanding of the topic.

Advertisement

Yeah, i guess i just wish there was a keyword like monster=deallocate(); or something so that I knew for sure it was emptied before reassignment. 

But as slow as a,text based game runs, shouldn't be an issue I guess.

24 minutes ago, blesseddisciple said:

Yeah, i guess i just wish there was a keyword like monster=deallocate(); or something so that I knew for sure it was emptied before reassign

Unless you are actually generating an error related to this, then I would put the possibility fairly far out of mind.  Java and other languages with garbage collection are built to handle this side of memory management for you.  When a variable goes out of scope it will get cleaned up at some point before that memory is reused. ;)

1 hour ago, blesseddisciple said:

Yeah, i guess i just wish there was a keyword like monster=deallocate(); or something so that I knew for sure it was emptied before reassignment.

Just to offer further reassurance, you don't have to worry about this.

Here's a way you can possibly convince yourself of this. It's unlikely that a language as widely used as Java, and with as long a history as Java has, would be missing a critical memory management feature. As such, I think you can consider the absence of something like a 'delete' or 'deallocate' keyword as good evidence that such a feature wouldn't offer anything beyond what's already available, and/or would be inconsistent with the language design.

If you're not already familiar with how these sorts of garbage collectors tend to work, you might find further reassurance by investigating that a bit. A simple way of describing it is that objects are released to the garbage collector once you no longer hold any references to them, after which they're guaranteed to be 'deleted' eventually. Some consideration should show that such a system is functionally and semantically complete by itself and that an explicit delete/deallocate operator wouldn't add anything.

There are additional details of potential interest, such as the now-deprecated 'finalize' function; reference graphs, reachability, 'islands of isolation', and what exactly qualifies an object for collection; weak and soft references; and so on. But, these are all academic and/or (I would guess) unlikely to be relevant for what you're doing currently.

On 1/4/2019 at 3:49 AM, Septopus said:

If you only ever have 1 monster active, then just declare the variable with enough scope to be seen by all the code needing to interact with it.  Then each time you monster = new Monster, you'll be re-using the same bit of memory and saving yourself the allocation time and garbage collection.

This is completely wrong. In Java, only the native types (boolean, int, and float like types, written all lower case) have enough internal storage to store their value. Everything else, including boxed types like Integer are objects. Object variables do not contain object data, they are references to heap-allocated memory. In C++ you'd call them pointers. Every 'new' creates a new object of the given type.

In other words, each "new Monster();" makes a new fresh object.

 

12 hours ago, blesseddisciple said:

Yeah, i guess i just wish there was a keyword like monster=deallocate(); or something so that I knew for sure it was emptied before reassignment.

Java has automatic garbage collection. it removes objects that cannot be longer accessed. You can access an object if there exists a variable that references the object. after "monster = new Monster();" the "monster" variable references the Monster object, so it will not be removed. Variables also exist in objects, This system thus extends to object variables in objects as well. If you have a "Room room" variable in your Monster (the room it currently is), then that room will not be removed, since the Monster object refers to it, and the Monster object is not removable too (since "monster" refers to it.)

So what you want is somewhat already possible. If you write "monster = new Monster()", the 'monster' variable now refers to the new Monster object. It does no refer to the previous Monster oibject any more. If no other variable in your program refers to the old Monster object with that assignment (ie "monster" was the last variable refering to the old Monster), the old Monster object will be removed from the program.

You cannot forcibly de-allocate an object in Java. Imagine what would happen:


// 1 object Monster, and 2 variables both refering to the same object.
Monster monster = new Monster();
Monster monster2 = monster;

deallocate monster; // Say we could de-allocate
// The Monster object is now gone, what would monster2 refer to now?
// Garbage?

Note that you can also remove the Monster object reference from the monster variable by a simple "monster = null;" assignment. "null" points to no object at all, and thus also not to the Monster object. This is not often needed though. Normally, you either assign a new object, or you drop the variable from the scope (ie you cannot access the variable itself any more), for example by leaving the function that had the (local) monster variable in it.

 

I agree with others that garbage collection is a non-issue in a text-based game, so just don't worry about it at all.

If you want to re-use the Monster object, you "new" it once at the start of the program, and then for each next monster, you re-initialize the object, like "monster,restart();". Note that in this way the game always has a monster object, so if the player can kill it, you need some sort of inactive or 'dead' state for the monster for the time between the kill and the respawn.

This topic is closed to new replies.

Advertisement