ID:164115
 
Yeah, that's a fancy way to say I need to figure out an efficient way to store data for individual mobs to later recall and process. During the AI loop, I intend on having the AI take note of interesting events it happens to witness (Another mob just died as a result of interacting with that object, this food I just ate increased my stamina by a small amount, the individual who attacked me earlier is standing near my spawn point, etc.) Ideally the mob would later be able to search its "memory" after having observed something and determine its relevance and/or any course of action it should take.

I know this sounds like I'm being overly ambitious, and maybe I am, but I do plan on making it as simple as possible for myself. Each event itself will be simplified into five components; The thing or creature of interest, the action that was performed, the outcome, an evaluation result (dangerous, helpful, so on), and a numerical value representing how "important" the event is to the mob. So essentially I need a way to tie five pieces of information together (a mob/obj, three text variables, and an integer) into an easily referenced, searchable, and CPU efficient... um... thing.

See, that's where I get hung up... I don't know what "thing" I need for this /is/. "Database" came to mind, but that looks so hopelessly complex, and it sounds like it may be too CPU intensive to be worthwhile. Is there some sort of associative list I could create? Or maybe write to an external file and search through that somehow? I've never dealt with a lot of these things before, so I'm turning to you guys for some advice. Where should I start looking? Any recommendations on implementation?

Thanks in advance.
Hmm, a number of things come to mind. I've never tried this before and it would be interesting to see which works best.

The things I can come up with off the top of my head are:

1) Create an atom for the selected mob, and store all variables on that atom, for later reference. This would be easy to record and access, and all necessary information could be kept. I'd try this way personally, to see how intense it is.

2) Store a list or string of particular events that have happened, and depending on the event, assign something to it later. However I think this wouldn't apply as you need a record of who, what, where and how.

3) Similiar to number 2, but in a list keep each string with all the necessary information, such as "friend trapped 5"(For who, what, and level of importance).

That's about all I can come up with atm...
In response to Hiddeknight
You know I had actually thought about creating a custom data class, I just don't have the comprehension of DM I'd need to make that work. In particular, I'm not sure how I'd go about storing the data in it. Would I make a new list for each event? I can't imagine cramming them all into one list - it's just a big jumbled pile of unorganized data, isn't it? Or maybe instantiate a new atom for each event the mob records? Again, I'm not really sure how I'd go about keeping the data organized within its container. Or how to "attach" the atom to the mob, for that matter.

If I strung all the information together into a single string per event, I'd have to parse it all out again later, right?
In response to Evre
This is an interesting goal.

I'm not much of a good coder myself, but if I were in this situation I would do the following:

-(You, not the AI) find a list of common events that would affect the AI, like spawn killing and so on.
-Create a basic list variable for each one, and add ckeys for each mob doing this action.
-Recalling is easy, but the important thing is cross referencing your list variables to make a threat determination.
-Mobs on more than one list get a higher threat determination.
-Certain list variables give a higher threat determination (i.e. active spawn killing is a higher level threat than bumping into the mob, which may show a negative threat level for inexperience.)

This of course requires a list of variables created prior to execution.

Creating a perfect AI (which collects variables at runtime, which you talked about doing) would entail giving all mobs in view of the AI a certain level of logging, for instance on attack, a log entry is made on the mob's side of things. This will also work for Enter(), if you are looking out for spawn killers. Using the log, the AI can use the same threat determination described above in order to seek out certain mobs.

Of course, this would also require you to program in pre-runtime points of entry into the mob's log (like Enter() or Attack).



If all of this makes no sense, its perfectly normal. Just ask about whatever you don't understand, and sorry ahead of time.

-AJ
In response to Foster AJ
This certainly would work if I wanted to pre-program every conceivable event the AI would log/remember. Unfortunately, since I'm going for more of a social game and less of an action-oriented one, I can't just dumb it down to think only in terms of "Will this kill me? Do I want to kill it?".

In a way, the AI will log on pre-programmed triggers like receiving damage or whatever, but the information it needs to log needs to be a bit more comprehensive than just who did it. I know it sounds unnecessary, but I want my AI to be able to change their minds later on if events dictate or be able to intelligently evaluate a situation they've never been in and weren't coded for based on previous data collected.

I've been thinking on it a bit more - what if I made each "memory" (logged and processed AI witnessed event with the five variables I mentioned earlier) an object and had those objects spawn inside of the custom atom data type I mentioned earlier? If that wouldn't drive up memory costs and count too heavily against any hardcoded upper limits of BYOND, I think that might be the way to go. I still wouldn't know how to go about "attaching" the atom to the mob without just putting it in its inventory (I'd rather not have to tip-toe around when writing code that might destroy objects in a mobs inventory because it could literally destroy their minds). I suppose I could have it spawn in limbo or some Z-level specifically made for those objects and then name them based on the tag of whatever mob caused it to spawn. I can't see any immediate problems with this... but like I said, this is all new to me.
In response to Evre
Saving logs/savefiles on the server side could hog up memory... Perhaps implementing a trigger system (i.e. killing the AI for the first time) would stop logging/saving on users that have no threat, or can't be a threat. This would help on memory hogging a lot, but the AI.log would still have to be on a good sized server.
In response to Evre
Here is what I mean-

You would create a new object, say, obj/ai_note, in their contents. Make sure it won't drop or anything of the sort. You would set the object's variables to the necessary values (Such as who, what happened, level of importance) and then continue.

Later, the AI might need to check all the things that have happened to it. You would then do a for(var/obj/ai_note/A in contents) for that AI, and when it finds one, you can access all the necessary variables off of it. This is also easy to delete if it becomes redundant. However, depending on how many you give to each AI could mean a lot of objs floating around.

However, for your purpose, this should work fine. Make sure you delete any ai_notes in the AI's contents when he gets killed or otherwise removed, and don't drop them.
Look up information on 'datums' in the DM reference.

Also, look up info on 'hash maps' in Computer Science books or Wikipedia. That's the sort of data structure you're interested in. Anything else will be incredibly slow to search through - at least for a hash map, you can cut search times down or one axis.
I've never tried to do anything of the sort, but, personally, I'd create a sort of an associative "Data Tree", which records topics and their content, which record topics of their own(sounds confusing? it did to me!). That way, you could easily find components of a certain topic without having to perform a full-scale search each time you need them. You can easily organize actions and sub-actions; you can easily access the "Hostile" tree under the "Combat" tree, without having to identify whether this tree actually belongs to "Combat".

Also note, that what you described works very much like a Wiki, just AI-readable, and changeable.

In DM, this would be done using multiple datums, and chaining them together. E.g.
IndexSeer // topic datum, labeled "IndexSeer", because it
var
keyword // keyword that links to this seer
content // this seer/topic's content

IndexSeer/parent // the parent seer (aka parent topic)

list/sight // the child seers (aka topics)

New(Parent,k,c)
if(k) keyword = "[k]"
if(c) content = c

// specify this seer's parent
// (there may or may not be a parent)
if(parent) parent = Parent
return ..()

proc
// find my parent's keyword
GetParentKeyword()
. = SEERFAILED
if(parent && parent.keyword) return parent.keyword

// find my parent's sight list
GetParentSight()
. = SEERFAILED
if(parent && parent.sight) return parent.sight

// find my parent (wait...)
// if no parent is found, return null
GetParent()
return (parent || null)

// get first seer created (aka the master seer)
GetMasterSeer()
var/IndexSeer/masterSeer = GetParent()
if(!masterSeer) return src
return masterSeer.GetParent()

// the searching algorithm. probably needs to be improved, but I don't feel like
// looking into it right now.
// The algorithm seaches "down"(meaning, it won't search itself or parent topics),
// and returns a list of IndexSeers that match the content specified.
Search(k)
var/list/topics = new
var/IndexSeer/topicSeer
var/list/topicSight
for(var/index in sight)
topicSeer = sight["[index]"]
if(!istype(topicSeer)) // if this keyword isn't a topic seer(anything can happen!), continue searching!
continue
else if(findtext("[index]","[k]") || findtext("[topicSeer.content]","[k]"))
topics.Add(topicSeer)
topicSight = topicSeer.Search("[k]")
for(var/IndexSeer/topicSeerSight in topicSight)
if(topicSeerSight && istype(topicSeerSight))
topics.Add(topicSeerSight)
return topics

<small>note: untested!</small>