   _____   ____     ____     _____  __    _  __ _     __     ____     _____
  /@/   ) /@/  )   /@/  \   /@/    /@ \   / /@ V \   /@ \   /@/  )   /@/   
 /@/ --/ /@/ -<   /@/    | /@/--  /@/\ \ / /@/\_/ \ (@(  ) /@/ -<   /@/--  
(@(   ( (@(    \ (@(____/ (@(___ (@(  \_/ (@(     _\ \@_/ (@(    \ (@(___  

Ammaross Danan's Unlimited Bit Snippet v1.1 for Rom24.

Features:
- Unlimited Bits.
- Bit arrays that can be expanded OR contracted at any time.
- Works very well. ;)

Comment from the Author:
     I used Erwin Andereason's unlimited bit system as reference 
for concepts, and modified his hex version of STR_IS_SET, etc. for mine,
but if anyone has seen his 'snippet' stuff, you will know that the end
implementation ends up original. I believe he is doing more good with his
'use this concept to write your own code' than any ten 'hand holding'
snippets could, and I extend my thanks. This is a 'hand holding' snippet,
but has a 'conceptual' nature to it also.


BE WARNED NOW:
- IF YOU DO NOT HAVE OLC, >> DO NOT << IMPLEMENT THIS FOR ANYTHING THAT
     SAVES IN AREA FILES. This is basically all the flags, except COMM_***,
     that would be worth changing over. Throughout this, I will be assuming
     that you have OLC, and giving instructions to add things into OLC-
     specific code. Just ignore these if you do not have OLC.
- This snippet leaves your current bit system intact, it effects only what
     you wish to run on this new system.
- This walkthrough will not hold your hand.
- If you mess your code up, restore from backup and try again,
     or delete this snippet.
- MAKE SURE YOU HAVE A BACKUP THAT YOU MADE IMMEDIATELY PRIOR TO USING THIS.
- This will run you though almost every file your mud has, and will draw
     on your personal knowledge of your code (since I am assuming your are
     not running stock).
- This walkthrough is left open-ended on what exactly should be converted to
     this new system. It gives an example of the hardest and most asked about
     flags to convert: the affects.
- If you have an aff2 snippet added already, this WILL STILL WORK. I do not
     have all the places marked where you would need to convert over, but I
     provided the utilities to do so.
- You WILL have to keep ALL headers or work references in tact, and add the
     attached help entry to use this snippet. If any work is derived from
     the ideas presented in this snippet, please give credit, it is not that
     hard to add a 'with thanks to Ammaross Danan (ammaross@ardenmore.com) for
     the base idea' to a help file and your code.

------------------------------------------------------------------------------

Now, with that out of the way, lets get our hands dirty. ;)
( all comments for installing this are denoted by a // before hand and do not
have to be added, but the comments in /* */ should be added for easy coding )
And remember, I am going to step through most of implementing this for the
AFF_*** flags, so if I "purposely" ;) miss anything, try to figure it out on
your own. But if you are still stumped, and are willing to prove you have tried,
email me or the ROM list.

Convience note: I put comments about the various parts of this implementation
  AFTER the actual code, that way, you know what I am talking about.


>>> MERC.H <<<
--------------

// SOMEWHERE, preferably close to the top of merc.h, put these defines.

/* Datatype that flag is. This is mainly here for readability */
typedef int		FLAG;
#define	FLAG_BITSIZE	16	/* Bitsize of FLAG. 16 bits in a int. */

/* Flag string sizes */
#define AFF_FLAGS		2	/* Max amount of flags = FLAG_BITSIZE * AFF_FLAGS */

/* Max amount of bit flags */
#define MAX_FLAGS 		2	/* This must ALWAYS be equal to, or higher than ANY
							 * of the current ***_FLAGS. If you encounter mem
							 * overflows, suspect this is too low, or one of your
							 * ***_FLAGS is set too low. */

// There has been much debate over whether int is better than char or vise versa
// but I personally do not want to increment this AFF_FLAGS or whatever ever time
// I decide to throw in a few new flags. Every increment will give 16 new flags.
// 1 byte does not make all that much of a difference anyway. (the most it would
// run up to is around 3000 bytes in memory on most muds anyway).
// But, if you want to change it to char, just change the FLAG typedef to 'char'
// and change FLAG_BITSIZE to 8, and then come up with your own dynamic way of
// storing those in the area/data files.

=======

// Put this just above the current 'SET_BIT' type macros.

// Infinate flag macros
#define STR_ZERO_STR(var,size)  { int i; for(i=0;i<(size);i++){(var)[i]=0;} }
#define STR_SAME_STR(a,b,size)  (memcmp((a),(b),(size))==0)
void STR_COPY_STR args( ( FLAG * a, const FLAG * b, const int size) );
#define STR_AND_STR(a,b,size) \
	{ int i;for(i=0;i<(size);i++){(a)[i]&=(b)[i];} }
#define STR_OR_STR(a,b,size) \
	{ int i;for(i=0;i<(size);i++){(a)[i]|=(b)[i];} }
#define STR_XOR_STR(a,b,size) \
	{ int i;for(i=0;i<(size);i++){(a)[i]^=(b)[i];} }
#define STR_NOT_STR(a,size) \
	{ int i;for(i=0;i<(size);i++){(a)[i]=~(a)[i];} }
#define STR_REMOVE_STR(a,b,size) \
	{ int i;for(i=0;i<(size);i++){(a)[i]&=~((b)[i]);} }
bool STR_IS_ZERO	args( ( FLAG *var, int size ) );
//tests to see if any bits in one string is the same as in another string
bool STR_AND		args( ( FLAG *var1, FLAG *var2, int size ) );
#define STR_IS_SET(var,bit) \
	((((FLAG *)(var))[((bit)/FLAG_BITSIZE)]) &   ((1<<((bit)%FLAG_BITSIZE))))
#define STR_SET_BIT(var,bit) \
	((((FLAG *)(var))[((bit)/FLAG_BITSIZE)]) |=  ((1<<((bit)%FLAG_BITSIZE))))
#define STR_REMOVE_BIT(var,bit) \
	((((FLAG *)(var))[((bit)/FLAG_BITSIZE)]) &= ~((1<<((bit)%FLAG_BITSIZE))))
#define STR_TOGGLE_BIT(var,bit) \
	((((FLAG *)(var))[((bit)/FLAG_BITSIZE)]) ^=  ((1<<((bit)%FLAG_BITSIZE))))

// Just how do these work? If you are unfamiliar with bits, then it would
// not be very fruitful to expain. Try reading Erwin's bit system implementation
// for an explaination.
// However, I will give you a run down on how to use them.
// STR_ZERO_STR: zeroes out an array of the given size.
// STR_SAME_STR: compares one array to another.
// STR_COPY_STR: copies one array to another to the size specified.
// STR_AND_STR: merges 2 arrays. 01010 and 01000 would become 01000.
// STR_OR_STR: basically merges 2 arrays. 00010 and 01000 would become 01010.
// STR_XOR_STR: works like toggle, but for all bits in the array.
// STR_NOT_STR: inverts the bits.
// STR_REMOVE_STR: removes a given array from an array. 01011 and 01001 become 00010.
// STR_IS_ZERO: test to see if no bits are set.
// STR_AND_STR: same as STR_AND_STR, but rather than setting, it just tests.
// STR_IS_SET: clone of IS_SET.
// STR_SET_BIT: clone of SET_BIT.
// STR_REMOVE_BIT: clone of REMOVE_BIT.
// STR_TOGGLE_BIT: clone of TOGGLE_BIT.
// If you want to see how these actually work, compile and run bit.cpp which is
// included in this package.

=======

// In the race_type struct, change the current 'long aff;' declaration to:

FLAG	aff[AFF_FLAGS];

// This should be pretty straight forward in what it does. All other structs that
// have aff fields in them will need to be changed to mimic this. (Note: you do
// not need to rename the current variable. IE change affected_by; to
// affected_by[AFF_FLAGS];. Believe it or not, that needs to be pointed out to
// some people... ) Other structs that use aff flags: mob_index_data, char_data

=======

// Change your 'IS_AFFECTED' macro, if you have one, to this:

#define IS_AFFECTED(ch, sn)	(STR_IS_SET((ch)->affected_by, (sn)))

=======

// Now, >> comment << out your current AFF_*** defines. DO NOT DELETE THEM. You will
// need them for reference later. Just under your old AFF's, start making new AFF
// defines, replacing the A, B, C, etc with 1, 2, 3, etc. IE:

#define AFF_BLIND			(1)
#define AFF_INVISIBLE		(2)
#define AFF_DETECT_EVIL		(3)
#define AFF_DETECT_INVIS	(4)
#define AFF_DETECT_MAGIC	(5)
...

// Whenever the number in () hits a multiple of FLAG_BITSIZE (32,48,64,etc. for int),
// you will need to increment the associated max. For affects, that would be AFF_FLAGS.
// If needed, increment MAX_FLAGS also.

// If you have AFF2 type flags, do the same for them EXCEPT, rather than starting
// at 1, start at the value of your last normal AFF flag. IE, if AFF_DARK_VISION
// is 30, your AFF2 defines (which should be called AFF_*** anyway) should start
// at 31.

=======

// Just under /* ban.c */, place this:
/* bitsys.c */
FLAG *	str_fread_flag	args( ( FILE *fp, const int size ) );
FLAG *	aff_convert_fread_flag		args( ( long bits ) );
int		aff_bit_convert_fread_flag	args( ( long bits ) );
char 	*str_print_flags args( ( FLAG *flags, const int size ) );
char	*str_fwrite_flag	args( ( FLAG *flags, const int size, char *out ) );
char *	affect_str_bit_name	args( ( FLAG *vector ) );
// Do note that the old affect_bit_name was left for the BIT_COMPILE. (more later)

// If you currently have an aff2 snippet in, add this:
FLAG *	aff2_convert_fread_flag		args( ( long bits ) );


// Place this under /* olc.c */
void save_area args( (AREA_DATA * pArea) );



>>> ACT_WIZ.C <<<
-----------------

// In do_mstat(), replace:
    if (victim->affected_by)
    {
	sprintf(buf, "Affected by %s\n\r", 
	    affect_bit_name(victim->affected_by));
	send_to_char(buf,ch);
    }
    
// with
    if ( !STR_IS_ZERO(victim->affected_by, AFF_FLAGS) )
    {
		sprintf(buf, "Affected by %s\n\r",
			affect_str_bit_name(victim->affected_by));
		send_to_char(buf,ch);
    }



>>> COMM.C <<<
--------------

// In main(), just after the call to boot_db(), add this (if you don't
// have OLC 2.0, just leave that part out):
#ifdef BIT_COMPILE
	/* OLC 2.0 stuff */
    save_skills();
    save_races();
    save_command_table();
    save_socials();
    save_groups();
    /* end OLC 2.0 stuff */

    {
	AREA_DATA *pArea;
		for( pArea = area_first; pArea; pArea = pArea->next )
	    	save_area( pArea );
	}

    fprintf( stderr, "Conversions Complete.\n"
    				"Please recompile without -DBIT_COMPILE.\n" );
    exit(0);
#endif

// In nanny(), under CON_GET_NEW_RACE: in the 'initialize stats' part replace:
ch->affected_by = ch->affected_by | race_table[race].aff;

// with
STR_OR_STR( ch->affected_by, race_table[race].aff, AFF_FLAGS );



>>> CONST.C <<<
---------------

// Your race table will need to be updated. For each member of the table, you
// will need to update the aff field. Here is the human and elf members in a
// pre- and post- updated form.
// pre:
    {
     "human", TRUE,
     0, 0, 0,
     0, 0, 0,
     A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},

    {
     "elf", TRUE,
     0, AFF_INFRARED, 0,
     0, RES_CHARM, VULN_IRON,
     A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},
// post:
    {
     "human", TRUE,
     0, { 0, 0 }, 0,
     0, 0, 0,
     A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},

    {
     "elf", TRUE,
     0, { 1024, 0 }, 0,
     0, RES_CHARM, VULN_IRON,
     A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},
// Now just how to reach these numbers? Here is a table:
//|-----+----------+--------------------|
//| AFF | Equation | Value              |
//|-----+----------+--------------------|
//| 1   | 2^1      | 2                  |
//| 2   | 2^2      | 4                  |
//| 3   | 2^3      | 8                  |
//| 4   | 2^4      | 16                 |
//| 5   | 2^5      | 32                 |
//.......................................
//| 16  | 2^1      | 2                  | Notice that we start over at 16?
//| 17  | 2^2      | 4                  | We did so because we are now in the second
//| 18  | 2^3      | 8                  | int in the bit array.
// Do I really need to hold your hand? I believe you can see the pattern.
// Now, just what do we do with this? Take the literal value of your AFF flags
// in your race table. Use the equation to get the value for each one less than 16
// and add all of those values up. That is your first value. Do the same again,
// but for all values 16 and greater. That is your second value. IE
//    {
//     "human", TRUE,
//     0, {  FIRST_VALUE, SECOND_VALUE }, 0,
//     0, 0, 0,
//     A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},
// Lets deal with the bat as a last example. It has AFF_FLYING | AFF_DARK_VISION.
// Flying, being 20, would be a value of 2^5 which is 32. Dark Vision, being 26,
// would be 2^11 which is 2048. 32+2048=2080. Our values would be { 0, 2080 },



>>> DB.C <<<
------------

// In load_old_mob(), replace:
		pMobIndex->affected_by		= fread_flag( fp );
// with
#ifdef BIT_COMPILE
		STR_COPY_STR( pMobIndex->affected_by,
					aff_convert_fread_flag( fread_flag( fp ) ), AFF_FLAGS );
#else
	STR_COPY_STR( pMobIndex->affected_by, 
					str_fread_flag( fp, AFF_FLAGS ), AFF_FLAGS );
#endif

// In create_mobile(), replace:
	mob->affected_by	= pMobIndex->affected_by;
// with
	STR_COPY_STR( mob->affected_by, pMobIndex->affected_by, AFF_FLAGS );

// Still in create_mobile(), under 'else /* read in old format and convert */'
// replace:
	mob->affected_by	= pMobIndex->affected_by;
// with
	STR_COPY_STR( mob->affected_by, pMobIndex->affected_by, AFF_FLAGS );

// In clone_mobile(), replace:
    clone->affected_by	= parent->affected_by;
// with
	STR_COPY_STR( clone->affected_by, parent->affected_by, AFF_FLAGS );



>>> DB2.C <<<
-------------

// In load_mobiles(), replace:
        pMobIndex->affected_by          = fread_flag( fp )
					| race_table[pMobIndex->race].aff;
// with
#ifdef BIT_COMPILE
 		STR_COPY_STR( pMobIndex->affected_by,
 			aff_convert_fread_flag( fread_flag( fp ) ), AFF_FLAGS );
#else
        STR_COPY_STR( pMobIndex->affected_by,
        	str_fread_flag( fp, AFF_FLAGS ), AFF_FLAGS );
#endif
		STR_OR_STR( pMobIndex->affected_by,
			race_table[pMobIndex->race].aff, AFF_FLAGS );


// Still in load_mobiles(), under 'if (letter == 'F')', replace:
                else if (!str_prefix(word,"aff"))
		    REMOVE_BIT(pMobIndex->affected_by,vector);
// with
        else if (!str_prefix(word,"aff"))
        {
        	FLAG vector[MAX_FLAGS];

#ifdef BIT_COMPILE
        	STR_COPY_STR( vector,
        		aff_convert_fread_flag( fread_flag( fp ) ), AFF_FLAGS );
		    STR_REMOVE_STR( pMobIndex->affected_by, vector, AFF_FLAGS );
#else
        	STR_COPY_STR( vector, str_fread_flag(fp,AFF_FLAGS), AFF_FLAGS );
		    STR_REMOVE_STR( pMobIndex->affected_by, vector, AFF_FLAGS );
#endif
		}


// In load_objects(), near the end of the function, just after the
// 'else if (letter == 'F')', replace:
				paf->bitvector			= fread_flag(fp);
// with:
#ifdef BIT_COMPILE
				paf->bitvector			= 
						aff_bit_convert_fread_flag( fread_flag(fp) );
#else
				paf->bitvector			= fread_number( fp );
#endif



>>> FIGHT.C <<<
---------------

// In raw_kill(), replace:
    victim->affected_by	= race_table[victim->race].aff;
// with
	STR_COPY_STR( victim->affected_by, race_table[victim->race].aff, AFF_FLAGS );



>>> FLAGS.C <<<
---------------

// DELETE this file. A modified do_flag() has been put into the bitsys.c file.
// Don't forget to remove it from your makefile if you use one.



>>> MEM.C (OLC specific file) <<<
---------------------------------

// In new_mob_index(), replace:
    pMob->affected_by	=	0;
// with
    STR_ZERO_STR( pMob->affected_by, AFF_FLAGS );



>>> OLC.H <<<
-------------

// Add these under the /* Utils. */ section of function declarations:
char *	str_flag_string		args( ( const struct flag_type *flag_table,
												FLAG *bits ) );
int 	str_flag_value	args ( ( const struct flag_type *flag_table,
												char *argument) );



>>> OLC_ACT.C <<<
-----------------

// In medit_show(), replace:
    sprintf( buf, "Affected by: [%s]\n\r",
	flag_string( affect_flags, pMob->affected_by ) );
// with:
    sprintf( buf, "Affected by: [%s]\n\r",
		str_flag_string( affect_flags, pMob->affected_by ) );

// If you have medit_copy(), you need to replace:
	pMob->affected_by	= mob2->affected_by;
// with
	STR_COPY_STR( pMob->affected_by, mob2->affected_by, AFF_FLAGS );

// If you are using OLC 2.0, under ed_toggle_flag() add this function:
// And don't forget to add the declaration in olc.h.
/*
 * Used to toggle flags in the new bit system.
 * This can set multiple flags at once. IE 'aff invis detect_invis flying'
 *   - Kirk Johnson (ammaross@ardenmore.com)
 */
ED_FUN_DEC(ed_str_flag_toggle)
{
	int value;
	char arg1[MIL];

	if ( !emptystring(argument) )
	{
	do
	{
		argument = one_argument( argument, arg1 );

	    if ( !IS_NULLSTR(arg1) )
	    {
			if ( ( value = str_flag_value( (struct flag_type *) par,
				arg1 ) ) != NO_FLAG )
			{
		    	STR_TOGGLE_BIT((FLAG *) arg, ((struct flag_type *) par)[value].bit );

		    	printf_to_char( ch, "%c%s flag %s %s.\n\r",
		    		toupper(n_fun[0]),
		    		&n_fun[1],
		    		(( struct flag_type * ) par)[value].name,
		    		STR_IS_SET( (FLAG *) arg, ((struct flag_type *) par)[value].bit )
		    			? "set" : "removed" );
		 	}
		 	else
		 	{
		 		printf_to_char( ch, "%s is not a flag.\n\r", arg1 );
		 	}
		}
	} while ( !IS_NULLSTR(arg1) );
	return TRUE;
	}

    printf_to_char( ch, "Syntax: %s [flag]\n\r", n_fun );
    return FALSE;
}

// Again, if you have OLC 2.0, in ed_race(), replace the affected_by assignment with:
STR_OR_STR( pMob->affected_by, race_table[race].aff, AFF_FLAGS );

// For OLC's that predate 2.0, you will need to modify medit_affect(). replace:
        if ((value = flag_value (affect_flags, argument)) != NO_FLAG)
        {
            pMob->affected_by ^= value;
// with:
        if ((value = str_flag_value (affect_flags, argument)) != NO_FLAG)
        {
            STR_TOGGLE_BIT(pMob->affected_by, value);

// OLC's that predate 2.0, in medit_race(), replace:
	pMob->affected_by |= race_table[race].aff;
// with:
	STR_OR_STR(pMob->affected_by, race_table[race].aff, AFF_FLAGS);



>>> OLC_SAVE.C <<<
------------------

// Just under the DIF macro, add this:
/* Used with the unlimited bit system */
void STR_DIF( const FLAG *var1, const FLAG *var2, FLAG *buf, int size )
{
	int i;

	for( i = 0; i < (size); i++ )
	{
		buf[i] = (~( ~(var1[i]) | (var2[i]) ));
	}

	return;
}


// In save_mobile(), add this to the list of variables:
FLAG temp2[MAX_FLAGS];

// Just a little further down the function, replace:
	fprintf( fp, "%s ",		fwrite_flag( pMobIndex->affected_by,	buf ) );
// (or whatever yours has), with:
    STR_DIF( pMobIndex->affected_by, race_table[race].aff, temp2, AFF_FLAGS );
    fprintf( fp, "%s ", str_fwrite_flag( temp2,	AFF_FLAGS, buf ) );

// A little further down the function, replace:
    if ((temp = DIF(race_table[race].aff,pMobIndex->affected_by)))
     	fprintf( fp, "F aff %s\n", fwrite_flag(temp, buf) );
// with:
	STR_DIF(race_table[race].aff,pMobIndex->affected_by,temp2,AFF_FLAGS);
    if (!STR_IS_ZERO(temp2,AFF_FLAGS))
     	fprintf( fp, "F aff %s\n", str_fwrite_flag( temp2, AFF_FLAGS, buf ) );

// In save_object(), (very near the end of the function), replace:
            fprintf (fp, "%d %d %s\n", pAf->location, pAf->modifier,
                     fwrite_flag (pAf->bitvector, buf));
// with:
	fprintf( fp, "%d %d %d\n", pAf->location, pAf->modifier, pAf->bitvector );



>>> TABLES.C <<<
----------------

// The affect_flags table needs to be modified to how it should be originally.
// Start from the top, and replace the A, B, C, etc with the AFF_*** that it
// should be. IE, the first on is "blind", change the A to AFF_BLIND. Continue
// though the whole list. (visual) {"blind", A, TRUE}, to {"blind", AFF_BLIND, TRUE},



>>> TABLESAVE.C (OLC 2.0 specific file) <<<
-------------------------------------------

// Time to remake a few things. Hehe. I hope you are comfortable with how
// this file works... :P

// In the define CAMPO_*** stuff, place this at the end (modifying the values
// if needed):
#define CAMPO_STR_FLAGVECTOR	13
#define CAMPO_CONV_FLAGVECTOR	14

#define T_AFF	1

// Yes, the straggling T_AFF needs to be added also.

// In the racesavetable, replace the aff line with
#ifdef BIT_COMPILE
	{ "aff", CAMPO_CONV_FLAGVECTOR, (void *) &race.aff, (void*)T_AFF, (void*)AFF_FLAGS },
#else
	{ "aff", CAMPO_STR_FLAGVECTOR, (void *) &race.aff, (void*)AFF_FLAGS, NULL },
#endif

// While we are on the subject, if you are trying to convert your ACT flags also,
// this is what you would replace the act line with:
// Note: do not add this if you are not converting act flags over also.
#ifdef BIT_COMPILE
	{ "act", CAMPO_CONV_FLAGVECTOR, (void *) &race.act, (void*)T_ACT, (void*)ACT_FLAGS },
#else
	{ "act", CAMPO_STR_FLAGVECTOR, (void *) &race.act, (void*)ACT_FLAGS, NULL },
#endif

// Now, in load_struct(), add this to the list of variables:
	FLAG * pstrflag;

// At the end of the big switch statement in load_struct(), add these
// (do note that I have partly translated it into English, IE
// typebase is tipobase in original OLC):
					case CAMPO_STR_FLAGVECTOR:
					pstrflag = (FLAG *) ((int) temp->puntero_campo - 
						(int) typebase + (int) puntero);
					STR_COPY_STR( pstrflag, str_fread_flag( fp,
						(int)temp->argument ), (int)temp->argument );
					found = TRUE, cnt++;
					break;

					case CAMPO_CONV_FLAGVECTOR:
					pstrflag = (FLAG *) ((int) temp->puntero_campo -
						(int) typebase + (int) puntero);
					/* switch statement in case you wanted to add more flag types. */
					switch ( (int)temp->argument )
					{
						case T_AFF:
						STR_COPY_STR( pstrflag,
							aff_convert_fread_flag( fread_flag(fp) ), ACT_FLAGS );
						break;
					}
					found = TRUE, cnt++;
					break;

// In save_struct(), add this to the list of variables:
	FLAG * pstrflag;

// At the end of the big switch statement in save_struct(), add these
// (again, note that I have partly translated it into English):
			case CAMPO_STR_FLAGVECTOR:
			pstrflag = (FLAG *) ((int) temp->puntero_campo -
				(int) typebase + (int) puntero);
			fprintf( fp, "%s %s\n", temp->campo,
				str_print_flags(pstrflag,(int)temp->argument) );
			break;

			case CAMPO_CONV_FLAGVECTOR:
			pstrflag = (FLAG *) ((int) temp->puntero_campo -
				(int) typebase + (int) puntero);
			fprintf( fp, "%s %s\n", temp->campo,
				str_print_flags(pstrflag,(int)temp->argument2) );
			break;



>>> SAVE.C <<<
--------------

// In fwrite_char(), replace:
	fprintf( fp, "Vers %d\n",   5			);
// with:
	fprintf( fp, "Vers %d\n",   6			);

// Also in fwrite_char(), replace:
    if (ch->affected_by != 0)
	fprintf( fp, "AfBy %s\n",   print_flags(ch->affected_by));
// with:
    if ( !STR_IS_ZERO(ch->affected_by, AFF_FLAGS) )
	fprintf( fp, "AfBy %s\n",   str_print_flags(ch->affected_by, AFF_FLAGS));

// In fwrite_pet(), replace:
    if (pet->affected_by != pet->pIndexData->affected_by)
    	fprintf(fp, "AfBy %s\n", print_flags(pet->affected_by));
// with:
    if ( !STR_SAME_STR(pet->affected_by, pet->pIndexData->affected_by, AFF_FLAGS) )
    	fprintf(fp, "AfBy %s\n", str_print_flags(pet->affected_by, AFF_FLAGS));

// In load_char_obj(), replace:
	ch->affected_by = ch->affected_by|race_table[ch->race].aff;
// with:
	STR_OR_STR( ch->affected_by, race_table[ch->race].aff, AFF_FLAGS );

// Just after the KEY macro, put this:
#if defined(KEYF)
#undef KEYF
#endif

#define KEYF( literal, field, value, size ) if ( !str_cmp( word, literal ) ) \
		{ STR_COPY_STR( field, value, size ); fMatch = TRUE; break; }


// In fread_char(), under 'case 'A':' in the switch, replace:
	    KEY( "AffectedBy",	ch->affected_by,	fread_flag( fp ) );
	    KEY( "AfBy",	ch->affected_by,	fread_flag( fp ) );
// with:
		if ( ch->version < 6 )
		{
	    	KEYF( "AffectedBy", ch->affected_by, aff_convert_fread_flag(
	    							fread_flag( fp ) ), AFF_FLAGS );
	    	KEYF( "AfBy", ch->affected_by, aff_convert_fread_flag(
	    							fread_flag( fp ) ), AFF_FLAGS );
	    // Add this only if you have aff2 snippet of some sort in.
			if ( !str_cmp( word, "Af2By" ) )
			{
				STR_OR_STR( ch->affected_by,
					aff2_convert_fread_flag( fread_flag( fp ) ), AFF_FLAGS );
				fMatch = TRUE;
				break;
			}
		// endif
	    }
	    else
	    {
	    	KEYF( "AfBy", ch->affected_by, str_fread_flag( fp, AFF_FLAGS ), AFF_FLAGS );
	    }
// If you have tampered with your player save file version numbers already,
// then modify the if statements (and saving player version number) accordingly.

// In fread_pet(), under the 'case 'A':' in the switch, replace:
    	    KEY( "AfBy",	pet->affected_by,	fread_flag(fp));
// with:
    		if ( ch->version < 6 )
    		{
    	    	KEYF( "AfBy", pet->affected_by, aff_convert_fread_flag(
    	    							fread_flag( fp ) ), AFF_FLAGS );
    	    // Add this only if you have aff2 snippet of some sort in.
    	    	KEYF( "Af2By", pet->affected_by, aff2_convert_fread_flag(
    	    							fread_flag( fp ) ), AFF_FLAGS );
    	    // endif
    	    }
    	    else
    	    {
    	    	KEYF( "AfBy", pet->affected_by, str_fread_flag(fp,AFF_FLAGS), AFF_FLAGS );
    	    }



>>> SCREEN.C (OLC 2.0 specific file) <<<
----------------------------------------

// In the medit_olc_show_table table, replace:
	{
		"aff", &xMob.affected_by, "Aff :", OLCS_FLAGSTR_INT,
		1, 10, 74, 1, 1, affect_flags
	},
// with:
	{
		"aff", &xMob.affected_by, "Aff :", OLCS_FLAGSTR_STR,
		1, 7, 74, 1, 1, affect_flags
	},

// In UpdateOLCScreen(), near the end of the switch statement, just below
// the 'case OLCS_FLAGSTR_SHINT:' block, add this:
			case OLCS_FLAGSTR_STR:
			flagt = (const struct flag_type *) table[i].func;
			strcpy(buf, str_flag_string( flagt, (FLAG *) point ) );
			break;



>>> SCREEN.H (OLC 2.0 specific file) <<<
----------------------------------------

// Add the following to the OLCS_*** list:
#define OLCS_FLAGSTR_STR	9



>>> BITSYS.C <<<
----------------

// You should have added this file to your src directory (and your makefile)
// by now. If not, do it now. Ok. If you are not converting your affects, you
// will have to make a few changes to this file. In do_flag(), you will have
// to make :
	 	else if (!str_prefix(arg3,"aff"))
		{
			size = AFF_FLAGS;
		    flag = victim->affected_by;
		    flag_table = affect_flags;
		}
// look like:
	  	else if (!str_prefix(arg3,"aff"))
		{
			do_flag_norm( ch, victim, argument, type,
							victim->affected_by, affect_flags );
			return;
		}
// You won't have to worry about the rest of the file, it is just support
// functions.

// Now, if you have aff2 flags, you will have to read the comment in
// affect_str_bit_name(), and look at the commented out functions below
// aff_bit_convert_fread_flag().

// If you are converting more than just AFF flags, then you will want to read
// the commented functions below aff_bit_convert_fread_flag() also. You will
// have to duplicate affect_str_bit_name() and modify it for the flag type you
// will be using also, not to mention change all references to the old function
// to your new one. (similarly to how I did with affect_str_bit_name()).

------------------------------------------------------------------------------

Now that we have the initial stuff in place, how about we go back through and
replace all the SET_BIT, IS_SET, etc with the new stuff?
If you do not have access to the grep command, you will have to open each file
individually to do this. Those with grep, search for 'IS_SET', 'REMOVE_BIT',
'SET_BIT', and 'TOGGLE_BIT' that have affected_by or aff in them. You will have
to change each one either 'STR_IS_SET', 'STR_REMOVE_BIT', 'STR_SET_BIT', or
'STR_TOGGLE_BIT'.

raedit.c will need this line in raedit_show() to replace the current one:
sprintf( buf, "Aff         : [%s]\n\r", str_flag_string( affect_flags, pRace->aff) );
not to mention several other small places. This is where reviewing the tools
I have provided and figuring what needs to be where comes in. ;)

There is some good news I can give you. If a spot was missed somewhere, you
will have a nasty buffer overflow, but it will be fairly easy to track down.
Also, you will not be able to successfully compile the code if you missed an
IS_SET or the like, so you will know just where to go to fix it. If you do run
into errors, make sure that the data has been read properly. That should take
care of a lot of potential problems.

Compiling instructions:
- Make a backup of your areas and data files.
- Compile with -DBIT_COMPILE in your command line (maybe add it to CC flags if
  you use a makefile).
- Run the mud, preferably in GDB in case something goes downhill.
- If you get the message to recompile without -DBIT_COMPILE, you are safe.
- Recompile without -DBIT_COMPILE.
- Run the mud and test out a few of your functions such as medit_show,
  any type of flag setting function such as affect setting in medit, try
  the 'flag' command and set yourself invis and back to normal. Make sure
  you medit_show a few mobs that had affects on them BEFORE you did the
  conversion, to make sure it was done correctly. If you ran across any crashes,
  use GDB to work through them. The real stumpers, you can post to me or the
  ROM mailing list. (posting to the list will get to me also, since I
  subscribe to it).

Well, that should cover it. If you lost any sleep because of this, just know that
you are one among many, me being the first. ;)

Kirk Johnson
aka Ammaross Danan
Implementor of ArdenmoreDOI
http://www.ardenmore.com
telnet://mud.ardenmore.com:5150
