23 Aug, 2008, Kayle wrote in the 1st comment:
Votes: 0
So, this question was posed to me by my wife-to-be in regards to handling randomized sacrifices for our mud.

Question is: "Is there a way to pull a random Immortals name for the random sacrifice directly off the wizlist?"

I think this roughly translates, at least in regards to Smaug, to pull a name off a random file in the gods directory. So I ask, is it possible to pull a random name from a random file in a specific directory to return as a string in the sacrifice message? Or for those familiar with Smaug did I miss something when I looked at how the wizlist is made, is there a way to pull a random name from the actual wizlist?

Currently, I have to manually add names to a list inside the sacrifice function, but if I could make it pull based off the wizlist or off a random file, I'd be willing to do so, as it would save me a bit of work every time I hire or fire someone.

This is what it looks like currently:
if( !IS_NPC( ch ) && ch->pcdata->deity && ch->pcdata->deity->name[0] != '\0' )
{
mudstrlcpy( name, ch->pcdata->deity->name, 50 );
}
else if( !IS_NPC( ch ) && IS_GUILDED( ch ) && sysdata.guild_overseer[0] != '\0' )
{
mudstrlcpy( name, sysdata.guild_overseer, 50 );
}
else if( !IS_NPC( ch ) && ch->pcdata->clan && ch->pcdata->clan->deity[0] != '\0' )
{
mudstrlcpy( name, ch->pcdata->clan->deity, 50 );
}
else
{
static const char *god_name_table [ ] =
{
"Kayle", "Venia", "Scoyn", "Mikon", "Aldar",
"Kaytone", "Rilgore", "Dimension", "Syrax",
"Thannie", "Khoryna", "Vratis"
};
mudstrlcpy( name, god_name_table[ number_range( 0, 11 ) ], 50 );
}
ch->copper += 1;
if( obj->item_type == ITEM_CORPSE_NPC || obj->item_type == ITEM_CORPSE_PC )
adjust_favor( ch, 5, 1 );
ch_printf( ch, "%s gives you one copper coin for your sacrifice.\r\n", name );
snprintf( buf, MSL, "$n sacrifices $p to %s.", name );
act( AT_ACTION, buf, ch, obj, NULL, TO_ROOM );


Any ideas, suggestions, or corrections to my thinking are welcome and appreciated. :P
23 Aug, 2008, kiasyn wrote in the 2nd comment:
Votes: 0
convert your wizlist to a std::vector and do godlist[ number_range( 0, godlist.size() ) ]
23 Aug, 2008, Kayle wrote in the 3rd comment:
Votes: 0
That makes sense, but requires that I understand how to use std::vector, which I don't at this point in time. :P
23 Aug, 2008, Kayle wrote in the 4th comment:
Votes: 0
On second thought, and after looking at vectors in a C++ Textbook that I have lying around, vector doesn't look like it's that difficult, I might have to play around with this after I finish this const char* update so I'm compilable on gcc4.2+ if Samson ever decides to upgrade Arthmoor to it. :P
23 Aug, 2008, David Haley wrote in the 5th comment:
Votes: 0
Kayle said:
as it would save me a bit of work every time I hire or fire someone.

This is why I've been opposed for some time to the conflation of a MUD's OOC staff with its IC pantheon. It's odd that the deities in a world would shift so suddenly, appearing and disappearing out of nowhere…

Anyhow, for what was suggested, you don't need a std::vector – just use sizeof on the array you already have.

Pulling the list of files is possible too, I think there is code in SMAUG that enumerates the contents of a directory. Look at that, do so on your gods directory, stick them into a list, and pick a random one.
23 Aug, 2008, Kayle wrote in the 6th comment:
Votes: 0
Well, I don't even know that I will for sure pursue this, as is, we're still fleshing out specifics on how classes will work when finished, and the need for the random imm name to substitute in may not even be necessary by the time the classes and deities are all sorted out.

But she did pose an interesting question, and I was very much intrigued by the thought, and after discussing it with Samson, and looking over things, it appears that having Smaug maintain it's wizlist in memory is as easy as moving a for loop from the end of the function to the beginning.

Also, because I don't like to be bothered with remembering to add/remove people to the array, it tends to not get updated very often. So it doesn't really shift all that suddenly. And with no players, it's not like it really matters anyway. :P
18 Sep, 2008, Sandi wrote in the 7th comment:
Votes: 0
I have a similar question, though my set up is slightly more complicated than Kayle's. While I also have staff as gods, I have about 5 gods as mobs, and these sit in Limbo waiting to be called for various purposes such as awarding updates (hp,mana,move) and conferring stat increases. I find this more immersive than the typical anonymous game message announcing you've leveled in the middle of a fight. The code looks for the proper god, and if they're busy it either waits for the next update or takes the next available in the room. Now I have added occasional spellups to the sacrifice/donate code, and for this I'd rather mix it up with random appearances than have it always be the same deity.

So, my question is, what's the best way to pick a random mob out of a room?
18 Sep, 2008, Caius wrote in the 8th comment:
Votes: 0
Sandi said:
So, my question is, what's the best way to pick a random mob out of a room?

Which codebase and programming language?
In C++ I'd do something like this:
Character *getRandomPerson( const Room *r )
{
if( r->charList.empty() )
return 0;

std::vector< Character* > people( r->charList.begin(), r->charList.end() ); // copy contents of list into new vector
return people[ number_range( 0, people.size() - 1 ) ];
}


If you don't have vectors available I suppose you could first find out how many people there are in the room, then create the random number, and finally loop through the list the number of times corresponding to your random number, at which point you will be at the correct god.
18 Sep, 2008, Sandi wrote in the 9th comment:
Votes: 0
Uh, ROM, and C.

That looks sort of like what I was thinking of.
18 Sep, 2008, Hades_Kane wrote in the 10th comment:
Votes: 0
I'm at work and don't have any code in front of me, so I'm going off of pure memory on this but it shouldn't be hard to figure out what I'm -trying- to suggest if I'm not suggesting it correctly :p

If the mobs are static, I would probably do something like:

int mob;

mob = number_range(1,5)

switch(mob)
Case 1:
mob = blah
Case 2:
mob = blah..


etc.

If they aren't static, you might also be able to do a for loop checking for mobs in that room, increase a counter for every mob there and then go back and pick a number at random within the range of 1 - the total count, and grab that mob.
18 Sep, 2008, Lobotomy wrote in the 11th comment:
Votes: 0
Edit: Deleted.
18 Sep, 2008, David Haley wrote in the 12th comment:
Votes: 0
No need to have a separate array. In fact, by having the array, you're limiting yourself to max… And finally, that has a bug in it, because you want to make a random number up until count, not max.

Here's one that isn't limited and doesn't use a temporary array.

CHAR_DATA* rand_mob_from_room( ROOM_INDEX_DATA* r )
{
// make sure we have a room, and that it has people in it
if( r == NULL || r->first_person == NULL )
return NULL;

int count = 0;
CHAR_DATA* ch;

// step 1: get the count
for( ch = r->first_person; ch; ch = ch->next_in_room ) {
count++;
}

// step 2: get a random number
int steps = number_range(0, count-1);

// step 3: make that many steps in the linked list
ch = r->first_person;
while (steps– > 0) {
ch = ch->next_in_room;
}
assert(ch != NULL); // it should never be NULL, so assert it here
return ch;
}


Caveat: untested, haven't even tried to compile it.
18 Sep, 2008, Lobotomy wrote in the 13th comment:
Votes: 0
DavidHaley said:
No need to have a separate array. In fact, by having the array, you're limiting yourself to max… And finally, that has a bug in it, because you want to make a random number up until count, not max.

True, and thanks for catching the typo. By the way, why even bother with assert() in that example when ch will never be null?
18 Sep, 2008, David Haley wrote in the 14th comment:
Votes: 0
Well, it's generally good to explicitly state and test your assumptions. Since you "know" it won't be null, if it ever is, something very wrong happened and you want to find out immediately.
18 Sep, 2008, Lobotomy wrote in the 15th comment:
Votes: 0
DavidHaley said:
Well, it's generally good to explicitly state and test your assumptions. Since you "know" it won't be null, if it ever is, something very wrong happened and you want to find out immediately.

How can you be sure that assert() will function properly in those instances, though?
18 Sep, 2008, David Haley wrote in the 16th comment:
Votes: 0
What do you mean? If the pointer is null, assert will detect it and die. The pointer could be null in the event of stack corruption, multithreading gone wrong, etc.

Basically, it is good programming practice to state fundamental assumptions with assertions. It helps sanity check your code, it tells people what your intention was, and it can catch mistakes introduced later on. If something is so wrong as to prevent even assert from working, well, may the skies have mercy upon your program… :wink:
18 Sep, 2008, Lobotomy wrote in the 17th comment:
Votes: 0
DavidHaley said:
The pointer could be null in the event of stack corruption, multithreading gone wrong, etc.

That's exactly what I mean. When things like that take place, what guarantee is there that assert() won't likewise be affected? I don't see how assert() is even needed provided that proper error trapping is practiced. Otherwise, by what you say, it would seem necessary to have assert() calls pretty much everywhere. :thinking:
18 Sep, 2008, David Haley wrote in the 18th comment:
Votes: 0
Program stack or heap corruption will not affect assert. Why would it? Besides, do you not agree that there are situations where a pointer could be unexpectedly null, but otherwise the program is perfectly normal?

The reason to have assert there is so that callers can be completely sure that they're getting a non-NULL value out. Instead of having to catch that at every single calling location, you catch it just once.

And yes, actually, having assert calls in other places wouldn't be such a bad thing…
0.0/18