RT ASCII stuff...

Posted by Nash on Wed 26 May 2004 02:14 AM — 23 posts, 74,229 views.

USA #0
ROM2.4b6, and I'd assume most of its siblings, uses 32 bit ascii rt blah something to assign bits to various things, like act_ and aff_ etc. The problem is you only can have 32 different things like this for each, if I wanted to expand that system to like 64 or something, where exactly would I go... or rather is there anything I should be concerned about in taking this approach so that I can add more act and aff types to a mud?
USA #1
32 bit ascii rt huh??

I think what you mean is that it uses a 32-bit integer with bit masks... and sine the integer is 32 bits in size you only have 32 bits to toggle on and off.

The easy way to expand this is to use long longs (__int64 on Windows, long long on Unix), which will give you 64... but, you'll have to make an awful lot of changes. Notably, any code that accesses these will have to be aware of the new 64-bit version.

Optionally you could look at the later versions of SMAUG, which have something called EXT_BV I believe which gets around this problem.

Of course, the right thing to do would be to make your own data type, but that's a considerably harder task. :)
USA #2
I probably changed the ints to long the bad way, because I get a large large error message and it all starts with:

merc.h:47: conflicting types for `system'
/usr/include/stdlib.h:694: previous declaration of `system'

and by ascii rt I meant..

/* RT ASCII conversions -- used so we can have letters in this file */

#define A 1
#define B 2
etc..
Amended on Thu 27 May 2004 06:05 AM by Nash
USA #3
Quote:
I probably changed the ints to long the bad way, because I get a large large error message and it all starts with:


You probably changed way more ints to long than you were supposed to.

Quote:
and by ascii rt I meant..

/* RT ASCII conversions -- used so we can have letters in this file */

#define A 1
#define B 2
etc..


...and these have what to do with the bitvectors? Those are just letters.
USA #4
What specific integers do I need to change into longs for this to work then, or... am I going about it wrong..?

Those are used to recognize the bits from the save files, those are assigned to act_ flags or aff_flags or any of the non-number based flaggies.. likkkkeeeeeeeee


#define ACT_MAGE (R)
#define ACT_THIEF (S)
#define ACT_FIGHTER (T)
#define ACT_NOALIGN (U)
#define ACT_NOPURGE (V)
#define ACT_OUTDOORS (W)
#define ACT_INDOORS (Y)
#define ACT_IS_HEALER (aa)
#define ACT_GAIN (bb)
#define ACT_UPDATE_ALWAYS (cc)
USA #5
Then there must be some other conversion going on, because to make it work as flags - if indeed they are using the bitvector scheme and there is no reason they wouldn't be. There must be a bitshift somewhere where those values are set. Can you give an example of where those flags are actually set?

The flags actually *are* number-based, by the way... that's what the defines are all about.

You have to change the variables which store these flags and the routines that read from them, but frankly it's a rather complicated coding task.
USA #6
these are like flags... like, they just exist, and your mob or players can have them, like a thief would be flagged with 'act_thief' and it can just run through and check if the character has the act flag 'act_thief' I believe that code in my last post was it being defined, because... like (ee) is like "#define ee 1073741824"

so yes, I know they're number based..
#define ACT_THIEF (S)
#define S 262144
so act_thief = 262144, which is part of some 32 bit saving system ROM2.4b6 uses..
'ee' is the largest it can go to, any attempt to expand it crashes with the error that I've exceeded the limit for an integer, which is true! Since integers are tiny..
USA #7
*ahem* I think I know how a bit-based flag system works. :) I'm not sure why they found it necessary to give the bitmasks letters... but, whatever.

Ints aren't as small as you think. I think you're not quite sure how these flags work. They are bitmasks. The number you gave just happens to be, in binary: 1000000000000000000. And if you look at R, lo and behold, it will be: 100000000000000000. Every time your letters move down (silly notation, BVxx or BMxx is much better) you will lose one zero in binary.

When you combine flags, for instance: 1 (1) and 2 (10), you get in binary 11.
So, if you were to combine from A to S, you get in binary: 1111111111111111111, which is 524,287 in decimal.

The maximum value for integers is 4294967296, assuming unsigned integers. You're probably using signed integers, in which case you "only" have 2,147,483,648. If 2 billion is "tiny" for you, I wonder what big is! That being said, the numeric decimal size of the integer is basically worthless; here we are only interested in the bits.

In any case you have two options. Either you stick with a bitmask system and go from 32-bit integers to 64-bit integers (long long on Unix, __int64 on Windows)... or you get rid of the bitmask system, and use something else (an array of bools, for example, or even smarter, a custom data structure that uses an array of integer bitmasks.) In the bitmask system, you are *always* limited to the number of bits you have available. 32-bit integers will provide no more than 32 flags. That's just the way it is. And if you use 64-bit integers, you will have no more than 64.
USA #8
I know how small integers are, just... they're used as 32 ones and zeroes to flag stuff in this case, so no matter what I'm limited to 32, but yes, it'd be nice to make a datastructure, but I really haven't the slightest clue how, and I probably won't be expanding it so much that I need more than 64 bits, but I apparently don't know which integers I wanna convert to long, and if it's just as easy as changing the variable from 'int whatever;' to 'long whatever;', but if ya have any explanation of applying a data structure to the various fields where it currently uses the bit-ness, I'd like to know..
Amended on Fri 28 May 2004 02:38 PM by Nash
USA #9
I said 'long long', not 'long'. If you change to long you likely won't be changing anything since on many systems ints and longs are both of 32 bits.

You need to change:
- the variables that store the flags
- the macroes that read/write the flags
- the functions that save/load the flags to file

Proceed at your own risk, however :)
USA #10
Am I doing something wrong to define a longlong? It's my understanding you do simply 'long long <variable>;', it works except I get the following errornicities...

db.c:2068: warning: decimal constant is so large that it is unsigned
->if (IS_SET(mob->act,ACT_SHAMAN))<-

handler.c:2681: warning: decimal constant is so large that it is unsigned
->if (act_flags & ACT_SHAMAN ) strcat(buf, " shaman");<-

tables.c:106: warning: decimal constant is so large that it is unsigned
->{ "shaman", ff, TRUE },<-

and ACT_SHAMAN is set as 'ff' which is set as '2147483648'

I set the bit variable in act_flags to a long long, but it apparently don't like it... and... just wondering if I define longlongs wrong
USA #11
Well, for one, you need to change all functions that access the new format.

For two, typically you don't define these constants the way your MUD is... you define them as bitshifts. e.g. 1 << 32

That should remove the warnings, but I suggest you look at code that actually uses that technique e.g. SMAUG 1.4.
USA #12
hm... lost me on the bitshift :D

the closest thing found there was "#define BV31 (1 << 31)" which isn't used in the flags, apparently they use a table for the various flags and such... but I'm still learning to code-alize, and that's way way beyond me..
Amended on Sun 30 May 2004 12:55 AM by Nash
USA #13
"Code-alize"? :P

The BVxx is the way you're "supposed" to do the flags, i.e. proper bitshifts and not decimal constants.

Do you understand binary and how bitmasks work?

If I may say so, no offense but you're trying something rather difficult but don't seem to know much about coding. More likely than not you'll just get frustrated here. Have you looked into the extended bitvector system that SMAUG has like I suggested?
USA #14
I do understand bitmasks and binary, and I have coding knowledge, but I've been more of a logic programmer, and I'm porting my knowledge of other languages over to C, which is a transistion that's not being very easy for me to make.. I learn best by asking a lot of questions and this is just something I don't understand too well, sorry for bugging you for so much clarification. I don't think I totally understand it, but it did work, and it's whittled the errors down to when you save, it seems to print weird stuff


->Afg† 0 0 0<-
(and the weird holy cross looks like an a with a circle ontop of it in shell..)

It seems to save new mobs funny... that mob had the flags 'npc' and 'shaman', and printed the above... the code for saving is in olc_save.c and I think the following function...

char *fwrite_flag( long long flags, char buf[] )
{
char offset;
char *cp;

buf[0] = '\0';

if ( flags == 0 )
{
strcpy( buf, "0" );
return buf;
}

/* 64 -- number of bits in a long long */

for ( offset = 0, cp = buf; offset < 64; offset++ )
if ( flags & ( (long)1 << offset ) )
{
if ( offset <= 'Z' - 'A' )
*(cp++) = 'A' + offset;
else
*(cp++) = 'a' + offset - ( 'Z' - 'A' + 1 );
}

*cp = '\0';

return buf;
}



and it's read in by this..

long long fread_flag( FILE *fp)
{
int number;
char c;
bool negative = FALSE;

do
{
c = getc(fp);
}
while ( isspace(c));

if (c == '-')
{
negative = TRUE;
c = getc(fp);
}

number = 0;

if (!isdigit(c))
{
while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
number += flag_convert(c);
c = getc(fp);
}
}

while (isdigit(c))
{
number = number * 10 + c - '0';
c = getc(fp);
}

if (c == '|')
number += fread_flag(fp);

else if ( c != ' ')
ungetc(c,fp);

if (negative)
return -1 * number;

return number;
}








this function also kinda stuck out to me...

long long fread_flag( FILE *fp)
{
int number;
char c;
bool negative = FALSE;

do
{
c = getc(fp);
}
while ( isspace(c));

if (c == '-')
{
negative = TRUE;
c = getc(fp);
}

number = 0;

if (!isdigit(c))
{
while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
number += flag_convert(c);
c = getc(fp);
}
}

while (isdigit(c))
{
number = number * 10 + c - '0';
c = getc(fp);
}

if (c == '|')
number += fread_flag(fp);

else if ( c != ' ')
ungetc(c,fp);

if (negative)
return -1 * number;

return number;
}
Amended on Sun 30 May 2004 03:37 AM by Nash
USA #15
What is a 'logic programmer' as opposed to a 'normal programmer'? What language did you program in?

Do you understand what this is doing:

 for ( offset = 0, cp = buf; offset < 64; offset++ )
if ( flags & ( (long)1 << offset ) )
{
if ( offset <= 'Z' - 'A' )
*(cp++) = 'A' + offset;
else
*(cp++) = 'a' + offset - ( 'Z' - 'A' + 1 );
}
USA #16
It means I suck with math, I'm better with more graphics type games, as opposed to thinking of the world in math functions, it's weird checks and word functions. I used to code vb and javascript, and the little c and j I did for a month, the former of which I'm trying to relearn! The function you point out writes letters to the designated file, which correspond to the different flags of a mob, apparently going based on the ascii of the upper/lower case letters... I don't understand totally how it works, but I know what it does.. it'd be more effective probably to write down 64 0's and then for each of those flags that's active, change its corresponding 0 to a 1, and then have it read in that way as well.. unless I have how it works wrong!
Amended on Sun 30 May 2004 04:48 AM by Nash
USA #17
With all due respect you can't cover C or Java in just a month if you've never done real programming before.

What that function is doing is writing out the letter constants that were given to the decimal constants. For instance, if the offset is zero, it will write A. If the offset is three, it will write D. If the offset is 26, it will write 'a'.

What this means is that you have an upper limit of 52=26*2 possible flags. If the system were more a little more intelligent, it wouldn't have such an upper limit.

You could write out the binary representation of the flag. That would be 64 characters, however. It would take up less memory to write out the decimal version. Only problem is that manipulating 64-bit numbers is harder than 32-bit numbers.

One problem is that you cast the bitshift to long and not long long. This won't work at all if your bitshift goes out of long range, which is clearly does since offset goes to 64.

Allow me to warn you again: what you are attempting to do is non-trivial and you seem to be a novice coder. I strongly suggest that you look at SMAUG's EXT_BV code. Have you done that yet?
USA #18
altered that for loop, trying to make it work a bit better, and it sorta prints it in binary.. but it ends up looking like this!

#818
no name~
(no short description)~
(no long description)
~
~
human~
1111111111111111111111111111111111 0 0 0
0 0 0d0+0 0d0+0 0d0+0 none
0 0 0 0
0 0 0 0
stand stand none 0
0 0 medium unknown
F for 1111
F par 11111111111
USA #19
How am I supposed to know if that output is correct or not? Besides, if it's wrong, there's only one reason: you must have made a mistake in your output code.

Forgive me for copy/pasting, but... Allow me to warn you again: what you are attempting to do is non-trivial and you seem to be a novice coder. I strongly suggest that you look at SMAUG's EXT_BV code. Have you done that yet?
USA #20
I have... smaug uses a structure to store flags, and reads/loads them all differently... I can paste in the functions.. but I'd have to know which you need to see ...I'm trying really hard to learn this and figure out the workings of it all, but it's quite hard to learn c on your own, thank ya for this.. but... yea smaug does it weird. So, in fwrite_flag, it should write out a 0 for each inactive flag, and a 1 for each active one, and then in fread_flag, do the reverse?

new fwrite_flag?->
for ( offset = 0, cp = buf; offset < 64; offset++ )
if ( flags & ( (long long)1 << offset ) )
{
*(cp++) = '1';
}
else
{
*(cp++) = '0';
}
Amended on Sun 30 May 2004 06:23 AM by Nash
USA #21
What you should do is do as SMAUG does in order to read and write flags. Imitate what they have. SMAUG doesn't do it "weird", chances are, they do it "right". :)

Very seriously, you should learn C before you do something non-trivial like this. Your function looks like it's right, but chances are you're forgetting something somewhere else. What is the type of 'flags'?
USA #22
actually.. somehow it works now, but... I get this:

In file included from /usr/include/bits/sigcontext.h:28,
from /usr/include/signal.h:313,
from comm.c:92:
/usr/include/asm/sigcontext.h:76: syntax error before numeric constant
/usr/include/asm/sigcontext.h:80: syntax error before '}' token


:(