dawn/notes/
dawn/src/
dawn/src/docs/
/**************************************************************************/
// bit.cpp - see below
/***************************************************************************
 * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt                    *
 * >> A number of people have contributed to the Dawn codebase, with the   *
 *    majority of code written by Michael Garratt - www.dawnoftime.org     *
 * >> To use this source code, you must fully comply with the dawn license *
 *    in licenses.txt... In particular, you may not remove this copyright  *
 *    notice.                                                              *
 **************************************************************************/
/***************************************************************************
 *  File: bit.cpp                                                          *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was written by Jason Dinkel and inspired by Russ Taylor,     *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/

#include "include.h" // dawn standard includes

#define STNM(flag) flag, #flag

struct flag_stat_type
{
    const struct flag_type *structure;
	const char *name;
    bool stat;
};

/*****************************************************************************
 Name:		flag_stat_table
 Purpose:	This table catagorizes the tables following the lookup
 		functions below into stats and flags.  Flags can be toggled
 		but stats can only be assigned.  Update this table when a
 		new set of flags is installed.
 ****************************************************************************/
const struct flag_stat_type flag_stat_table[] =
{
//	{	structure, text version				type	}, 
    {   STNM(ac_types),						true    },
    {   STNM(apply_types),					true    },
	{   STNM(area_import_format_types),		true    },
    {   STNM(ban_types),					true    },
    {   STNM(buildrestrict_types),			true    },  
    {   STNM(castnames_types),				true    },
    {   STNM(category_types),				true    },
    {   STNM(colourmode_types),				true    },  
    {   STNM(com_category_types),			true    },
    {   STNM(commandlog_types),				true    },
    {   STNM(damtype_types),				true    },
    {   STNM(direction_types),				true    },
    {   STNM(help_category_types),			true    },
    {   STNM(immhelp_types),				true    },
    {   STNM(item_types),					true    },
    {   STNM(mixtype_types),				true    },
    {   STNM(position_types),				true    },
    {   STNM(preference_types),				true    },
    {   STNM(sector_types),					true    },
    {   STNM(sex_types),					true    },
    {   STNM(size_types),					true    },
    {   STNM(sktype_types),					true    }, // different types of entries in the skill_table
    {   STNM(target_types),					true    },
    {   STNM(textsearch_types),				true    },
	{   STNM(to_types),						true    },    
    {   STNM(weapon_class_types),			true    },
    {   STNM(wear_location_types),			true    },
    {   STNM(wear_location_strings_types),	true    },
	{   STNM(laston_wizlist_types),			true    },
	// NOTE: ALL TRUE TABLES MUST BE ABOVE HERE

    {   STNM(act_flags),					false   },
    {   STNM(act2_flags),					false   },
    {   STNM(affect_flags),					false   },
    {   STNM(affect2_flags),				false   },
    {   STNM(align_flags),					false   },
    {   STNM(attune_flags),					false   },
    {   STNM(classnames_flags),				false   },  
    {   STNM(commandflag_flags),			false   },
    {   STNM(container_flags),				false   },
    {   STNM(council_flags),				false   },
    {   STNM(dedit_flags),					false   },
    {   STNM(exit_flags),					false   },
    {   STNM(grantgroup_flags),				false   },
	{   STNM(language_flags),				false	},
    {   STNM(objextra_flags),				false   },
    {   STNM(objextra2_flags),				false   },
    {   STNM(form_flags),					false   },
    {   STNM(imm_flags),					false   },
    {   STNM(off_flags),					false   },
    {   STNM(olc_flags),					false   },
    {   STNM(part_flags),					false   },
	{   STNM(res_flags	),          		false   },
    {   STNM(room_flags	),					false   },
	{   STNM(room2_flags),					false   },
    {   STNM(tendency_flags),				false   },
    {   STNM(vuln_flags),					false   },
    {   STNM(weapon_flags),					false   },
    {   STNM(wear_flags),					false   },
	{	0,"",			0	}
};
    


/*****************************************************************************
 Name:		is_stat( table )
 Purpose:	Returns true if the table is a stat table and false if flag.
 Called by:	flag_value and flag_string.
 Note:		This function is local and used only in bit.c.
 ****************************************************************************/
bool is_stat( const struct flag_type *flag_table )
{
	int flag;

	for (flag = 0; flag_stat_table[flag].structure && flag_stat_table[flag].stat; flag++)
	{
		if ( flag_stat_table[flag].structure == flag_table
			&& flag_stat_table[flag].stat )
			return true;
	}
	return false;
}

/**************************************************************************/
// Kal - Aug 01
const char *get_flag_table_name( const struct flag_type *flag_table )
{
	int flag;

	for (flag = 0; flag_stat_table[flag].structure; flag++)
	{
		if (flag_stat_table[flag].structure == flag_table){
			return flag_stat_table[flag].name;
		}
	}
	return "unknown";
}
/**************************************************************************/

/*
 * This function is Russ Taylor's creation.  Thanks Russ!
 * All code copyright (C) Russ Taylor, permission to use and/or distribute
 * has NOT been granted.  Use only in this OLC package has been granted.
 */
/*****************************************************************************
 Name:      flag_lookup( flag, table )
 Purpose:	Returns the value of a single, settable flag from the table.
 Called by:	flag_value and flag_string.
 Note:		This function is local and used only in bit.c.
 ****************************************************************************/
int flag_lookup (const char *name, const struct flag_type *flag_table)
{
    int flag;
 
    // first try an exact match, then do a substring match

	// exact
	for (flag = 0; flag_table[flag].name != NULL; flag++)
    {
        if ( !str_cmp( name, flag_table[flag].name )
          && flag_table[flag].settable )
            return flag_table[flag].bit;
    }

	// substring
	for (flag = 0; flag_table[flag].name != NULL; flag++)
    {
        if ( !str_prefix( name, flag_table[flag].name )
          && flag_table[flag].settable )
            return flag_table[flag].bit;
    }
    return NO_FLAG;
}

/*****************************************************************************
 Name:		flag_value( table, flag )
 Purpose:	Returns the value of the flags entered.  Multi-flags accepted.
 Called by:	olc.c and olc_act.c.

// use wordflag_to_value( const struct flag_type *flag_table, const char *wordtext)
// to convert a text into a value ignoring if the wordtext is settable.
 ****************************************************************************/
int flag_value( const struct flag_type *flag_table, char *argument)
{
    char word[MIL];
    int  bit;
    int  marked = 0;
    bool found = false;

	if(IS_NULLSTR(argument)){
		return NO_FLAG;
	}

    if ( is_stat( flag_table ) )
    {
		one_argument( argument, word );

		if ( ( bit = flag_lookup( word, flag_table ) ) != NO_FLAG ){
			return bit;
		}else{
			return NO_FLAG;
		}
    }

    // Accept multiple flags.
    for (; ;)
    {
        argument = one_argument( argument, word );

        if ( word[0] == '\0' )
	    break;

        if ( ( bit = flag_lookup( word, flag_table ) ) != NO_FLAG )
        {
            SET_BIT( marked, bit );
            found = true;
        }
    }

    if ( found ){
		return marked;
    }else{
		return NO_FLAG;
	}
}



/*****************************************************************************
 Name:		flag_string( table, flags/stat )
 Purpose:	Returns string with name(s) of the flags or stat entered.
 Called by:	act_olc.c, olc.c, and olc_save.c.
 ****************************************************************************/
char *flag_string( const struct flag_type *flag_table, int bits )
{
	static int i;
    static char buf[5][MSL];
	char tbuf[MIL];
    int flag;
	bool bit_found=false;

	// rotate buffers
	++i%=5;

    buf[i][0] = '\0';

	// 2 different modes... if their is a stat table to be written 
	// a different mode is used from checking each bit is written
	if (is_stat( flag_table )){
	    for (flag = 0; flag_table[flag].name && !bit_found; flag++)
	    {
			if ( flag_table[flag].bit == bits ){
				strcat( buf[i], " " );
				strcat( buf[i], flag_table[flag].name );
				bit_found=true;
			}
		}
		// report that we have a missing value in a table
		if(!bit_found && bits!=-1)
		{
			sprintf(tbuf," `#`RVALUE%dMISSING!!!`&",bits);
			strcat( buf[i], tbuf);
		}
	}else{
		// write bits the long way so we can record if a bit isn't written due 
		// to no matching bit in the flag table.
		// Also write only one bit word for a single bit allowing multiple 
		// words for a bit value in a table (colour vs color) and single words in 
		// stored files.
		for (int bit_index=0; bit_index<32; bit_index++)
		{
			bit_found=false;
			int bit_value = 1<<bit_index;

			if (!IS_SET(bit_value, bits))
				continue;

			for (flag = 0; flag_table[flag].name && !bit_found; flag++)
			{
				if ( IS_SET(bit_value, flag_table[flag].bit) )
				{
					strcat( buf[i], " ");
					strcat( buf[i], flag_table[flag].name );
					bit_found= true;
				}
			}
			// report that we have a missing bit in a table
			if(!bit_found && bits!=-1)
			{
				sprintf(tbuf," `#`RBIT#%d(%c)MISSING!!!`&",
					bit_index,(bit_index <= 'Z' - 'A'?'A' + bit_index :
						'a' + bit_index - ( 'Z' - 'A' + 1 )));
				strcat( buf[i], tbuf);
			}
		}
	} // non stat table (multiple bit table)

	// return the result
    return (buf[i][0] != '\0') ? buf[i]+1 : (char*)"none";
}
/*****************************************************************************
 Name:      flagging_info( table, flags/stat )
 Purpose:   tells a char what flags they just toggled
 Called by: olc.c
 ****************************************************************************/
/**************************************************************************/
// perform only exact case insensitive matching
// returns a pointer to the table entry or NULL if unfound
// Kal - Feb 99
classgroup_type * classgroup_lookup(const char* name)
{
	int index;
	for(index=0; !IS_NULLSTR(classgroup_table[index].name);index++){
		if(!str_cmp(classgroup_table[index].name, name)){
			return &classgroup_table[index];
		}
	}
	return NULL;
}
/**************************************************************************/
affectprofile_type * affectprofile_lookup(const char *name)
{
	int index;
	for(index=0; !IS_NULLSTR(affectprofile_table[index].name);index++){
		if(!str_cmp(affectprofile_table[index].name, name)){
			return &affectprofile_table[index];
		}
	}
	return NULL;
}
/**************************************************************************/
// encode the bits into A->Z a->e form
char *flags_print(int flag)
{
	int count, pos = 0;
	static char buf[52];

	for (count = 0; count < 32;  count++)
	{
		if (IS_SET(flag,1<<count))
		{
			if (count < 26)
				buf[pos] = 'A' + count;
			else
				buf[pos] = 'a' + (count - 26);
			pos++;
		}
	}

	if (pos == 0)
	{
		buf[pos] = '0';
		pos++;
	}
	
	buf[pos] = '\0';
	return buf;
}
/**************************************************************************/
// convert bits from the form A->Z a->e into a number value
int flags_read(char *flagtext)
{
	int number;
	char c;
	char *p=flagtext;
	bool negative = false;
    
	do{
		c=*p++;
	}
	while ( is_space(c));
    
	if (c == '-')
	{
		negative = true;
		c = *p++;
	}

	number = 0;
    
	if (!is_digit(c))
	{
		while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
		{
			number += flag_convert(c);
			c = *p++;
		}
	}else{
		while (is_digit(c))
		{
			number = number * 10 + c - '0';
			c = *p++;
		}
	}

	if(negative){
		number*=-1;
	}
	return number;
}

/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/