Temple of The Roguelike Forums

Development => Programming => Topic started by: Krice on December 09, 2010, 08:39:12 PM

Title: Tracking targets
Post by: Krice on December 09, 2010, 08:39:12 PM
1. npc is going towards an item, having its pointer or id stored
2. The item is destroyed

How to notify npc that the item is destroyed? I was wondering is it a good idea to include the list of targetters to the item's data directly? Or go through the list of npcs and check the target id of deleted item (could be slow)? Any ideas?
Title: Re: Tracking targets
Post by: anpd on December 09, 2010, 08:47:48 PM
I would let the item have a list and notify all that have it as a target that it's destroyed. Check the observer design pattern http://en.wikipedia.org/wiki/Observer_pattern (http://en.wikipedia.org/wiki/Observer_pattern)
Title: Re: Tracking targets
Post by: kipar on December 09, 2010, 09:14:03 PM
I would use second approach (check the list when object destroyed) just because it is easier to code. I can always switch to first method if profiling will show that checking list of units cause observable delay.
Title: Re: Tracking targets
Post by: Ex on December 10, 2010, 02:43:45 AM
This is a very intriguing question, particularly because although it's a somewhat rare situation, it usually shows up sooner or later. Anyway, I'd probably do it one of two ways. Either:

1. I'd loop over all the enemies whenever an object on the map is erased. If the enemy's target is the object to be erased, set the pointer in the enemy to NULL.
2. Or I'd use a "death" flag to specify that an enemy or item needs to be removed from the map. Assuming that this death flag is set before enemies are updated, the enemy could check to see if the item's death flag is set. If it's set, it would change it's target to NULL. Then, after the enemies have been updated, I'd loop over the items removing and deleting anything with a death flag.

Of the two, I'd more likely use the first because it's very easy to code. But, the second is convenient because often I already have a death flag implemented, in which case it's just a matter of having each enemy check during update if it's target's death flag is set. If some complicated situation comes up where neither are suitable, I'd definitely maintain a list of all references to each object (inside of the object's class), and on object deletion, I'd make sure that all the pointers referencing the object are set to NULL.

A lesser way to deal with the problem would be to work around it entirely. Such as, rather than storing a pointer to the target item, store it's coordinates and the intention of the enemy to get a certain type of item on those coordinates. Then you'd just need to periodically make sure that the given type of item still has those coordinates. Of course, I'd vastly prefer not to use this method because it's not a real solution, but I thought I'd throw it out there anyway :)
Title: Re: Tracking targets
Post by: corremn on December 10, 2010, 03:41:26 AM
1. npc is going towards an item, having its pointer or id stored
2. The item is destroyed

How to notify npc that the item is destroyed? I was wondering is it a good idea to include the list of targetters to the item's data directly? Or go through the list of npcs and check the target id of deleted item (could be slow)? Any ideas?

At the start of the AIs turn, check if item still exists. EASY.

I think an AI should adapt to its surroundings, not have its surrounding inform it when things change.

Hmm, Generally I just have enemies update there goals on the fly, if the target disappears then it will cease to go for it next turn.
For my AIs that have a set goal that stays persistent over turns, they just checks if it is still a relevant goal at the start of its turn. I.e does destination still exist, can I get there, is the object I am going for still there?
I dont see the point of informing AIs that a object has disappeared prior to their turn, they should figure it out themselves.  Sounds like needless complexity. Simple is best.



Title: Re: Tracking targets
Post by: Bear on December 10, 2010, 03:46:04 AM
What Corremn said.

If a mobile is tracking/targeting something, then the tracking/targeting state, as well as the ID number of the item/creature being tracked, is information that, IMO, ought to be stored as local state in that mobile's  AI.  

So, when the tracked thing disappears, it just disappears.  But the next time the mobile that's tracking it has a chance to move, its tracking/targeting function checks the ID number, finds no corresponding location for an item or creature, and reverts to a "figure out what else to do" state.

Bear
Title: Re: Tracking targets
Post by: Ex on December 10, 2010, 03:55:44 AM
1. npc is going towards an item, having its pointer or id stored
2. The item is destroyed

How to notify npc that the item is destroyed? I was wondering is it a good idea to include the list of targetters to the item's data directly? Or go through the list of npcs and check the target id of deleted item (could be slow)? Any ideas?

At the start of the AIs turn, check if item still exists. EASY.

I think an AI should adapt to its surroundings, not have its surrounding inform it when things change.

Hmm, Generally I just have enemies update there goals on the fly, if the target disappears then it will cease to go for it next turn.
For my AIs that have a set goal that stays persistent over turns, they just checks if it is still a relevant goal at the start of its turn. I.e does destination still exist, can I get there, is the object I am going for still there?
I dont see the point of informing AIs that a object has disappeared prior to their turn, they should figure it out themselves.  Sounds like needless complexity. Simple is best.
I would assume Krice is going to use a pointer to keep track of the target for speed. You can't simply check to see if the item still exists if you only have a pointer. He could keep track of the item's ID and information, but that would require looping over all the items looking for the item with the given ID every turn to make sure it still exists. And unfortunately, that doesn't solve the problem of: how do you determine if an object still exists when you only have a pointer to that object?

Of course, rereading Krice's post, it seems he's okay with IDs, so as long as you don't mind looping over every item every turn for every monster, I suppose it's okay.
Title: Re: Tracking targets
Post by: Bear on December 10, 2010, 04:09:12 AM
Don't be silly.  An object ID is an O(1) hashtable lookup, not an O(n) looping over every item. 

Title: Re: Tracking targets
Post by: Krice on December 10, 2010, 10:17:27 AM
so as long as you don't mind looping over every item every turn for every monster, I suppose it's okay.

When the target is destroyed you only need to check out every monster in that level to see if it has it as target.

I'm using 'destroyed' state for objects and they are finally deleted after a turn, so nothing points to a deleted object during the turn. The target check could be actually made at the same time when deleting the destroyed objects...

I'm just wondering if it's worth it to create a link between the target and one who is targetting for faster checking when something happens to the target. Maybe it's premature optimizing, since objects don't get destroyed that often.
Title: Re: Tracking targets
Post by: Krice on December 11, 2010, 05:18:13 PM
Actually all objects that are destroyed need to be check for all monsters (who have targets) so when more than one object is destroyed it can be slow.

The more I think this I'm convinced that having the object know that something is targetting it could be a good solution. It's also good for AI, because at least more intelligent creatures would then know that a monster is trying to attack (excluding the player, but that could be determined other way).
Title: Re: Tracking targets
Post by: Bear on December 12, 2010, 03:14:14 PM
I still don't understand what the problem is.  Why do you have to iterate over everything?? 

Creature A targets or tracks creature/item B.  Okay.  We write B's ID into A's AI record along with a state number that means "targeting" or "tracking".  Now B is destroyed.  Okay. Mark B "destroyed".  Next time it's A's turn, it checks for B and finds that B is destroyed, so it ends its targeting/tracking state and erases B's ID from its AI record.  Where is the need for an iteration?

The only interesting bit here is how do you mark B as having been destroyed.  If you have the infrastructure (a hash table) to separate ID's from pointers, you can just deallocate B.  The next ID lookup returns a NULL pointer so code knows that there is no more B. 

On the other hand, If your ID is the pointer itself, you still don't have to iterate; just set a flag in B and note a pointer to B and the turn B ceased to exist in a FIFO reclamation queue.  When you're allocating a new item or creature, you go to the reclamation list first, and reuse the oldest record provided the thing it refers do expired more than N turns ago (a thousand, maybe). Otherwise you allocate a new record.  You may have a bug or two if something follows a very old pointer expecting to find a different item, but you won't ever have code following a pointer to deallocated space or wrong type, because you reuse within type and never deallocate.

But... there's never a need for iteration over creatures or objects!  The whole thing works in terms of getting things off the front of a queue, accessing a hash table, adding things to the end of a queue, etc.  All O(1) operations!!

Title: Re: Tracking targets
Post by: kipar on December 12, 2010, 08:05:03 PM
Quote
On the other hand, If your ID is the pointer itself, you still don't have to iterate; just set a flag in B and note a pointer to B and the turn B ceased to exist in a FIFO reclamation queue.
I don't think it is possible if you use objects inherited from base class instead of just records. (e.g. TWeapon is child of TItem, TPotion is child of TItem, and they have different fields and different size in memory).

Using ID's instead of pointers eliminates the problem,  but imho pointers (= objects themselves in OOP) are more "intuitive" way then using IDs, creating hashtable and making a lot of wrappers or using unclear code such as
Code: [Select]
TargetID := B.ID;
...
if GetUnitByID(TargetID).Smiles then ...
instead of

Code: [Select]
Target := B;
...
if Target.Sad then...
Of course that's only my opinion.


Generally, my point is that O(N) isn't so bad while it isn't a bottleneck. Video output and complex AI algorithms will most likely eat more CPU-time.

Title: Re: Tracking targets
Post by: Krice on December 13, 2010, 10:14:39 AM
Next time it's A's turn, it checks for B and finds that B is destroyed

In the current code a destroyed B will be deleted after the turn so I guess it's possible that a creature could still target it and in the next turn it's pointing to a deleted object.
Title: Re: Tracking targets
Post by: elwin on December 13, 2010, 06:46:26 PM
I actually wouldn't have the NPC store any reference to the item it's tracking at all.  I'd have it look around every turn for items worth picking up.

My reason is that if monster A wants to pick up object B, indicating this by storing an id or pointer to B in A's data structure is duplicating information.  The level map contains the locations of A and B and implies that A can see B.  It implicitly stores the fact that A wants to pick up B.  Creating an explicit reference from A to B is storing the same information in two places.  If you do that, either they will fall into disagreement, or you will have to come up with a complicated method of making sure you always change them both at the same time.

Suppose, instead of getting destroyed, the item gets picked up by some other monster, or the player.  Or it gets teleported, or polymorphed into an item the monster isn't interested in.  Or the monster gets teleported out of sight, or polymorphed into something that can't pick up items.  There are just too many sections of code that have to work together.
Title: Re: Tracking targets
Post by: Krice on December 13, 2010, 07:08:33 PM
I'd have it look around every turn for items worth picking up.

I don't know how it would be possible to travel to a specific target without storing some information about it, because making that evaluation in every turn would make the monster chase between two items, never reaching either one of them.
Title: Re: Tracking targets
Post by: Bear on December 13, 2010, 07:31:21 PM
If an object has been deleted, and you follow a pointer to it, it's not a problem -- unless the object has also been deallocated.  If an object has been deleted, you discover the fact by reading the "deleted" flag in the object.  If it's been deallocated, then you cannot discover the fact; your program will segfault the minute you follow the dangling pointer. This is why you need a reclamation queue and a cooldown period before the record is reused; If you're keeping pointers to records, then unless you can prove that every pointer to a record has been NULL'ed, you don't ever deallocate that record.

I handle it with a hash table, so a reference from one item or creature to another item or creature is always an ID, never a pointer.  So I can check for ID mapped to NULL before I follow a pointer and segfault.  I think this is actually pretty important considering all the places where I can want to have references to items.  It's far easier than keeping track of all the different pointers that might need to be NULL'ed when something is deallocated. 

Basically, I guess there's three choices;

1) one "owning" pointer to an item or creature, probably from the map, and all other places where you need it you have to iterate to find it;

2) one "owning" pointer to an item or creature, from a hash table, and all places where you need it you consult the hash table; or

3) multiple pointers to items and creatures, and you can't deallocate ever unless you can prove that every pointer in every possible place is NULL.  Instead you have to keep the record around in a deleted state and may eventually reuse it subject to the risk of more minor bugs.



Title: Re: Tracking targets
Post by: elwin on December 13, 2010, 11:09:13 PM
I'd have it look around every turn for items worth picking up.

I don't know how it would be possible to travel to a specific target without storing some information about it, because making that evaluation in every turn would make the monster chase between two items, never reaching either one of them.

Always move toward the closest one.
Title: Re: Tracking targets
Post by: guest509 on December 14, 2010, 01:44:53 AM
  Go through the decision making process for the NPC every turn. Unless the decision is influenced by a random factor the NPC should be walking toward the item every turn. If something changes in the environment the NPC might change its path, as it should.
Title: Re: Tracking targets
Post by: MrMorley on December 14, 2010, 12:41:36 PM
Why not give every object an "OnDestroyed" event of some description? That way, whatever needs to know about them registers onto that event and they just trigger OnDestroyed.

How you implement that would depend on the language of course. In any Object-orientated language (C++, .net, java) You could have an "IWatchDestruction" interface, or .NET or C++ you could use delegation (boost/std::function for C++, delegate for .NET).
Title: Re: Tracking targets
Post by: Krice on December 15, 2010, 02:56:36 PM
Go through the decision making process for the NPC every turn.

I don't know. I like the idea of selecting a task and then trying to follow it. If the decision making is going to be as complex as planned it's also faster. The changes to target (someone picking it up etc.) are possibly easy to notify with the targetter list.
Title: Re: Tracking targets
Post by: roguedjack on December 22, 2010, 04:09:16 PM
I agree with some advices given here:

1 You should use entity IDs for storing logical relationships between game objects not pointers.

2 The entity initiating the relationship is the one responsible for managing it, not the other way around (eg: AI decides to target an item, so AI is holding the targeted Item ID and will check for the item validity and status).

3 An AI planning over many turns is not as interesting as it sounds. You have to explicitly code reactivity to game state changes or the AI will appear even dumber than a purely stateless reactive AI as the planned AI risks persisting in doing irrevelant actions (eg: AI keep trying to get a far away item while under fire; sounds easy to fix but you will have lots of situations like this to think about and code proper reactions).

There are a lot of benefits in doing 1 and 2 with only the negligible overhead of using a hashtable for ids.
Title: Re: Tracking targets
Post by: Krice on December 22, 2010, 06:42:12 PM
I don't really follow advices. Besides.. isn't pointer a kind of id anyway?
Title: Re: Tracking targets
Post by: Ex on December 22, 2010, 08:42:07 PM
1 You should use entity IDs for storing logical relationships between game objects not pointers.

There are a lot of benefits in doing 1 and 2 with only the negligible overhead of using a hashtable for ids.
There is still overhead for using a hashtable with IDs, whether or not some would consider it negligible. There is zero overhead for using a pointer.
Title: Re: Tracking targets
Post by: Bear on December 23, 2010, 09:10:49 AM
I don't really follow advices. Besides.. isn't pointer a kind of id anyway?

Yes, it is.  It's the kind of ID that can force your program to segfault if you check it after deallocating an object. That's why I want only one  of it per item, and in a single known place where I can keep track of it.  Most places I want object ID's, I want to be able to check them without crashing.

Bear
Title: Re: Tracking targets
Post by: roguedjack on December 23, 2010, 09:22:03 AM
I don't really follow advices.
Why do you ask for other people opinions then?
If you have already make up your mind go ahead then.

Quote
Besides.. isn't pointer a kind of id anyway?
Game ID != Memory ID (pointer).

For instance, how will you save to disk shared references to game objects that rely exclusively on pointers?
You have to have an ID on top of that, whether you call it "shared pointer" (smart pointers in boost for instance) or hand-made ID.
Title: Re: Tracking targets
Post by: roguedjack on December 23, 2010, 09:24:48 AM
There is still overhead for using a hashtable with IDs, whether or not some would consider it negligible. There is zero overhead for using a pointer.
If you never share your pointer of course a pointer is the best thing.
Title: Re: Tracking targets
Post by: Krice on December 23, 2010, 04:34:26 PM
Why do you ask for other people opinions then?

I like to know how others do stuff.

Quote
You have to have an ID on top of that, whether you call it "shared pointer" (smart pointers in boost for instance) or hand-made ID.

There is an id for each object, but it's mainly for save game and in some places where speed is not important.
Title: Re: Tracking targets
Post by: roguedjack on December 23, 2010, 07:27:34 PM
Allright then.

Your "targeted by" solution is basically the observer pattern :
An object notify another object something has happened to him (eg: the item is taken by someone else).
http://en.wikipedia.org/wiki/Observer_pattern (http://en.wikipedia.org/wiki/Observer_pattern)

If you run into pointers problems (eg: item "targeted by list" might hold invalid pointers at some point) and still don't want to use IDs for storing game object references you could consider using smart pointers:
http://en.wikipedia.org/wiki/Smart_pointer (http://en.wikipedia.org/wiki/Smart_pointer)
Assuming you program in C++ the Boost library is a good complement to the STL :
http://en.wikipedia.org/wiki/Boost_C%2B%2B_Libraries (http://en.wikipedia.org/wiki/Boost_C%2B%2B_Libraries)

Title: Re: Tracking targets
Post by: Krice on January 01, 2011, 07:22:17 PM
I don't use boost or smart pointers. I don't like how vague they are. I like to know what I get. Also, I'm puzzled when someone is talking about patterns. So what if some idea or part of the source code is a "pattern"? They don't own these ideas, whoever they are. I don't even care.
Title: Re: Tracking targets
Post by: Bear on January 02, 2011, 01:03:23 AM
It's okay, Krice; you don't have to care about design patterns. Just do good software design, and your particular set of design patterns will eventually emerge.  Some of these will be the same as some of the patterns named in the "Design Patterns" book (whether you care about the names or not) and others won't be.

Title: Re: Tracking targets
Post by: Slash on January 02, 2011, 05:19:54 AM
The Observer pattern is the obvious answer here.

Also, nobody *owns* a pattern... maybe someone must read a bit before replying :)
Title: Re: Tracking targets
Post by: MrMorley on January 02, 2011, 01:15:43 PM
I don't use boost or smart pointers. I don't like how vague they are. I like to know what I get. Also, I'm puzzled when someone is talking about patterns. So what if some idea or part of the source code is a "pattern"? They don't own these ideas, whoever they are. I don't even care.

Vague?

Boost is basically just the new content for the next version the standard template library (lots of the classes like smart pointers, hash maps and multithreading are being added to the STL for C++0x) and then some.

The smart pointer is pretty well defined. It counts the references to a pointer, and deletes it when no references are left. It's simple to implement your own instead, if you'd rather remove your perceived vagueness. Unless you take issue with templates, in which case....uhm, good luck with that?

And patterns are the ideas. Nobody owns them, just like nobody owns the concept of "chair" but you would still 90% of the time use the basic design of chair when making something to sit on. It tends to be useful to define what works, and definitions mean names.

"Each pattern describes a problem that occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice." - Christopher Alexander
Title: Re: Tracking targets
Post by: Krice on January 02, 2011, 01:34:19 PM
Templates are the thing that sucks most in C++ and what I know about the next version of C++ it's going to fail.
Title: Re: Tracking targets
Post by: scaught on January 03, 2011, 12:41:31 AM
Templates are the thing that sucks most in C++ and what I know about the next version of C++ it's going to fail.
I can prove your poorly formed opinion wrong in two snippets of code:

Code: [Select]
#define max( a, b ) ( a > b ? a : b )
Code: [Select]
template< typename T > T max( T const a, T const b ) { return a > b ? a : b; }

Snippet B is vastly superior to Snippet A in every possible way.  This is an unarguable fact.

Templates are a way to increase productivity and decrease bugs when used correctly.  People often misunderstand what code a template could generate and paint themselves into a corner of bloat and poor performance.  C++0x extends the tools available and makes even more available (decltype, lambdas, auto, variadic templates, etc).  (Shame about concepts not being ratified, tho -- that would've been a really nice nice-to-have)  It is as likely to "fail" (how do you even measure that?) as C++98 was.  Or C++ in general.  Or even C.  (each had/has its detractors, claiming it would never catch on.  Hell, the head of the CS dept of the university I attended almost 20 years ago was convinced Modula-2 was going to be 'the next big language'.)

By your bizarre disparaging comments about boost, smart pointers, patterns, etc, it's painfully obvious you're self taught.  You've reached a point in your self-education where you're accomplishing things and think you somehow now know best.  You are wrong.  You need to keep up the learning, even if you continue self-teaching.  Work with other people.  Drop the attitude and drop the assumptions.  Go start learning again.  You'll be a better programmer for it.
Title: Re: Tracking targets
Post by: willraman on January 03, 2011, 06:41:34 PM
In response to the OP. I have a map of vectors that act as containers for ground items. The items exist in a container, always. Either an item container on the character, or a container on the ground.

When the AI node needs an item, the item of interest ID is stored in memory of the character, and the AI state determines what it wants to do with that item and finally there is a an X,Y coordinate pair of where it needs to go. If it needs to, it can quickly open the container to check for the item to make sure it is still at the location or completely forget about the item if it's AI state changes (like it was attacked or decided it is really tired).

Not sure if this is the most efficient means. Yet it works great for when I drop several items in adjacent map squares and each item is considered a stack. As an example in Legacy of a Warlord one of the army members eat his fill, drops the item and then the next guy in line walks on top of the container, picks up the item and eats his fill... then the next guy seeing that all the food was eaten, goes back into food hunt mode shoots out some LOS rays and sees the square next to him has food and walks over to it to repeats the community eating process. Then all his hungry buddies seeing that the item is gone, do the same thing (go into hunt mode), target the item on the tile that was next to the one their original item was at or stop eating and go attack a goblin that wandered to close.

Will
Title: Re: Tracking targets
Post by: Krice on January 03, 2011, 10:03:12 PM
Snippet B is vastly superior to Snippet A in every possible way.  This is an unarguable fact.

Sadly it's something that you can't use in this context. You see, I never use macros and I try as hard as possible to avoid templates.

Quote
Templates are a way to increase productivity and decrease bugs when used correctly.

Isn't everything? Java was supposed to do that and then python.
Title: Re: Tracking targets
Post by: Slash on January 04, 2011, 12:24:58 AM
instead of diving into a pointless language flamewar, we could go back to the original subject...

So yeah, have each item store a reference to the npcs who are currently looking at it. When doing the LOS for each NPC (as simple or complex as you want it to be) and finding an item, add such npc to the item's "lookers list". Clean the lists for each item after a "turn" ends (or when it's time for the item to "act", you'll need to add it into your queue, or just an abstract actor in charge of cleaning up all the item's lists). If the item is destroyed, notify all those looking at it..

Should work good enough if not perfect
Title: Re: Tracking targets
Post by: MrMorley on January 04, 2011, 05:16:00 AM
Aside from making the comment that C# and Java both have generics after it became apparent some level of metaprogramming is required in a strictly typed language...at least for lower level things like linked lists, associated arrays, smart pointers etc.

Uhm yeah, you've basically been given all the options.

The viewed keeps a list, or the viewer keeps a list. If of pointers, both raise segment fault issues without some kind of memory management. If of ids, you have to have implemented some kind of id-obj association system. Also if an id is freed and reallocated the viewed/viewer could be fooled depending on the system.

Alternatively some kind of event system (trigger "obj_disassociated" event and let the event dispatch system handle all which want to know of said event). Best/easiest implemented if you are already using one (and definitely easiest if it's a flexible one).
Title: Re: Tracking targets
Post by: Krice on January 04, 2011, 10:26:44 AM
instead of diving into a pointless language flamewar

It's not always a flamewar. I find it good to discuss about programming. Over-templatizing is a problem indeed and that's what they try to do in the next version of C++ but I can't help thinking that there is a pressure to follow "modern" programming languages like Python. However nothing has proved Python superior and the same thing happened for Java that was supposed to "fix" all the "problems" C++ had. I think some stuff of STL is nice, but only because basic C++ doesn't have something like std::string. I think templates are quite ok when used as a library. But I like strict type based programming, nothing wrong with that. I've learned to work with types so I don't often get confused with them as beginners do.
Title: Re: Tracking targets
Post by: MrMorley on January 04, 2011, 05:45:53 PM
I agree that using templates pointlessly is stupid. So is using functional programming pointlessly, using polymorphism pointlessly, you get the idea. However, for low level concepts such as associative arrays (http://www.cplusplus.com/reference/stl/map/), smart pointers (http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/smart_ptr.htm), linked lists (http://www.cplusplus.com/reference/stl/list/) and so-forth that's a situation where templates are useful and the alternative solutions (such as reimplementing a new linked list class every time you need one with minor changes) are just pointless reinvention of the wheel. Templates pretty much exist is to stop the potential horrors of void pointers...

As for the features C++0x adds, well aside from variadic templates and template aliases they don't all seem that template orientated. Type inference, Lambda functions, constructor delegation, the nullptr constant, strongly typed enumerations, unrestricted unions, a standardised multithreading API and thread local storage, Regular expressions...holy heck I wants it now ;_;

As for the "java didn't remove C++"...well, there is not such thing as a superior language. Programming languages are tools and most have a place somewhere in the world of software where they are better suited than other languages. There is no be-all-and-end-all language.
Title: Re: Tracking targets
Post by: willraman on January 04, 2011, 10:07:33 PM
What I am trying to understand is why the need to have observed item call back to an observer? Wouldn't the observer have to then tell the item, "Hey I'm not interested in you any more..." if the AI found an item that was closer or better or the AI changed it's mind when it was attacked?

I'm trying to wrap my mind around a scenario of why the observer is better then what I currently use. That is a list that stores the items and returns a not_found (NULL) flag if the item was removed from the list when the AI checks each turn if it should continue moving towards the Item's location.

Will
Title: Re: Tracking targets
Post by: MrMorley on January 05, 2011, 08:54:09 PM
If I understand your situation...

Say you have n items removed in a turn, and m items in total being watched in that turn. You are doing m-n needless checks. The observer pattern only alerts items when they need to be alerted, thus you are doing only as much as needed.
Title: Re: Tracking targets
Post by: roguedjack on January 07, 2011, 10:57:15 AM
Krice.

Patterns are like standard algorithms.
Patterns help solving DESIGN/PROGRAMMING problems the same way standard algorithms help sove TASKS problems.
Patterns are good because they have been proven to work in practice and you can communicate your ideas more easily with other programmers with just saying the name of the pattern.
Patterns are just common ways to solve problems. Since quite a lot of people ended up using very similar solutions they have been formalized and given names like "Command pattern", "Observer pattern"...
Just like people used some similar data structures that are formalized and given names like "Tree", "List", "Graph"...
Nowadays patterns are part of your average software designer culture. Like "types", "variables", "quick-sort"....

Directing you to a pattern is a way of offering you a solution without writing a little 10 pages essay to explain you the idea in detail and how it is a candidate solution to your problem.
You wouldn't explain the list structure to other programmers over and over again. You just say "you can use a list to store your character items" and point them to the "list" idiom. Same for patterns.

Same with smart pointers. If you keep lots of references with pointers between your objects, smart pointers can help you avoiding crashing the program with invalid pointers. You can do without of course.

If you knew the Observer pattern for instance you wouldn't have to ask your initial question. It is exactly offering a viable, simple and clear solution for your problem.
Just like someone who know the "A-star" algorithm don't have to ask questions like "how can my AI find a path?".

You are perfectly entitled to refuse using or looking at these common solutions. Just know you are probably overlooking a set of tools that can help you fixing your problems.
Most programmers are using them not because they look nice or are fancy but because they work.
Just be aware that a lot of other people have gone through the same problems as you and ended up finding good solutions and are sharing them : Patterns, Algorithms, Data structures, Other languages...

Some solutions are just superior to others, others are superior under some conditions. Most of the time someone else has already solved a problem better than you could ever do ("you" means you, me, everyone).
You either:
a) accept that and trust other programmers experiences.
or
b) try for own thing and see the results.

Most people start doing b) thinking "uh. that new thing is complicated, useless, stupid, overdoing-it. the stuff I already use is fine."
...and after months or years of experience...
"hey, those guys were right! the best solution i found is just like those guys said in the first place! and sometimes they found an even better soltion than mine! duh! i lost a lot of time, but at least I learned! next time i'll listen and havea look at that new thing first!"

Ok. Hope my little easy didn't bore/enraged you. Good luck anyway with whatever solution you choose.
Title: Re: Tracking targets
Post by: Krice on January 09, 2011, 11:34:51 AM
Smart pointers are too smart. I like to struggle with old school pointers the proper way.
Title: Re: Tracking targets
Post by: Bear on January 09, 2011, 05:46:06 PM
Smart pointers are too smart. I like to struggle with old school pointers the proper way.

Heh.  Hey, if that's part of your artistic vision, go for it.  It's like me writing in C because I like the old-fashioned hardcore-ness of C. 



Title: Re: Tracking targets
Post by: Krice on January 11, 2011, 08:53:13 PM
It's like me writing in C because I like the old-fashioned hardcore-ness of C.

No, it's not like that. I don't like hardcore. I'm simply aware of problems in C++ and I pretty much know how to handle them - without boost or smart pointers which I think just makes things more confusing. The results of my programming style can be seen in Teemu which has zero known bugs.
Title: Re: Tracking targets
Post by: siob on January 11, 2011, 11:05:06 PM
I'm basically with roguedjack. thanks for the solid advice: http://www.roguetemple.com/forums/index.php?topic=1425.msg10297#msg10297

I don't care if looking up in hash table costs me time. But that's a given, because I write most my code in JavaScript and only very small parts in C or Java if necessary.
Title: Re: Tracking targets
Post by: Fenrir on January 12, 2011, 12:13:54 AM
The results of my programming style can be seen in Teemu which has zero known bugs.
Well then make it bigger and better until it does have bugs! You're not pushing the limits of what you can do.

If something or someone isn't on fire, you haven't tried hard enough.
Title: Re: Tracking targets
Post by: Krice on January 13, 2011, 02:14:51 PM
You're not pushing the limits of what you can do.

Maybe. But you can't deny that even the project size of Teemu is pretty good with its zero known bugs. The current development version 1.3 has total of 33 bugs by the way, but 30 of them are fixed. In fact I believe that the code quality will become better even the size and complexity is growing, because minor refactoring going on.
Title: Re: Tracking targets
Post by: Fenrir on January 13, 2011, 03:40:09 PM
That is true. Sorry, I didn't mean to imply that you weren't very good at what you do.

Anyway, don't let me derail the thread...
Title: Re: Tracking targets
Post by: wire_hall_medic on March 13, 2011, 06:31:33 AM
So, bringing it back, then.

I'm assuming that you have some random variable in your AI decision-making, and that you sometimes assign actions which take more than one turn.  Otherwise, you don't need anything.

You could store the current action as "Get item X" (well, "currentAcion = GET_ITEM" and "currentTarget = item").  Then each turn, the AI checks to see if there is an item of the type within sight, then moves as close as possible, picking it up if possible.  This also works for things like slow melee guys (you don't want them charging dead targets), etc.

This is a pretty clean solution, as you can just let the AI figure the best way to accomplish its current goal each turn; this has the emergent behavior of making the NPCs look smart.  The only thing is that this means the AI will repath each turn; this can be computationally expensive when the target is far away, or if you have a very large number of NPCs acting.

If you experience slowdown, you could save the path.  When the AI checks if its current action is still valid, part of that check is if the item is on the last step of the path.  If it is, then the NPC continues to step.  If not, it chooses a new task.