01 Jul, 2009, Banner wrote in the 1st comment:
Votes: 0
for( loops = 0; loops < 10; loops++ )
{
for( area = planet->first_area; area; area = area->next_on_planet )
{
int try = 0, vnum = 0;

if( area == NULL )
continue;

for( try = 0; try < ( area->hi_r_vnum - area->low_r_vnum ) / 2; try++ )
{
vnum = number_range( area->low_r_vnum, area->hi_r_vnum );
if( ( room = get_room_index( vnum ) ) != NULL )
{
/*
* Bombs can only land OUTSIDE and in NON-SAFE Rooms
*/
if( !IS_SET( room->room_flags, ROOM_INDOORS ) && !IS_SET( room->room_flags, ROOM_SAFE )
&& !IS_SET( room->room_flags, ROOM_NOFLOOR ) )
{
rfound = TRUE;
break;
}
}
}
}
if( rfound )
break;
}


This code is supposed to loop through the areas of a planet and find a suitable room and return it, however, for some reason it always seems to settle on one area in the list no matter what. Is there something wrong here?
01 Jul, 2009, kiasyn wrote in the 2nd comment:
Votes: 0
the 10 loops thing is unnecessary. it will always return the first suitable room in the first area with one, in this case, the first area in the list. You want to be randomly picking areas and then looking for the room.
01 Jul, 2009, Banner wrote in the 3rd comment:
Votes: 0
What would be the better way to randomly loop?
01 Jul, 2009, Runter wrote in the 4th comment:
Votes: 0
Banner said:
What would be the better way to randomly loop?


The random selection for rooms by just poking random numbers isn't so good.

Check out this snippet. I suspect your codebase works similar.
http://www.mudbytes.net/index.php?a=file...
01 Jul, 2009, Banner wrote in the 5th comment:
Votes: 0
Runter said:
Banner said:
What would be the better way to randomly loop?


The random selection for rooms by just poking random numbers isn't so good.

Check out this snippet. I suspect your codebase works similar.
http://www.mudbytes.net/index.php?a=file...

That's good and all, but I need it randomly select an area first, as the room selection randomness already works, although I may use that anyway for rooms.
01 Jul, 2009, Runter wrote in the 6th comment:
Votes: 0
Banner said:
Runter said:
Banner said:
What would be the better way to randomly loop?


The random selection for rooms by just poking random numbers isn't so good.

Check out this snippet. I suspect your codebase works similar.
http://www.mudbytes.net/index.php?a=file...

That's good and all, but I need it randomly select an area first, as the room selection randomness already works, although I may use that anyway for rooms.


I'm not really understanding what you really want. If you want a randomly selected room that function I just posted is a pretty good way. If you also want a randomly selected area you can make a function to grab an area randomly or you can snatch a randomly selected room and use its room->area pointer. (This wouldn't be an equally weighted random selection.) If it needed to be equally weighted distribution I suggest making a function to grab an area as well.
01 Jul, 2009, Banner wrote in the 7th comment:
Votes: 0
Planets have a list of areas attached to them. For example, Coruscant has the areas (monument_plaza.are, senate.are, corus_pt2.are, coruscant_streets.are, grand_towers.are, menari_spaceport.are). If I were to pass Coruscant to this function, I need to select an area randomly from that list, and then select a random room from that area.
01 Jul, 2009, Runter wrote in the 8th comment:
Votes: 0
Banner said:
Planets have a list of areas attached to them. For example, Coruscant has the areas (monument_plaza.are, senate.are, corus_pt2.are, coruscant_streets.are, grand_towers.are, menari_spaceport.are). If I were to pass Coruscant to this function, I need to select an area randomly from that list, and then select a random room from that area.


Here's a good way of doing it. Create an array the length of the count of areas in the passed planet. Then populate that array with each area. If that array is called area_array you can then do:

selected_area = area_array[number_range(0, area_count-1)];

Now we have our selected area. Now we need to do the same thing with the rooms in that area. Count the rooms, create an array and populate it with those rooms and:

selected_room = room_array[number_range(0, room_count-1)];
01 Jul, 2009, Banner wrote in the 9th comment:
Votes: 0
How do you create an array?
01 Jul, 2009, Runter wrote in the 10th comment:
Votes: 0
Also keep in mind with that you would want arrays of pointers, really. Already finding/knowing count:
AREA_DATA **area_list; // an array of pointers to AREA_DATA

area_list = (AREA_DATA **) malloc(sizeof(AREA_DATA*) * count);

Now you could access area_list as an array of AREA_DATA* and it is of length count. area_list[count-1] is the final element.

Edit: Keep in mind you are responsible for 1 free call for every malloc. Otherwise you're leaking memory. So sometime before the function returns you need to do this:
// area_list is still valid.
free(area_list);
// area_list is no longer valid
01 Jul, 2009, Runter wrote in the 11th comment:
Votes: 0
This is all assuming you're working in C, also. C++ is a little more elegant about these things.

You could also do something like this in gcc extended C:
AREA_DATA *area_list[count]; 
// It specifically works like this in gcc extended C. It straight C you're talking about count needing to be known at compile time. Eg not a variable.
01 Jul, 2009, Runter wrote in the 12th comment:
Votes: 0
Btw, for completeness sake here's how you could use std::vector in C++ to have a clearer syntax to dynamically assigned arrays.

AREA_DATA *get_rand_area( PLANET_DATA *p) {
std::vector<AREA_DATA *> area_list;

for(a = p.list; a; a = a->next_area)
area_list.push_back(a);

return area_list[number_range(0, area_list.size() - 1)];
}
01 Jul, 2009, David Haley wrote in the 13th comment:
Votes: 0
This is the kind of place where, if you're compiling with g++ already, you can let some C++ sneak in inside functions to make life a lot easier writing algorithms. You don't need to start "class-ifying" things to use C++ here and there.
01 Jul, 2009, Banner wrote in the 14th comment:
Votes: 0
Except in this case I'm compiling with C. :(
01 Jul, 2009, Runter wrote in the 15th comment:
Votes: 0
Did you get it working?
01 Jul, 2009, Banner wrote in the 16th comment:
Votes: 0
void do_randplanet( CHAR_DATA * ch, char *argument )
{
PLANET_DATA *planet;
AREA_DATA *area;
AREA_DATA *parea;
AREA_DATA **area_list; // an array of pointers to AREA_DATA
int count;

if( (planet = get_planet(argument)) == NULL )
{
send_to_char( "&RNo such planet.\n\r",ch );
return;
}
for( area = planet->first_area; area; area = area->next_on_planet )
count++;

area_list = (AREA_DATA **) malloc(sizeof(AREA_DATA*) * count);

parea = area_list[number_range(0, count-1)];


ch_printf( ch, "Planet: %s Selected Area:%s", planet->name, parea->name );
free(area_list);
return;
}


Wed Jul  1 12:54:40 2009 :: Log Banner: cedit randplanet create

Program received signal SIGSEGV, Segmentation fault.
0x08195677 in do_randplanet (ch=0x8f11ac8, argument=0xbfae9f3b "Coruscant")
at misc.c:5761
5761 parea = area_list[number_range(0, count-1)];
(gdb) print area_list
$1 = (AREA_DATA **) 0x0
(gdb)
01 Jul, 2009, David Haley wrote in the 17th comment:
Votes: 0
area_list is a NULL pointer. What is count equal to? If count is zero, malloc will probably return a NULL pointer (don't remember off the top of my head).

There's also the problem that you create the array but don't actually put anything into it.

You could also count the areas in one pass, and then skip the array business and just make a random number of hops through the linked list; it'd give you the same effect without the extra allocations.
01 Jul, 2009, Banner wrote in the 18th comment:
Votes: 0
David Haley said:
area_list is a NULL pointer. What is count equal to? If count is zero, malloc will probably return a NULL pointer (don't remember off the top of my head).

Count should be equal to 6.

David Haley said:
There's also the problem that you create the array but don't actually put anything into it.

I did it how Runter said. I've never created arrays before so beyond that I don't know what to do.

DavidHaley said:
You could also count the areas in one pass, and then skip the array business and just make a random number of hops through the linked list; it'd give you the same effect without the extra allocations.

Could you be more specific on how to actually achieve that?
01 Jul, 2009, David Haley wrote in the 19th comment:
Votes: 0
Well, when stuff doesn't work, you need to stop making assumptions about what things should or shouldn't be and check in the debugger. :wink: Obviously something is going wrong because area_list is coming back as a null pointer.

As for the array: well, an array is just a sequence of slots. What you've done is create that sequence of slots. But you still need to put things into the slots, by looping over the areas again and assigning them to the next slot.

As for the list: you first get the count, then you start at the first area. You pick a random number, and you move forward in the linked list that many times by taking area->next_on_planet (or whatever the linked list uses) to step forward in the list. It's just a list traversal, except that you count how many nodes you traverse.
01 Jul, 2009, Banner wrote in the 20th comment:
Votes: 0
How do you assign them to a slot in the array?
0.0/33