10 Jan, 2008, David Haley wrote in the 21st comment:
Votes: 0
Oh… ok, sorry. :smile: Why would you have to hash those though? You could (should?) just store them as-is. The problem is that if you hash them, you won't be able to extract the information out of them – all you'd have is a hash value.
10 Jan, 2008, Zeno wrote in the 22nd comment:
Votes: 0
Wouldn't that cause the problem I mentioned before though? If mob #532 exists in the world 7 times, and mob #300 hates it, and you store the mob name of #532 over a hotboot, and then the hate data would be loaded back… How would it know of the 7 mobs to "target" for the hate?
10 Jan, 2008, David Haley wrote in the 23rd comment:
Votes: 0
A good question, but on the other hand, how would hashing the name and vnum solve the same problem? To develop further, if you have some amount of information that is sufficient to identify the mob uniquely, what are you gaining by hashing that information? I posit that by hashing you run the risk of losing information since you will not be able to retrieve that information out of the hash code.
11 Jan, 2008, Zeno wrote in the 24th comment:
Votes: 0
As long as you do it "correctly" and it's injective, theoretically you should be able to retrieve the data from the hash.
11 Jan, 2008, David Haley wrote in the 25th comment:
Votes: 0
Well, yes, theoretically it is possible if your hash function is injective. But, have fun (a) establishing that your hash function is injective; and (b) writing the hash inversion function. My point here is that it's going to be an awful lot of trouble to be hashing that data when you could just store it as-is at the expense of just a few bytes per entry. And recall that the data isn't meant to be stored on the hard drive longer than it takes to shut down the MUD and restart it, so it's not as if we're incurring large storage costs anyhow.
12 Jan, 2008, Zeno wrote in the 26th comment:
Votes: 0
Right, which is why I said it wasn't a high priority. I figured you already knew that I was aware of how extremely annoying it would be. :P
12 Jan, 2008, Davion wrote in the 27th comment:
Votes: 0
Do your mobiles and PC's not have their own unique ID? If not, I don't think adding one would be that difficult. You could then just store it by said ID and you'd avoid the hate from spreading needlessly.
12 Jan, 2008, David Haley wrote in the 28th comment:
Votes: 0
PCs have unique IDs, notably their name; and indeed it would be fairly easy to construct unique IDs for the mobs. My MUD already has that but for different reasons, it's for memory management. It's based off of the discussion in this thread. (Funnily enough, in that thread I say it'd mean too much work to put it in, but then I went and did it… heh…)
12 Jan, 2008, Zeno wrote in the 29th comment:
Votes: 0
I see a serial # on ostat, but not mstat. Mobs may not have a unique identifier, not sure offhand.
22 Jan, 2008, drrck wrote in the 30th comment:
Votes: 0
I'm assuming, based on a couple of ideas thrown around at the beginning of the thread, that hate for a character would decrease over time, whether automatically per tick/round/whatever, or through "revenge" on the hatee by the hater (lol).

Based on that assumption, I don't see why anything more than a linked list is needed. We're talking about, what, ten nodes maximum at any given time? It would realistically be only one or two nodes (depending on player-base size) for 99% of mobs in the game 99% of the time. The overhead for insertion (adding/subtracting hate) is negligible, and the list could maintain order, so that the first node is always the "most hated", and lookups would only be singular pointer dereferences.

As far as saving hate over reboots goes, hashing would be overkill. If you haven't already, you should add a unique ID # to your mob struct, and just save hate to a .dat based on player name/mob ID #.

That's my two cents, anyhow.
24 Jan, 2008, David Haley wrote in the 31st comment:
Votes: 0
99% * 10,000 mobs = 9,900 mobs with hate * 1.5 = 14,850 average number of nodes, 99% of the time.

The cost for insertion and lookup is linear (insertion is normally constant, but you said it should keep order), and grows with the number of nodes in the list. It's quite wasteful to scan that whole thing linearly when it would be so remarkably easy to make it a binary search tree… A balanced BST would take at the most 14 hops using the above number, whereas any kind of linear structure (array, list…) would take at the most 14,850.
24 Jan, 2008, drrck wrote in the 32nd comment:
Votes: 0
DavidHaley said:
99% * 10,000 mobs = 9,900 mobs with hate * 1.5 = 14,850 average number of nodes, 99% of the time.

The cost for insertion and lookup is linear (insertion is normally constant, but you said it should keep order), and grows with the number of nodes in the list. It's quite wasteful to scan that whole thing linearly when it would be so remarkably easy to make it a binary search tree… A balanced BST would take at the most 14 hops using the above number, whereas any kind of linear structure (array, list…) would take at the most 14,850.


You're under the assumption that the game as a whole would only have one giant hate list. That would be terribly inefficient, and I don't even see how it could function properly.

Instead, each mob would have their own hate list, comprised of hate objects (which would be nothing more than linked list wrappers with a pointer to a char_data object, and a variable for the "amount" of hate). Using this method, insertion for those 99% of mobs would involve a ~1.5 node list, or pretty damn close to constant insertion - not a ~14,850 node list. While it would still technically be linear, and grow with the number of characters that the mob hates, I can't see how the list of hated characters could ever grow past, say, 10-12 nodes per mob, depending on how your game handles formations and such, and these would be worst-case scenarios.

Lookup, on the other hand, would be constant, because the lists are kept in descending order and the first node on a mob's hate list will always be the "most hated" - no search involved.
24 Jan, 2008, David Haley wrote in the 33rd comment:
Votes: 0
It would be pretty easy to make it function properly. :smile: But anyhow, as for whether or not it's inefficient, that depends on what you want to do with it… If it matters how many people are hating whom, or how many people hate a given person, you really want to have it in a single countable place instead of having to check each mob's hate structure. (For instance, this could be used in a faction/reputation system where there is a component of current dynamic aggression.) If all you care about is whom this particular mob hates the most, then yes, it makes more sense to have it stored on a per-mob basis.
25 Jan, 2008, Conner wrote in the 34th comment:
Votes: 0
DavidHaley said:
If it matters how many people are hating whom, or how many people hate a given person, you really want to have it in a single countable place instead of having to check each mob's hate structure. (For instance, this could be used in a faction/reputation system where there is a component of current dynamic aggression.) If all you care about is whom this particular mob hates the most, then yes, it makes more sense to have it stored on a per-mob basis.

Now you've got my attention. Currently my code has the mphate/mphunt/mpfear snippet which basically just lets you access the stock hate/fear/hunt code (if memory serves), but basically each mob can hate/hunt/fear a single character and they forget about that character after awhile or if someone else earns their hate/fear/hunt status sooner or if the mud gets hotbooted/rebooted, but it isn't impacted by the character's death nor online status. I think being able to extend the functionality of this system to include a full faction/reputation system sounds like a vast improvement.
25 Jan, 2008, drrck wrote in the 35th comment:
Votes: 0
DavidHaley said:
It would be pretty easy to make it function properly. :smile: But anyhow, as for whether or not it's inefficient, that depends on what you want to do with it… If it matters how many people are hating whom, or how many people hate a given person, you really want to have it in a single countable place instead of having to check each mob's hate structure. (For instance, this could be used in a faction/reputation system where there is a component of current dynamic aggression.) If all you care about is whom this particular mob hates the most, then yes, it makes more sense to have it stored on a per-mob basis.


If you also care about who/how many people hate a given person, then simply alter my previous suggestion from one list to two in each char_data - iHateTheseChars and theseCharsHateMe - same efficiency and much more intelligible than a giant game-wide list.
25 Jan, 2008, David Haley wrote in the 36th comment:
Votes: 0
drrck said:
same efficiency and much more intelligible than a giant game-wide list

I never said anything about a game-wide plain old list… indeed, a plain old list *would* be hard to manage. A simple indexed map would be incredibly simple…
25 Jan, 2008, Kjwah wrote in the 37th comment:
Votes: 0
I'm assuming you have code to support groups.. Assuming you have that, why not use the party to hold the list of hate instead of per character.. Sort the characters through the hate list in the group. Create a function to calculate hate and stick it in your damage function. Have it so if you're in a party to update that characters hate and use the party to keep track of it. No point in sticking it into the character structure if it is just really the party/raid managing the hate.

If you have a unique ID system based off of integers, it will be a little faster searching if you have to rather than comparing strings. I'd just store the UID of the player in the hate list in the party structure and their hate. How you calculate the hate is up to you but just use that in association with the UID to see who controls the aggro of the npc you're fighting.

That's how I'd go about it. I read a few of the posts here but didn't read every one so maybe someone has suggested something like this.

I'd probably use something like..

typedef struct hate_list {
int char_id;
int hate;
} HATE_LIST;


Then I'd just write the functions to sort the list and have aggro stick to the top of the list possibly with a chance to shift to another player, especially if there was a spike in their hate.

Something like that anyways.. However, that's just a rough draft of how I'd do it so there may be flaws which I haven't thought of or some better way to do it that I haven't realized yet since I have zero code for it. lol Also, add in the fact that I had a long stressful day at work so I relaxed with a few beers and it's late.. lol

EDIT: There's probably quite a bit of spelling and grammatical errors in this post.. Please, don't remind me. lol
25 Jan, 2008, drrck wrote in the 38th comment:
Votes: 0
DavidHaley said:
I never said anything about a game-wide plain old list… indeed, a plain old list *would* be hard to manage. A simple indexed map would be incredibly simple…


By "game-wide list", I was of course referring to any data structure that uniformly kept track of every character in the game - which applies to an indexed map, as well. Such a structure, while "simple" in a loose sense of the word, would have the disadvantage of having to be maintained outside the scope of a character itself (which is bad OO design, if you use OO), leaving a lot of openings for potential bugs. I'm not saying it's not a plausible system; just that it seems less efficient and obfuscated to me, personally.

Kjwah said:
I'm assuming you have code to support groups.. Assuming you have that, why not use the party to hold the list of hate instead of per character.. Sort the characters through the hate list in the group. Create a function to calculate hate and stick it in your damage function. Have it so if you're in a party to update that characters hate and use the party to keep track of it. No point in sticking it into the character structure if it is just really the party/raid managing the hate.

If you have a unique ID system based off of integers, it will be a little faster searching if you have to rather than comparing strings. I'd just store the UID of the player in the hate list in the party structure and their hate. How you calculate the hate is up to you but just use that in association with the UID to see who controls the aggro of the npc you're fighting.

That's how I'd go about it. I read a few of the posts here but didn't read every one so maybe someone has suggested something like this.

I'd probably use something like..

typedef struct hate_list {
int char_id;
int hate;
} HATE_LIST;


Then I'd just write the functions to sort the list and have aggro stick to the top of the list possibly with a chance to shift to another player, especially if there was a spike in their hate.

Something like that anyways.. However, that's just a rough draft of how I'd do it so there may be flaws which I haven't thought of or some better way to do it that I haven't realized yet since I have zero code for it. lol Also, add in the fact that I had a long stressful day at work so I relaxed with a few beers and it's late.. lol

EDIT: There's probably quite a bit of spelling and grammatical errors in this post.. Please, don't remind me. lol


Unless you're trying to use a map, like DavidHaley suggested, and want to index characters by their IDs, then there's really no need for an integer, when you can just replace it with a pointer to the char_data struct. There's also never a need to compare anything, be it strings or integers; you confused me with that part. And associating hate with the group rather than the individual wouldn't work unless solo characters are still considered "in a group" in your code and you never wanted to implement target switching in combat like was previously mentioned.
26 Jan, 2008, David Haley wrote in the 39th comment:
Votes: 0
drrck said:
(which is bad OO design, if you use OO)

Databases don't store everything related to an object in the object itself. You need indexing at a higher level for greater efficiency in some cases. Apply OOP design principles judiciously…

drrck said:
Unless you're trying to use a map, like DavidHaley suggested, and want to index characters by their IDs, then there's really no need for an integer, when you can just replace it with a pointer to the char_data struct. There's also never a need to compare anything

You don't need to index characters by IDs either if you have pointers. You only need IDs or strings if you need to persist across reboots. And you need comparisons if you are using a map.
26 Jan, 2008, drrck wrote in the 40th comment:
Votes: 0
DavidHaley said:
Databases don't store everything related to an object in the object itself. You need indexing at a higher level for greater efficiency in some cases. Apply OOP design principles judiciously…


Why would your database format matter? We're talking about structures in memory…

DavidHaley said:
You don't need to index characters by IDs either if you have pointers. You only need IDs or strings if you need to persist across reboots. And you need comparisons if you are using a map.


You don't need to, but again, it's much more efficient. Indexing them is constant, vs. linear for comparisons, and this time it actually matters, since the number of entries is likely to be in the tens of thousands.
20.0/77