Room Flags as Extended Bitvectors

Posted by Robert Powell on Sun 06 Feb 2005 09:19 AM — 25 posts, 89,603 views.

Australia #0
Hi all, i got silly and decided to convert room flags to be extended bitvectors as i needed more than 32,

What i have done se far is change to this in mud.h

EXT_BV room_flags;

Changed the #defines to be a typedef enum with all the room flags nicely sorted, Have gone through all the code changing IS_SET to xIS_SET.
and changed calls to flag_string to be ext_flag_string. Now i still have a few compile errors that i cannot work out how to fix.

Incompatable type for argument 1 of ext_flag_string :

 ch_printf_color( ch, "&cRoom flags: &w%s\n\r", ext_flag_string(location->room_flags, r_flags) );

Incompatable types in assignment

pRoomIndex->room_flags		= x2;
and
room->room_flags  = ROOM_INDOORS | ROOM_PRIVATE | ROOM_NO_RECALL | ROOM_NO_SUMMON | ROOM_NO_ASTRAL | ROOM_SOLITARY;

and last but not least,
invalid operands to binary &&

location -> room_flags = ROOM_PROTOTYPE && rm -> room_flags;


Im sort of gathering that i will need to change a variable somewhere but for the life of me i have no idea, any help on this would be great. Thanks in advance.
Amended on Sun 06 Feb 2005 09:21 AM by Robert Powell
USA #1
Quote:

Incompatable type for argument 1 of ext_flag_string :


ch_printf_color( ch, "&cRoom flags: &w%s\n\r", ext_flag_string(location->room_flags, r_flags) );

You need to add a & in front of the location->room_flags. So it will look like:

 ch_printf_color( ch, "&cRoom flags: &w%s\n\r", ext_flag_string(&location->room_flags, r_flags) );


Incompatable types in assignment

Quote:

pRoomIndex->room_flags = x2;
and
room->room_flags = ROOM_INDOORS | ROOM_PRIVATE | ROOM_NO_RECALL | ROOM_NO_SUMMON | ROOM_NO_ASTRAL | ROOM_SOLITARY;

First off, when you save it, make sure you save it as a string like this:

	if ( !xIS_EMPTY(room->room_flags) )
      fprintf( fpout, "%s ", print_bitvector(&room->room_flags) );

Secondly, when read, you need to do this:

pRoomIndex->room_flags		= fread_bitvector( fp );


Quote:

invalid operands to binary &&


location -> room_flags = ROOM_PROTOTYPE && rm -> room_flags;

I don't quite remember how I fixed this as it was forever ago when I did it. The obvious solution seems to just change it to:

xSET_BIT( location->room_flags, ROOM_PROTOTYPE );


I'm sure a few other people will come along and fix/clarify up my post for ya, as my experience with this is rather limited and old. :P
Australia #2
OK just about got it all working last problem is this, changed this pRoomIndex->room_flags = x2; to this pRoomIndex->room_flags = fread_bitvector( fp );

and now i get this error, fp, undeclared first use in function, i looked in the functions above that load mobs and object that use fread_bitvector but cannot see what to do so that it likes it, Thanks for the help so far.
Australia #3
Please ignore last post, i worked out what i was ment to do, the = 0 is the room_flag 0 and all i needed to do was xIs_Set it to whatever i wanted the flag to be
Australia #4
HEHE, it took some work but i managed to get it all to compile, and thanks to my friend GDb i got rid of all of the problems i had with loading and saving areas including a check to see if the flag number was less than 31, i dont know why people have to hard code numbers when its much prettier to put a MAX_RFLAG var there instead. Anywho im rambleing, Problem i now have is my room flags after 31 dont work when using a typedef enum with all the room flags listed in the correct order, i can set them on the room, they show in rstat they just dont work, i converted back to using #define room_flag 32 etc and it all works, am i missing something with the typedef enum or is it most likely a typist malfunction i cannot see just now.
USA #5
What do you mean? They show in rstat and they "just don't work". How are they not working?
Australia #6
Well it seems that for some reason it thinks any flag after 31 in the typedef enum, is not there, i can set them on a room an d they show, its just when i try to do something with it in code that it doesnt work, like lockers code, ROOM_LOCKER is flag number 33 its in spot 33 in the typedef enum, but the following condition always fails, even when rstat shows locker in the flags section.

if(!xIS_SET(ch->in_room->room_flags, ROOM_LOCKER))
        {
            send_to_char( "Does this smell like a locker room to you?\r\n", ch );
            return;
        }

If i define the flag numbers like so,
#define ROOM_LOCKER 33 , i have no problem at all. I will look at the enum list later, but as i recall there were no typos and all flags were in the correct order. As a test i put all the flags onto a room and it still didnt work, so its not an order issue, might look again to see if all my commas are there and what they are ment to be.
USA #7
Could you post the enum list? It was probably just a typing mistake or some such thing.
USA #8
Or rather, for your reference, it should look something like this (this is from UR):

typedef enum
{
	ROOM_NONE, ROOM_DARK, BFS_MARK, ROOM_NO_MOB, ROOM_INDOORS, 
	ROOM_NO_DRIVING, ROOM_NO_MAGIC, ROOM_BANK,
	ROOM_PRIVATE, ROOM_SAFE, ROOM_EMPTYSHOP, ROOM_PET_SHOP,
	ROOM_NODROPALL, ROOM_SILENCE, ROOM_LOGSPEECH, 
	ROOM_NODROP, ROOM_CLANSTOREROOM, ROOM_PLR_HOME,
	ROOM_EMPTY_HOME, ROOM_HOTEL, ROOM_NOFLOOR, ROOM_REFINERY,
	ROOM_FACTORY, ROOM_RECRUIT, ROOM_BOUNTY, ROOM_SPACECRAFT, ROOM_PROTOTYPE,
	ROOM_HOUSE, ROOM_BARRACKS, ROOM_DND, ROOM_NODEATH,
	ROOM_CRASH, ROOM_ARENA, ROOM_SANITARY, ROOM_DIRTY,
	MAX_ROOM_FLAG
} more_room_flags;
Canada #9
Just to clarify, any code thats set above the 31st value in your definitions will return false on xIS_SET but are infact set when you scan through the bits in your print function? What does your print function look like? Do the ones below 31 display and work properly?

It may be that xIS_SET is not checking anything past the 0 index of the xbit array.
Australia #10
All is fixed now, seems i overlooked a duplicate entry in the r_flags in build.c, i think i shouldnt be trying to code after working 14 hours.

Thank you all for the help.
USA #11
I've just recently installed this, and the only problem I ran into is this:
            if ( match == (match & pRoom->room_flags)


How do I convert that to EXT?

[EDIT] I also compared these...
  ROOM_DARK, ROOM_DEATH, ROOM_NO_MOB, ROOM_INDOORS, ROOM_BANK,
  ROOM_NEUTRAL, ROOM_CHAOTIC, ROOM_NO_MAGIC, ROOM_TUNNEL, ROOM_PRIVATE,
  ROOM_SAFE, ROOM_SOLITARY, ROOM_PET_SHOP, ROOM_PLR_HOME, ROOM_DONATION,
  ROOM_NODROPALL, ROOM_SILENCE, ROOM_LOGSPEECH, ROOM_NODROP, ROOM_CLANSTOREROOM,
  ROOM_NO_SUMMON, ROOM_NO_ASTRAL, ROOM_TELEPORT, ROOM_TELESHOWDESC, ROOM_NOFLOOR,
  ROOM_EMPTY_HOME, ROOM_ARENA, ROOM_NOMISSILE, ROOM_PROTOTYPE, ROOM_DND, ROOM_NO_TRAIN

"dark", "death", "nomob", "indoors", "bank", "neutral", "chaotic",
"nomagic", "tunnel", "private", "safe", "solitary", "petshop", "plr_home",
"donation", "nodropall", "silence", "logspeech", "nodrop", "clanstoreroom",
"nosummon", "noastral", "teleport", "teleshowdesc", "nofloor",
"apartment", "arena", "nomissile", "r4", "r5", "prototype", "dnd", "no_train"


I don't know why those r4 and r5 are there. Should I remove them?

[EDIT 2] Also, crashes are happening.
#0  find_first_step (src=0xa13df08, target=0xa13eea0, maxdist=1475)
    at track.c:143
143         MARK(src);
#0  find_first_step (src=0xa13df08, target=0xa13eea0, maxdist=1475)
    at track.c:143
#1  0x0814cbab in hunt_victim (ch=0xa1b11b8) at track.c:365
#2  0x0814e318 in mobile_update () at update.c:800
#3  0x08150e1e in update_handler () at update.c:2272
#4  0x080bf05f in game_loop () at comm.c:708
#5  0x080be8cd in main (argc=8, argv=0xbffde310) at comm.c:318



#define MARK(room)      (xSET_BIT(      (room)->room_flags, BFS_MARK) )
#define UNMARK(room)    (xREMOVE_BIT(   (room)->room_flags, BFS_MARK) )
#define IS_MARKED(room) (xIS_SET(       (room)->room_flags, BFS_MARK) )


What's wrong?
Amended on Mon 28 Mar 2005 08:08 PM by Zeno
USA #12
I think I left BFS_MARK as it was when I was modifying the thing I was doing. In the SMAUG dist I have its defined in track.c as:

#define BFS_MARK    536870912

and in the UR release that I had lying around I see this in mud.h:

/* BFS_MARK is for track and hunt */
typedef enum
{
	ROOM_NONE, ROOM_DARK, BFS_MARK, ROOM_NO_MOB, ROOM_INDOORS, 
	ROOM_NO_DRIVING, ROOM_NO_MAGIC, ROOM_BANK,
	ROOM_PRIVATE, ROOM_SAFE, ROOM_EMPTYSHOP, ROOM_PET_SHOP,
	ROOM_NODROPALL, ROOM_SILENCE, ROOM_LOGSPEECH, 
	ROOM_NODROP, ROOM_CLANSTOREROOM, ROOM_PLR_HOME,
	ROOM_EMPTY_HOME, ROOM_HOTEL, ROOM_NOFLOOR, ROOM_REFINERY,
	ROOM_FACTORY, ROOM_RECRUIT, ROOM_BOUNTY, ROOM_SPACECRAFT, ROOM_PROTOTYPE,
	ROOM_HOUSE, ROOM_BARRACKS, ROOM_DND, ROOM_NODEATH,
	ROOM_CRASH, ROOM_ARENA, ROOM_SANITARY, ROOM_DIRTY,
	MAX_ROOM_FLAG
} more_room_flags;

I looked in track.c and BFS_MARK BV01 was commented out. I'm guessing maybe you have it defined wrong?
USA #13
It's the same as Stock smaug.

#define BFS_MARK    536870912


I don't have BFS_MARK in the enums list but it is defined in track.c, does it need to be in the enums list, if so, where?

[EDIT] Perhaps I will focus on this crash, which happens if I remove r4 and r5:
#0  0x008e20b9 in strcat () from /lib/tls/libc.so.6
#1  0x0809e407 in ext_flag_string (bitvector=0x88082c0, flagarray=0x8194040) at build.c:315
#2  0x0807cd54 in do_rstat (ch=0x8942e40, argument=0xbff77845 "") at act_wiz.c:1736
#3  0x080e9f60 in interpret (ch=0x8942e40, argument=0xbff77845 "") at interp.c:583
#4  0x080befd3 in game_loop () at comm.c:689
#5  0x080be875 in main (argc=2, argv=0xbff77c80) at comm.c:318

(gdb) f 1
#1  0x0809e407 in ext_flag_string (bitvector=0x88082c0, flagarray=0x8194040) at build.c:315
315                 strcat( buf, flagarray[x] );


x is 31.

[EDIT] I guess I was missing a flag. I added BFS_MARK to the end.
So the only thing I need to know is how to convert this to EXT_BV:
            if ( match == (match & pRoom->room_flags)

Amended on Tue 29 Mar 2005 12:22 AM by Zeno
Australia #14
if ( match == (match & pRoom->room_flags)

Errrr you lost me on that, i dont have anything in my code that faintly resembles that.

Just out of curiosity, what does match do, or is it just a variable.


[EDIT]
So match compares strings, did some looking up heh, i think im more lost than ever.
Amended on Tue 29 Mar 2005 02:58 AM by Robert Powell
USA #15
That line is in grub.c, under do_diagnose.

   ch_printf (ch, "\n\rRoom Vnums\n\r");
   for (cou = 0; cou < MAX_KEY_HASH; cou++)
   {
      if ( room_index_hash[cou] )
         for (pRoom = room_index_hash[cou]; pRoom; pRoom = pRoom->next)
         {
            if (pRoom->vnum >= lo && pRoom->vnum <= hi)
            {
            if ( match == (match & pRoom->room_flags)
            && hit_cou < DIAG_RF_MAX_SIZE)
               vnum[hit_cou++] = pRoom->vnum;
            }
         }
   }
Australia #16
I must be realy lucky as i do not have grub.c in SmaugFUSS, i guess if you dont use diagnose you could just scrub it, and from what the help file says diagnose will return the most popular objects in the game, something i have no need to know.

So i guess what that part of the code is cheching is for how many rooms in the mud have that room flag?

For my mind if no one uses diagnose then blow it away.
USA #17
Diagnose is really useful in my opinion. It can find room flags in the mud without having to grep through area files.
Canada #18
The "&" operation basically make a comparison between two sets of bit flags. In this case, it takes the value(s) of match, compares it to the room flag, and re-sets match to contain only matching flags. It kind of works like this:

    01010101
 &  11110001
------------
 =  01010001
It only matches if both are set, so this is kind of filtering everything else out of the equation. In this case, I beleive that it is, and please anyone correct me if I am wrong, checking to see if whats supplied in the match variable is an exact match to the room flags. Now I'm not great with bitwise code, but if match and the rooms flags weren't exactly the same, then the result would not be equal to match, and so the code in the if check only gets executed if match has the same value as room_flags, at which point it puts the room in an array of rooms to be printed, I would assume?

If this is the circumstance, and you want to use xBV's, you could make a small function, if one doesn't already exist that just loops through the array of integers in the extended bitvectors and compares index 0 to index 0, 1 to 1, etc, and if all of them match, then add it to the list. You would also need to convert match to an extended bitvector, and set it with the extended bitvector functions.

[EDIT]
K, so a quick check came up with this:

#define xSAME_BITS(var, bit)	(ext_same_bits(&(var), &(bit)))

/* for use by xSAME_BITS() -- works like == */
bool ext_same_bits(EXT_BV * var, EXT_BV * bits)
{
        int       x;

        for (x = 0; x < XBI; x++)
                if (var->bits[x] != bits->bits[x])
                        return FALSE;

        return TRUE;
}

This should produce the same effect. Hope this helps.

[EDIT2]

Sure seem to be alot of edits lately, huh? Anyways, after looking at that again, its not checking for an exact match, its checking to see if all the flags specified in match are also in room_flags, but allows for more than just the ones specified, so you probably want to use xHAS_BITS(var, bit) instead.

You should be able to use
   ch_printf (ch, "\n\rRoom Vnums\n\r");
   for (cou = 0; cou < MAX_KEY_HASH; cou++)
   {
      if ( room_index_hash[cou] )
         for (pRoom = room_index_hash[cou]; pRoom; pRoom = pRoom->next)
         {
            if (pRoom->vnum >= lo && pRoom->vnum <= hi)
            {
            if ( xHAS_BITs(pRoom->room_flag, match)
            && hit_cou < DIAG_RF_MAX_SIZE)
               vnum[hit_cou++] = pRoom->vnum;
            }
         }
   }
Not tested, but lemme know.
Amended on Tue 29 Mar 2005 05:45 AM by Greven
USA #19
Quote:

#define BFS_MARK 536870912


Surprised nobody caught this :)

Just for fun, what happens if you try to access the 536870912th an array that's only 128 members long? :)

The BFS_MARK value needs to be tamed basically. 536870912 may have been appropriate when your bitflags were huge values and this was expected. But it's a Bad Thing(tm) with EXT_BV. IT's probably best to include BFS_MARK in your new enum of room flags and reserve a spot for it in the r_flags list in build.c so that you don't get them out of synch.
USA #20
Yes we (Saiyr and I) were aware that was not a thing that would work, but the gdb really was pointing us in the wrong direction. So I finally just went and removed that line, and added it to the enum list. Works fine.
USA #21
The reason why we "semi-caught" it, was because it's still defined like that in the DBSC codebase...but it still works. I still blame our having to take a long time to solve this problem on miscommunication.

On the other hand, Greven, I don't think that'll work. EXT_BVs typically use the size of 4 ints, being 16 bytes or 128 bits. This won't fit into a single integer, obviously, which is what match is setup to be. I haven't thoroughly tested what I've done, but I think mine works. http://www.sourceforge.net/projects/dbsaga (Zeno already knows about this, this is really just for you) has it under the patch tracker. I basically said, "Why use numbers instead of actual flag names? Not everyone knows how to calculate bitvectors." I revamped the diagnose function a bit so that it would take flag arguments instead of a bitvector that could just be obtained with atoi. I've done some testing, and it works well from what I've seen. Using numbers, still, you would have to use fread_bitvector on it, rather than atoi. Personally, I don't know how to type in EXT_BV's in number form, anyway. Never bothered to look at it.
Amended on Tue 29 Mar 2005 04:45 PM by Saiyr
Canada #22
See with this I had no clue how it actually worked. I generally work with SWR and it doesn't have this commands, so I'm a little unfamiliar. You actually had to enter the flags number? That would be less than useful I would think.
USA #23
Yep. That's what I was thinking, also. Apparently you're supposed to enter the bitvector in int form already, which is kinda silly. Using words is so much more user-friendly. I don't actually have a use for this command at all; I've never used diagnose. I fixed it because he asked me about it, and I actually understand bitwise operations fairly well now.
Canada #24
See with this I assumed that you entered flags names, and it looped through the supplied list, took a number, and used SET_BIT based on the comparison between the names your entered and the value, similiar to how you can apply multiple flags at once while building. If this were the case, as I had erroneously though, all would have to do is create a local EXT_BV variable, and use the xSET_BIT on the local based on the supplied names, and then compare that to the rooms flags.