01 Mar, 2008, Banner wrote in the 1st comment:
Votes: 0
This topic involves races and languages and bitvectors, and how to extend them. I'm using a modified version of SWRFUSS.

Anyway, I wanted to extend races and languages so I could have more than 32, since bitvectors stop at 32. I tried putting them in a typedef enum table, and while it seemed to work for races, languages had several problems, such as not showing up on the LANGUAGES command, and mobs reporting that they were trying to speak a null language.

I think the problem originated somewhere around LANG_UNKNOWN.


Here's how it originally looks:
#define LANG_COMMON      BV00                          
#define LANG_SHYRIIWOOK BV01
#define LANG_TWI_LEK BV02
#define LANG_RODIAN BV03
#define LANG_HUTT BV04
#define LANG_MON_CALAMARI BV05
#define LANG_NOGHRI BV06
#define LANG_EWOK BV07
#define LANG_ITHORIAN BV08
#define LANG_GOTAL BV09
#define LANG_DEVARONIAN BV10
#define LANG_BINARY BV11
#define LANG_SPIRITUAL BV12
#define LANG_MAGICAL BV13
#define LANG_GAMORREAN BV14
#define LANG_GOD BV15
#define LANG_ANCIENT BV16
#define LANG_JAWA BV17
#define LANG_CLAN BV18
#define LANG_ADARIAN BV19
#define LANG_VERPINE BV20
#define LANG_DEFEL BV21
#define LANG_TRANDOSHAN BV22
#define LANG_CHADRA_FAN BV23
#define LANG_QUARREN BV24
#define LANG_BOTHESE BV25
#define LANG_UNKNOWN 0 /* Anything that doesnt fit a category */
#define VALID_LANGS ( LANG_COMMON | LANG_SHYRIIWOOK | LANG_TWI_LEK | LANG_RODIAN \
| LANG_HUTT | LANG_MON_CALAMARI | LANG_NOGHRI | LANG_GAMORREAN \
| LANG_JAWA | LANG_ADARIAN | LANG_EWOK | LANG_BINARY | LANG_VERPINE | LANG_DEFEL \
| LANG_TRANDOSHAN | LANG_CHADRA_FAN | LANG_QUARREN | LANG_BOTHESE )


Here is how I had it:
/*
* Languages – Altraag
*/
#define LANG_UNKNOWN 0 /* Anything that doesnt fit a category */
typedef enum
{
LANG_COMMON, LANG_SHYRIIWOOK, LANG_TWI_LEK, LANG_RODIAN, LANG_HUTT, LANG_MON_CALAMARI,
LANG_NOGHRI, LANG_EWOK, LANG_ITHORIAN, LANG_GOTAL, LANG_DEVARONIAN, LANG_BINARY,
LANG_SPIRTUAL, LANG_MAGICAL, LANG_GAMORREAN, LANG_GOD, LANG_ANCIENT, LANG_JAWA,
LANG_CLAN, LANG_ADARIAN, LANG_VERPINE, LANG_DEFEL, LANG_TRANDOSHAN, LANG_CHADRA_FAN,
LANG_QUARREN, LANG_BOTHESE
} lang_types;
#define VALID_LANGS ( LANG_COMMON | LANG_SHYRIIWOOK | LANG_TWI_LEK | LANG_RODIAN \
| LANG_HUTT | LANG_MON_CALAMARI | LANG_NOGHRI | LANG_GAMORREAN \
| LANG_JAWA | LANG_ADARIAN | LANG_EWOK | LANG_BINARY | LANG_VERPINE | LANG_DEFEL \
| LANG_TRANDOSHAN | LANG_CHADRA_FAN | LANG_QUARREN | LANG_BOTHESE )



I also commented out the define for LANG_UNKNOWN and tried putting it in the table:
typedef enum
{
LANG_COMMON, LANG_SHYRIIWOOK, LANG_TWI_LEK, LANG_RODIAN, LANG_HUTT, LANG_MON_CALAMARI,
LANG_NOGHRI, LANG_EWOK, LANG_ITHORIAN, LANG_GOTAL, LANG_DEVARONIAN, LANG_BINARY,
LANG_SPIRTUAL, LANG_MAGICAL, LANG_GAMORREAN, LANG_GOD, LANG_ANCIENT, LANG_JAWA,
LANG_CLAN, LANG_ADARIAN, LANG_VERPINE, LANG_DEFEL, LANG_TRANDOSHAN, LANG_CHADRA_FAN,
LANG_QUARREN, LANG_BOTHESE, LANG_UNKOWN
} lang_types;


That stopped most of the bug spam about null languages, although most mobs then spoke several languages, and one mob was still reporting a null language, and my ch->speaking and ch->speaks was negative. Anyway, my question is, is there any other way to easily extend the bitvectors so I can have virtually unlimited race and language creation abilitites, or a way to fix the languages to work in a typedef enum table? Thanks in advance.
02 Mar, 2008, drrck wrote in the 2nd comment:
Votes: 0
Enumerated types don't work like that. An enumerated type will assign values like 0, 1, 2, 3, 4, 5, … and that's going to mess up a bit flagged variable because most of these numbers will take up more than 1 bit each.

What you need to do is simply change it back to the way it was previously, and change the data type of whatever variable you're storing languages in to a 64-bit integer instead of 32-bit (on most systems, this will be the long long int data type). Then simply add more BV?? power of 2 constants and define your new language constants to these.

For example:
#define BV26 67108864
#define BV27 134217728
#define BV28 268435456
// etc…

#define LANG_MANDARIN BV26
#define LANG_PORTUGUESE BV27
#define LANG_EBONICS BV28
// etc…
02 Mar, 2008, Banner wrote in the 3rd comment:
Votes: 0
How do you know what to assign as the declaration for new BVxx? Just double the number (268435456) and define it for BV29? Also, why long long int if it's already assigned to use bitvectors? Does it need long long int since it'll now be using more than 32? And is it the same for races? My races are #define RACE_HUMAN 0 instead of BV00, so is it okay to store in an enum table?
02 Mar, 2008, Kayle wrote in the 4th comment:
Votes: 0
Could always just install Extended Bitvectors like the later versions of Smaug have.
02 Mar, 2008, drrck wrote in the 5th comment:
Votes: 0
Banner said:
How do you know what to assign as the declaration for new BVxx? Just double the number (268435456) and define it for BV29? Also, why long long int if it's already assigned to use bitvectors? Does it need long long int since it'll now be using more than 32? And is it the same for races? My races are #define RACE_HUMAN 0 instead of BV00, so is it okay to store in an enum table?


The BV?? constants are just masks for power-of-2 values that require only 1 bit to represent.

For example, in an 8-bit integer:
1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000
16 = 00010000
32 = 00100000
64 = 01000000
128 = 10000000

With each mask taking only 1 bit, you can now store up to 8 flags worth of information in this 1 variable, so that if BV12 = 8 and BV16 = 128, and LANG_CHINESE = BV12 and LANG_GERMAN = BV16, then someone who knows both languages will have a language variable that looks like this: 10001000

Changing the variable type to long long int is going to double the number of bits that you have to represent flags, from 32 to 64. To find the new BV?? values, just double the previous constant's value (making sure the value you use is some power of 2, or it won't work).

Races usually aren't represented as bit flagged variables because a person can usually only have one race, so there's no need for flags. So, yes; using an enumerated type for races would be OK.

Kayle said:
Could always just install Extended Bitvectors like the later versions of Smaug have.


Maybe, but then he wouldn't necessarily learn how they work ;)
03 Mar, 2008, Davion wrote in the 6th comment:
Votes: 0
Instead of calculating the values, you can use bit shifting ot make it look a little nicer. Eg.

#define BV26 1 << 26
#define BV27 1 << 27
#define BV28 1 << 28
03 Mar, 2008, Banner wrote in the 7th comment:
Votes: 0
drrck said:
The BV?? constants are just masks for power-of-2 values that require only 1 bit to represent.

For example, in an 8-bit integer:
1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000
16 = 00010000
32 = 00100000
64 = 01000000
128 = 10000000


I still don't understand what you mean there.


drrck said:
Changing the variable type to long long int is going to double the number of bits that you have to represent flags, from 32 to 64. To find the new BV?? values, just double the previous constant's value (making sure the value you use is some power of 2, or it won't work).


I can change the language value to lon long int, and I understand that it'll double from 32 to 64, but how do I find the new BV?? values? How do I know what 32's value is, 20's value, ect.. and what do you mean by power of 2? 32 squared gives me 33? 33 squared gives me 34?
03 Mar, 2008, Davion wrote in the 8th comment:
Votes: 0
Banner. How bit's work is they're stored in a 32-bit integer (most of the time.) Which means, the integer (in binary) looks like
0000 0000 0000 0000 0000 0000 0000 0000


Those 0's can only become 1's. Now, starting from the right, to the left, the numbers go up by the power of two.

0000 0000 0000 0000 0000 0000 0000 0001


This is what 1 looks like.

0000 0000 0000 0000 0000 0000 0000 0010

This is two.

0000 0000 0000 0000 0000 0000 0000 0100

That's four

0000 0000 0000 0000 0000 0000 0000 1000


That's eight. It goes all the way up to 2^32 (16, 32, 64, 128, 256, 512, 1024, etc)

Say you want to set PLR_AUTOLOOT and it's defined as 1 << 1, and you want to set PLR_AUTOEXIT and it's 1 << 4. The int would then look like

0000 0000 0000 0000 0000 0000 0000 1001


You have now set the 1st, and 4th bit (The integer's value is now 9.)

Now, if you're using enums, you can see where this'll go wrong. If you set say, PLR_NOSUMMON, which is 9, adding that to the int would set the 4th and 1st bit.


Banner said:
I can change the language value to lon long int, and I understand that it'll double from 32 to 64, but how do I find the new BV?? values? How do I know what 32's value is, 20's value, ect.. and what do you mean by power of 2? 32 squared gives me 33? 33 squared gives me 34?


Read my previous post.
03 Mar, 2008, Davion wrote in the 9th comment:
Votes: 0
To further explain
Davion said:
Instead of calculating the values, you can use bit shifting to make it look a little nicer. Eg.

#define BV26 1 << 26
#define BV27 1 << 27
#define BV28 1 << 28


This defines BV26 as "1 << 26"

<< is a bitwise operater that shifts the bits of x, n movements to the left. This shifts the bits of 1, 26 movements left.

To refer to my last post,

0000 0000 0000 0000 0000 0000 0000 0001


This is 1, so we'll shift it's bits 26 left…
0000 0010 0000 0000 0000 0000 0000 0000


The value of this int is going to be (2^(26-1) ) or 33554432
03 Mar, 2008, David Haley wrote in the 10th comment:
Votes: 0
You can think of shifting one bit to the left as multiplying by two, if that makes it easier. Shifting to the right is integer division by two, so 3 >> 1 is equal to 1. I find it easier to think of it that way than going to binary, moving the bits, and then going back to decimal.

As a somewhat interesting side comment, if you care about every last assembly instruction (which, in MUD programming, we typically don't) it is more efficient to write "x >> 1" than to write "x/2". That said, a smart compiler will translate "x/2" to "x >> 1" anyhow…

EDIT: fixed "smart compiler" behavior……
03 Mar, 2008, KaVir wrote in the 11th comment:
Votes: 0
drrck said:
Changing the variable type to long long int is going to double the number of bits that you have to represent flags, from 32 to 64


He should use an unsigned integer if he's shifting the bits around (i.e., unsigned long long), otherwise he'll run into issues with the signed bit and arithmetic shifts. However "long long int" is only a standard data type in C99, with some C89 compilers providing it as an extension; a safer, more portable and easier to extend approach would be to use an array of unsigned chars. I believe the "Extended Bitvectors" implementation Kayle refered to uses such an array.
03 Mar, 2008, KaVir wrote in the 12th comment:
Votes: 0
DavidHaley said:
That said, a smart compiler will translate "x/2" to "x << 1" anyhow…


Hopefully it'll translate it into "x >> 1" instead ;)
03 Mar, 2008, David Haley wrote in the 13th comment:
Votes: 0
Indeed, I had just written << so I guess my fingers were stuck on <<. :smile: I fixed the post to avoid confusion…
03 Mar, 2008, Banner wrote in the 14th comment:
Votes: 0
That's too confusing. All you're telling me is a bunch of stuff I don't know. Is there another way to do it?
03 Mar, 2008, David Haley wrote in the 15th comment:
Votes: 0
Banner said:
How do I know what 32's value is, 20's value, ect..

Davion gave you the method:
Davion said:
This defines BV26 as "1 << 26"


To understand this you need to understand how the flags work. Basically, the bits in the flag binary number indicate which flags are turned on. If the "1" bit is on, flag 1 (i.e. BV01) is on. If the "2" bit is on, flag 2 is on. If the "4" bit is on, flag 3 is on; bit 8 means flag 4; and so on. You go up in powers of two because that's how binary works: each bit means adding a power of two.

You can think of it this way: to translate from binary to decimal, you take the sum, for i=0 to n, of 2^{bit_i}, where bit_i is the i'th bit of the number. Bit 0 is the smallest, i.e. right-most, bit. n is typically 32, for 32-bit numbers. If this doesn't make any sense, ignore it.

The point is that you should set BVx to 1 << x.
03 Mar, 2008, KaVir wrote in the 16th comment:
Votes: 0
Banner said:
That's too confusing. All you're telling me is a bunch of stuff I don't know. Is there another way to do it?


Here's a basic overview of bitvectors that I wrote several years back. It's pretty basic, but you might find it helpful: http://homepage.ntlworld.com/r.woolcock/...
19 Mar, 2008, Banner wrote in the 17th comment:
Votes: 0
If I wanted to simply make them extended bitvectors, do I just change 'int language' to 'EXT_BV language' in struct race_type in mud.h?

That'd then allow mt to put the languages into an enumerated table, right? Is there anything else I need to do?
19 Mar, 2008, David Haley wrote in the 18th comment:
Votes: 0
You'd have to access them using the EXT_BV calls, too. I don't remember what exactly the functions (or macros) are, but you could find that by looking at one of the existing EXT_BV uses.
19 Mar, 2008, Kayle wrote in the 19th comment:
Votes: 0
xIS_SET, xSET_BIT, xREMOVE_BIT, xCLEAR_BITS, and theres.. Um.. one other one that I can't remember.
19 Mar, 2008, kiasyn wrote in the 20th comment:
Votes: 0
xTOGGLE_BIT
0.0/23