19 Jul, 2012, Idealiad wrote in the 1st comment:
Votes: 0
Say you wanted to find every mob in your game that currently was berserk. Also, you wanted to find every mob that couldgo berserk. How would you do that?
19 Jul, 2012, Rarva.Riendf wrote in the 2nd comment:
Votes: 0
What codebase, mobs that can spawn or mobs that are already spawned ?
19 Jul, 2012, KaVir wrote in the 3rd comment:
Votes: 0
You're interested in seeing how it would be done in different codebases? In GW2 it would be something like this:

for ( std::list<IBrain*>::iterator Iterator = IBrain::List().begin(); Iterator != IBrain::List().end(); ++Iterator ) 
{
IBrain *pBrain = (*Iterator);

if ( pBrain->GetType() == IBrain::eMOBILE && pBrain->GetThing() != NULL )
{
IThing *pThing = pBrain->GetThing();

if ( pThing->GetSpells()->GetBonuses()->Get(IBonus::eRAGE) != 0 )
{
// This mob is berserk.
}
else if ( pThing->GetTalent()->Get(ITalent::eBerserkerRage) )
{
// This mob is capable of going berserk.
}
}
}
19 Jul, 2012, Runter wrote in the 4th comment:
Votes: 0
I'm using a css system as mentioned in an other thread before. I'm still working on it, but I can find npcs like this pretty efficiently in this case:

All that are berserk:
Npc.css '.berserk'


All that have berserk skill:
Npc.css '[data-skill*="berserk"]'


In both cases it returns a collection that can be operated on easily. Like if we want to fully heal every berserk npc:

Npc.css('.berserk').each :restore


And the more code-y way that I rarely use now:
Actor.all.select {|a| a.npc? && a.affects.include?(:berserk) }


And for completeness sake, if I wanted to find the template rather than the actual loaded Npc I'd just switch Npc class with NpcT, which is my convention for instance and templates of things in game.

NpcT.css '[data-skill*="berserk"]'
19 Jul, 2012, plamzi wrote in the 5th comment:
Votes: 0
Runter wins.
19 Jul, 2012, Cratylus wrote in the 6th comment:
Votes: 0
filter(livings(), (: $1->GetProperty("berzerk") && !playerp($1) :) )
19 Jul, 2012, Idealiad wrote in the 7th comment:
Votes: 0
Runter, that's pretty cool.

Crat, is that LPC?


edit: In Inform 7 you would do it in a style similar to Runter's:

Every berserk mob.

Every berserking mob.


Would anyone do it without iterating over the collection of all mobs?
19 Jul, 2012, Cratylus wrote in the 8th comment:
Votes: 0
Idealiad said:
Crat, is that LPC?


Yes, it is one way to do it in one flavor of LPC. What is the context for your questions? Is this abstract curiosity or are you solving a problem?
19 Jul, 2012, Rarva.Riendf wrote in the 9th comment:
Votes: 0
Idealiad said:
Would anyone do it without iterating over the collection of all mobs?

Yeah sure if your mobs are in a relational database you could avoid iteration over all of them (provided you have the right table)
It is not about not wanting to do it, all depends on how you can parse your data. (relational database, linked list, hashtable etc)
And unless you have specifically organized your data so you can reach a mob through it affects, nope you wont be able to avoid to parse them all.
19 Jul, 2012, KaVir wrote in the 10th comment:
Votes: 0
plamzi said:
Runter wins.

I didn't realise it was a competition to see who could come up with the shortest syntax. How about this:

GetMobsWith(IBonus::eRAGE);

Hmm, I could shorten it further though, and skip the namespace…

GMW(eRAGE);

Do I win now?

Idealiad said:
Would anyone do it without iterating over the collection of all mobs?

Could do, but it really depends on the needs of the individual mud. My bottlenecks lie in string parsing, so that's where I focus most of my optimisations. I've never needed to search for mobs based on rage, but as I rarely have more than a few dozen mobs in memory at any one time, I wouldn't think twice about iterating over them all.
19 Jul, 2012, plamzi wrote in the 11th comment:
Votes: 0
KaVir said:
plamzi said:
Runter wins.

I didn't realise it was a competition to see who could come up with the shortest syntax. How about this:

GetMobsWith(IBonus::eRAGE);

Hmm, I could shorten it further though, and skip the namespace…

GMW(eRAGE);

Do I win now?


This was an ironic comment on the fact that many threads on these forums quickly regress into competitions. I wish it were different. But it ain't. I blame testosterone.
19 Jul, 2012, Cratylus wrote in the 12th comment:
Votes: 0
There is a non-zero chance that the point of this thread wasn't to give idealiad an opportunity to show that in his favorite language, this riddle is solved in three short keywords on one line.

I'm hoping he'll clarify what the actual point was, and that it wasn't just epeen preening.

-Crat
http://lpmuds.net
19 Jul, 2012, Runter wrote in the 13th comment:
Votes: 0
Lol, well, I was just stating how I'm doing it not as competition, but because that's the question that was asked.

If you want to know the implementation details…

Anything in the game is stored in a document object model and parsed/searched by nokogiri (http://nokogiri.org/). Node name is the class it represents in ruby, attributes represent data I've exposed to the system, and classes represent a variety of things. I haven't nailed down exactly where I should use classes, yet. I'm using them for different things based on the class it represents. So actually the blackbox I'm calling to seach the dom doesn't ensure it's not iterating over *more* than the entire collection. None the less, it's more than fast enough for my needs and the flexibility is high. That's what I'm really interested in.

But for what it's worth, I don't think that my code represents me basically hiding a lot of code behind a function name. If you think that's all that's going on here then you don't really understand what the code is doing.
20 Jul, 2012, Lyanic wrote in the 14th comment:
Votes: 0
Runter said:
But for what it's worth, I don't think that my code represents me basically hiding a lot of code behind a function name. If you think that's all that's going on here then you don't really understand what the code is doing.

I understand what the code is doing, but hiding a lot of code behind a function name is essentially what's going on there. The key difference between your example and KaVir's is that you're taking advantage of libraries and allowing Ruby to hide a lot of code for you, whereas KaVir was more literally doing the thing you said. Your case wins on programmer efficiency. KaVir's likely wins on computational efficiency. Overall, the trade-off seems negligible to me.
20 Jul, 2012, Idealiad wrote in the 15th comment:
Votes: 0
@Crat, it was curiosity prompted by a question someone asked on Stack Overflow; in his mud he was calling the update function of every mob in the game every game tick, and with 2000 mobs in memory wondering why he was getting 3-4 seconds of lag :sad:. That just got me to take another look at these kinds of issues.

And for what it's worth, I left the topic title as vague as it is to allow for more questions like this in the thread. Who knows, it could get fun. I only mentioned the Inform 7 example because it was so similar to the CSS-style declaration, I thought it was an interesting parallel.
20 Jul, 2012, Cratylus wrote in the 16th comment:
Votes: 0
Idealiad said:
@Crat, it was curiosity prompted by a question someone asked on Stack Overflow; in his mud he was calling the update function of every mob in the game every game tick, and with 2000 mobs in memory wondering why he was getting 3-4 seconds of lag :sad:. That just got me to take another look at these kinds of issues.


I don't know the codebase but I can imagine it being a valid thing to check every mob in the game every tick, depending on the game world requirements.

It seemed like you were implying that iterating through every mob was somehow undesirable…I'd suggest that iterating through lots of things all the time is kind of par for the course on a single threaded game with multiple players on at the same time.

Maybe this specific thing, "calling the update function" is a heavy operation and others here can identify it as the sort of thing one obviously tries to avoid doing too frequently. If so, then ok, we can talk about how to mitigate that.

I reject, though, the implication that having lots of objects polled frequently is avoidably inelegant. Severed limbs decay, as do zombies. NPC's heal. This stuff has to keep happening even if players aren't in the same room, so that when the player comes back in the room, a sensible scene is presented.

I guess you could set up a system where stuff that happens out of sight of the player gets cleaned up, retired to a central daemon, and redeployed just-in-time if a player comes back…but you're still checking and incrementing/decrementing variables in that central daemon, cycling through them every tick, based on whatever the logic is for their time-based change.

Maybe you could just avoid loading all those mobs til they're needed?

-Crat
http://lpmuds.net
20 Jul, 2012, Rarva.Riendf wrote in the 17th comment:
Votes: 0
Quote
his mud he was calling the update function of every mob in the game every game tick, and with 2000 mobs in memory wondering why he was getting 3-4 seconds of lag

Well obvisouly he is not only looking for an affect or anything cause I have more mobs in memory, (around 9k) I go repeatdly through them a lot more than once per tick (aggr update) and it does not take more than…dunno but it is not noticeable enough to make me go look for it (yet) even though I could probably do better…

Quote
Who knows, it could get fun.

There is no other way than parsing all of them, unless you have some data that store every mob having berserk. Even if your code won't show it because you use a sql request, it just means you have the db engine will do the parsing.
Or if you have a hashtable with mob as key and affect as values, finding every key having that value will make the library invoke a loop to parse them all. There is NO other way.
20 Jul, 2012, Runter wrote in the 18th comment:
Votes: 0
Lyanic said:
Runter said:
But for what it's worth, I don't think that my code represents me basically hiding a lot of code behind a function name. If you think that's all that's going on here then you don't really understand what the code is doing.

I understand what the code is doing, but hiding a lot of code behind a function name is essentially what's going on there. The key difference between your example and KaVir's is that you're taking advantage of libraries and allowing Ruby to hide a lot of code for you, whereas KaVir was more literally doing the thing you said. Your case wins on programmer efficiency. KaVir's likely wins on computational efficiency. Overall, the trade-off seems negligible to me.


I'm not saying my way is the best or the only, but let's not draw the conclusion that all things are equal just with trade offs. I'm not hiding iterating over a linked list. I'm hiding a sophisticated query engine. Which means that when some random, and even complex, problem relating to query arises I have a quick way of doing it that is very efficient and maintainable without needing more boilerplate. I'm sorry if someone is offended by that, but it's the fact of the matter. I don't have to write a new function called SearchForSomethingNew with a bunch of code behind it.

The tradeoff seeming negligible is the interesting part here. How can you possibly come to that conclusion? If I had a usecase that required more computational efficiency I can still programmatically iterate over a collection. Frankly, I can't think of a time that would happen. So the point of my post was "I do it with an in memory query engine especially built with associations representing the state of the game-world." It's a great way to do it most of the time, and not because it's succinct, but because it's flexible. It's even more flexible than a sql database, which I also use.
20 Jul, 2012, KaVir wrote in the 19th comment:
Votes: 0
Idealiad said:
@Crat, it was curiosity prompted by a question someone asked on Stack Overflow; in his mud he was calling the update function of every mob in the game every game tick, and with 2000 mobs in memory wondering why he was getting 3-4 seconds of lag :sad:. That just got me to take another look at these kinds of issues.

3-4 seconds of lag for 2000 mobs? Sounds like he should check his update function for bottlenecks.

In God Wars Deluxe (Diku/Merc based) I significantly sped up the combat rounds. In Merc it would iterate over every mob in the game, so I created a separate list of people who were fighting and just iterated over that instead. You wouldn't want to do that for things like "who has rage", but in my case it was a very specific situation (combat), and it did the job.
20 Jul, 2012, plamzi wrote in the 20th comment:
Votes: 0
KaVir said:
Idealiad said:
@Crat, it was curiosity prompted by a question someone asked on Stack Overflow; in his mud he was calling the update function of every mob in the game every game tick, and with 2000 mobs in memory wondering why he was getting 3-4 seconds of lag :sad:. That just got me to take another look at these kinds of issues.

3-4 seconds of lag for 2000 mobs? Sounds like he should check his update function for bottlenecks.

In God Wars Deluxe (Diku/Merc based) I significantly sped up the combat rounds. In Merc it would iterate over every mob in the game, so I created a separate list of people who were fighting and just iterated over that instead. You wouldn't want to do that for things like "who has rage", but in my case it was a very specific situation (combat), and it did the job.


I think you can get this kind of lag only if you've mis-designed something and the code ends up iterating over all your mobs multiple times (e. g. 2,000 times for every mob :). It happened to me on an early draft of code that generated several thousand random mobs. I'm pretty sure this is what happened to the person Idealiad referred to. Either that, or he's running his game on 80's hardware.

And yes, you can always optimize by creating sub-lists as needed, but each time you have to make a judgment call, and then write a good bit of code to create and maintain those sub-lists. Using CSS selectors can clearly help in such situations, and it would have been nice to have something like that. I use a SQL db extensively, but not for volatile states or anything that needs to run frequently. On one occasion, I tried to use it for reading and processing zone reset commands, but it was slower than iterating over the whole list in memory (code is in C). I've also tried keeping the actual query results in memory but they are much more complex, it seems, and slower to iterate over than simpler C structs.
0.0/21