/***********************************************************************
 *                                                                     *
 *  This was originally the stock do_areas command, but I modified it  *
 *  greatly to suit the needs of a growing areas list.  Originally we  *
 *  just had the credits scroll like normal, using the 'credits' value *
 *  in the area file to credit the builders, but as the areas list got *
 *  bigger, it began to spam people out.  The primary function of this *
 *  command is to add in page breaks [hit return to continue] into the *
 *  list to prevent people from spamming out.  The secondary purpose   *
 *  is to allow players to search through the areas list, returning a  *
 *  list of areas that match the criteria.  In order to use this code, *
 *  you must abide by all of the license terms set forth by the Diku,  *
 *  Merc, and Rom authors.  No need to credit me for this, although a  *
 *  mention in a snippets helpfile or the do_areas helpfile would be   *
 *  appreciated.  This was originally done by Joseph, aka Diablos, of  *
 *  End of Time at eotmud.com:4000.  I would also ask that any of the  *
 *  comments in the code below remain intact.                          *
 *  As written below, it will display the area credits like:           *
 *                                                                     *

GAME [ LEVEL ]  AREA NAME                         BUILDER(S)          FINISHED?!
--------------------------------------------------------------------------------
-CT- [001-015]  End of Time                       Diablos             FINISHED!!
MISC [001-015]  Newbie Zones                      Guion/Ssolvarain    
SoM2 [001-015]  Castle City Jad                   Diablos             FINISHED!!

 *                                                                     *
 *  The criteria it allows the areas to be searched by are the Area's  *
 *  Game, Level, Author(s), and whether it is finished or not.  The    *
 *  syntax to just see the entire list is simply 'areas' but to search *
 *  the list it is:                                                    *
 *  areas [game|range|author|finished] <game|range|author|(yes/no)>    *
 *  So if you wanted to see all of the areas authored by Diablos, you  *
 *  would type 'areas author Diablos'.                                 *
 *                                                                     *
 ***********************************************************************/



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

//In merc.h, find the area_data struct as below and make sure you have all of
//the following:

/*
 * Area definition.
 */
struct	area_data
{
    AREA_DATA *		next;
    RESET_DATA *	reset_first;
    RESET_DATA *	reset_last;
    HELP_AREA *		helps;
    char *		file_name;
    char *		name;
    char *		credits;
    sh_int		age;
    sh_int		nplayer;
    sh_int		low_range;	/* Diablos - For new Areas Command */
    sh_int		high_range;	/* Diablos - For new Areas Command */
    long 		min_vnum;
    long		max_vnum;
    bool		empty;
    char *		builders;	/* OLC */ /* Listing of */
    int			vnum;		/* OLC */ /* Area vnum  */
    int			area_flags;	/* OLC */
    int			security;	/* OLC */ /* Value 1-9  */
    char *        	game;		/* Diablos - For new Areas Command */
    char *        	authors;	/* Diablos - For new Areas Command */
};


//-low_range is for the minimum suggested character level
//-high_range is for the maximum suggested character level
//-game is for listing which Final Fantasy game our areas at End of Time were based off of,
// so feel free to change this to something else or remove it from this and subsequent blocks
// of code
//-authors is different from builders.  Builders is for which immortals have access to the
// area.  Authors is for displaying in the credits which builders worked on it.  We remove
// builder access after the area is finished, so a different value for authors was necessary
// to retain long-term credit.

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

//In olc_act.c find the aedit_show function and be sure that it displays the necessary values:


/*
 * Area Editor Functions.
 */
AEDIT( aedit_show )
{
    AREA_DATA *pArea;
    char buf  [MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    sprintf( buf, "Name:     [%5d] %s\n\r", pArea->vnum, pArea->name );
    send_to_char( buf, ch );

#if 0  /* ROM OLC */
    sprintf( buf, "Recall:   [%5d] %s\n\r", pArea->recall,
	get_room_index( pArea->recall )
	? get_room_index( pArea->recall )->name : "none" );
    send_to_char( buf, ch );
#endif /* ROM */

    sprintf( buf, "File:     %s\n\r", pArea->file_name );
    send_to_char( buf, ch );

    sprintf( buf, "Vnums:    [%ld-%ld]\n\r", pArea->min_vnum, pArea->max_vnum );
    send_to_char( buf, ch );

    sprintf( buf, "Range:    [%d-%d]\n\r", pArea->low_range, pArea->high_range );
    send_to_char( buf, ch );

    sprintf( buf, "Game:     [%s]\n\r", pArea->game );
    send_to_char( buf, ch );

    sprintf( buf, "Security: [%d]\n\r", pArea->security );
    send_to_char( buf, ch );

    sprintf( buf, "Builders: [%s]\n\r", pArea->builders );
    send_to_char( buf, ch );

    sprintf( buf, "Authors:  [%s]\n\r", pArea->authors );
    send_to_char( buf, ch );

    sprintf( buf, "Finished?:[%s]\n\r", pArea->credits );
    send_to_char( buf, ch );

    sprintf( buf, "Age:      [%d]\n\r",	pArea->age );
    send_to_char( buf, ch );

    sprintf( buf, "Players:  [%d]\n\r", pArea->nplayer );
    send_to_char( buf, ch );

    sprintf( buf, "Flags:    [%s]\n\r", flag_string( area_flags, pArea->area_flags ) );
    send_to_char( buf, ch );

    return FALSE;
}


//the following are all of the NEW necessary commands to edit these values:


//We set a display value on whether an area is finished or not, so this was converted to this purpose.

AEDIT( aedit_credits )
{
    AREA_DATA *pArea;
    char arg[MIL];

    EDIT_AREA(ch, pArea);

    argument = one_argument (argument, arg);

    if ( arg[0] == '\0' )
    {
	send_to_char( "Syntax:   finished <yes/no/null>\n\r", ch );
	return FALSE;
    }

    if (!str_prefix (arg, "yes"))
    {
      free_string( pArea->credits );
      pArea->credits = str_dup( "FINISHED!!" );
    }
    else if (!str_prefix (arg, "no"))
    {
      free_string( pArea->credits );
      pArea->credits = str_dup( "" );
    }
    else if (!str_prefix (arg, "null"))
    {
      free_string( pArea->credits );
      pArea->credits = str_dup( "(null)" );
    }
    else
    {
	send_to_char( "Syntax:   finished <yes/no/null>\n\r", ch );
	return FALSE;
    }

    send_to_char( "Finished status set.\n\r", ch );
    return TRUE;
}


AEDIT( aedit_authors )
{
    AREA_DATA *pArea;
    int length;

    EDIT_AREA(ch, pArea);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:   authors [$authors]\n\r", ch );
	return FALSE;
    }

    length = strlen( argument );
    if ( length > 19 )
    {
	send_to_char( "No more than 19 characters allowed.\n\r", ch );
	return FALSE;
    }

    free_string( pArea->authors );
    pArea->authors = str_dup( argument );

    send_to_char( "Authors set.\n\r", ch );
    return TRUE;
}


AEDIT( aedit_game )
{
    AREA_DATA *pArea;
    int length;

    EDIT_AREA(ch, pArea);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:   game [$game]\n\rie: 'game FF07'\n\r", ch );
	return FALSE;
    }

    length = strlen( argument );
    if ( length > 4 )
    {
	send_to_char( "No more than four characters allowed.\n\r", ch );
	return FALSE;
    }

    free_string( pArea->game );
    pArea->game = str_dup( argument );

    send_to_char( "Game set.\n\r", ch );
    return TRUE;
}


//The following range commands aren't as put together as nice as the vnum command, and thus where the
// vnum syntax is 'vnum <low> <high>', the range commands are 'lrange <number>' and 'hrange <number>'
// Of course, feel free to change it up as the aedit_vnum command is, I just didn't feel like it was
// necessary.

AEDIT( aedit_hrange )
{
    AREA_DATA *pArea;
    char hrange[MAX_STRING_LENGTH];
    int  value, length;

    EDIT_AREA(ch, pArea);

    one_argument( argument, hrange );

    if ( !is_number( hrange ) || hrange[0] == '\0' )
    {
	send_to_char( "Syntax:  hrange [#xlevel]\n\r", ch );
	return FALSE;
    }

    length = strlen( argument );
    if ( length > 3 )
    {
	send_to_char( "No more than three numbers allowed.", ch );
	return FALSE;
    }

    value = atoi( hrange );

    pArea->high_range = value;

    send_to_char( "Higher Level Range set.\n\r", ch );
    return TRUE;
}


AEDIT( aedit_lrange )
{
    AREA_DATA *pArea;
    char lrange[MAX_STRING_LENGTH];
    int  value, length;

    EDIT_AREA(ch, pArea);

    one_argument( argument, lrange );

    if ( !is_number( lrange ) || lrange[0] == '\0' )
    {
	send_to_char( "Syntax:  lrange [#xlevel]\n\r", ch );
	return FALSE;
    }

    length = strlen( argument );
    if ( length > 3 )
    {
	send_to_char( "No more than three numbers allowed.", ch );
	return FALSE;
    }

    value = atoi( lrange );

    pArea->low_range = value;

    send_to_char( "Lower Level Range set.\n\r", ch );
    return TRUE;
}


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

//Go into olc_save.c and find the 'void save_area( AREA_DATA *pArea )' function.
//Near the top, be sure you have all of the new values being saved here.  Here is
//my entire block of that code:

    fprintf( fp, "#AREADATA\n" );
    fprintf( fp, "Name %s~\n",        pArea->name );
    fprintf( fp, "Builders %s~\n",    fix_string( pArea->builders ) );
    fprintf( fp, "VNUMs %ld %ld\n",   pArea->min_vnum, pArea->max_vnum );
    fprintf( fp, "Credits %s~\n", 	  pArea->credits );
    fprintf( fp, "Security %d\n",     pArea->security );
    fprintf( fp, "Authors %s~\n",     fix_string( pArea->authors ) );
    fprintf( fp, "Game %s~\n",    	  fix_string( pArea->game ) );
    fprintf( fp, "Levels %d %d\n",    pArea->low_range, pArea->high_range );
    fprintf( fp, "End\n\n\n\n" );


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

//Before you do the following, I believe you need to compile and reboot, then when
//your MUD comes back up, do an asave_world or otherwise force all of the areas to
//save with the new values as listed above.  Then, add the following and copyover,
//allowing the following values to load into the game.  I make no claim that is
//definitely the way to do it, but I did this code a while back and cannot 100%
//remember :p

//Go into db.c and find the 'void load_area( FILE *fp )' function.  Be sure to add
//in the same values as listed above in olc_save.c.  Here is my block of code there:

    pArea		= alloc_perm( sizeof(*pArea) );
    pArea->file_name	= fread_string(fp);

    pArea->area_flags   = AREA_LOADING;         /* OLC */
    pArea->security     = 9;                    /* OLC */ /* 9 -- Hugin */
    pArea->builders     = str_dup( "None" );    /* OLC */
    pArea->vnum         = top_area;             /* OLC */

    pArea->name		= fread_string( fp );
    pArea->credits	= fread_string( fp );
    pArea->min_vnum	= fread_lnumber(fp);
    pArea->max_vnum	= fread_lnumber(fp);
    pArea->age		= 15;
    pArea->nplayer	= 0;
    pArea->game		= fread_string( fp );
    pArea->authors	= fread_string( fp );
    pArea->low_range	= fread_lnumber(fp);
    pArea->high_range	= fread_lnumber(fp);



//Now go down to 'void new_load_area( FILE *fp )' and add these:

	   case 'A':
	    SKEY( "Authors", pArea->authors );
	   case 'G':
	    SKEY( "Game", pArea->game );
	   case 'L':
            if ( !str_cmp( word, "Levels" ) )
            {
                pArea->low_range = fread_lnumber( fp );
                pArea->high_range = fread_lnumber( fp );
            }


	   case 'A':
	    SKEY( "Authors", pArea->authors );
	   case 'G':
	    SKEY( "Game", pArea->game );
	   case 'L':
            if ( !str_cmp( word, "Levels" ) )
            {
                pArea->low_range = fread_lnumber( fp );
                pArea->high_range = fread_lnumber( fp );
            }



//No find your do_areas command be sure to add in the new values and functionality.
//This is my do_areas command:



void do_areas( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    AREA_DATA *pArea;
    int iArea, value, value2, count = 0;
    BUFFER *output;
    output = new_buf();
    char cmd[ MAX_INPUT_LENGTH ];

    argument = one_argument( argument, cmd );

    if (cmd[0] == '\0')
    {
      iArea = top_area;
      pArea    = area_first;

      for ( iArea = 0; pArea != NULL ; iArea++ )
      {
		if(pArea == NULL
			|| pArea->credits == '\0'
			|| !(strcmp(pArea->credits,"(null)"))) {
			;} else {

        if(pArea->low_range == 52 && pArea->high_range == 57)
        {
          sprintf( buf, "{D%s [{wPROMOTE{D]  {W%-33s {r%-19s {R%s{x\n\r",
           pArea->game, pArea->name, pArea->authors,
           (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
	    add_buf( output, buf );
        }
        else
        {
          sprintf( buf, "{D%s [{w%s%d-%s%d{D]  {W%-33s {r%-19s {R%s{x\n\r",
           pArea->game, 
           (pArea->low_range < 10) ? "00" : (pArea->low_range > 9 && pArea->low_range < 100) ? "0" : "",
           pArea->low_range,
           (pArea->high_range < 10) ? "00" : (pArea->high_range > 9 && pArea->high_range < 100) ? "0" : "",
           pArea->high_range, pArea->name, pArea->authors,
           (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
	    add_buf( output, buf );
        }
	}
	pArea = pArea->next;
      }
    }
    else if (!str_prefix (cmd, "range"))
    {
	char max[ MAX_INPUT_LENGTH ];
      argument = one_argument( argument, max );
	if (argument[0] =='\0' || max[0] =='\0')
	{
	  send_to_char ("Syntax: areas range <level1> <level2>\n\r", ch);
	  return;
	}

	if (!is_number (argument) || !is_number (max))
	{
	  send_to_char ("That's not a number!\n\r", ch);
	  return;
	}

	value  = atoi (argument);
	value2 = atoi (max);

      iArea = top_area;
      pArea    = area_first;

      for ( iArea = 0; pArea != NULL ; iArea++ )
      {
		if(pArea == NULL
			|| pArea->credits == '\0'
			|| !(strcmp(pArea->credits,"(null)"))) {
			;} else {

        if(value >= pArea->low_range && value2 <= pArea->high_range)
        {
          if(pArea->low_range == 52 && pArea->high_range == 57)
          {
            sprintf( buf, "{D%s [{wPROMOTE{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
          else
          {
            sprintf( buf, "{D%s [{w%s%d-%s%d{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, 
             (pArea->low_range < 10) ? "00" : (pArea->low_range > 9 && pArea->low_range < 100) ? "0" : "",
             pArea->low_range,
             (pArea->high_range < 10) ? "00" : (pArea->high_range > 9 && pArea->high_range < 100) ? "0" : "",
             pArea->high_range, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
        }
	}
	pArea = pArea->next;
      }
    }

    else if (!str_prefix (cmd, "game"))
    {
	if (argument[0] =='\0')
	{
	  send_to_char ("Syntax: areas game <game>\n\rie: 'areas game FF05'\n\r", ch);
	  return;
	}

      iArea = top_area;
      pArea    = area_first;

      for ( iArea = 0; pArea != NULL ; iArea++ )
      {
		if(pArea == NULL
			|| pArea->credits == '\0'
			|| !(strcmp(pArea->credits,"(null)"))) {
			;} else {
        if(mystristr( pArea->game, argument ) )
        {
          if(pArea->low_range == 52 && pArea->high_range == 57)
          {
            sprintf( buf, "{D%s [{wPROMOTE{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
          else
          {
            sprintf( buf, "{D%s [{w%s%d-%s%d{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, 
             (pArea->low_range < 10) ? "00" : (pArea->low_range > 9 && pArea->low_range < 100) ? "0" : "",
             pArea->low_range,
             (pArea->high_range < 10) ? "00" : (pArea->high_range > 9 && pArea->high_range < 100) ? "0" : "",
             pArea->high_range, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
        }
	}
	pArea = pArea->next;
      }
    }

    else if (!str_prefix (cmd, "author"))
    {
	if (argument[0] =='\0')
	{
	  send_to_char ("Syntax: areas author <author>\n\rie: 'areas author Diablos'\n\r", ch);
	  return;
	}

      iArea = top_area;
      pArea    = area_first;

      for ( iArea = 0; pArea != NULL ; iArea++ )
      {
		if(pArea == NULL
			|| pArea->credits == '\0'
			|| !(strcmp(pArea->credits,"(null)"))) {
			;} else {
        if(mystristr( pArea->authors, argument ) )
        {
          if(pArea->low_range == 52 && pArea->high_range == 57)
          {
            sprintf( buf, "{D%s [{wPROMOTE{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
             count++;
	      add_buf( output, buf );
          }
          else
          {
            sprintf( buf, "{D%s [{w%s%d-%s%d{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, 
             (pArea->low_range < 10) ? "00" : (pArea->low_range > 9 && pArea->low_range < 100) ? "0" : "",
             pArea->low_range,
             (pArea->high_range < 10) ? "00" : (pArea->high_range > 9 && pArea->high_range < 100) ? "0" : "",
             pArea->high_range, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
        }
	}
	pArea = pArea->next;
      }
    }

    else if (!str_prefix (cmd, "finished"))
    {
	if (argument[0] =='\0')
	{
	  send_to_char ("Syntax: areas finished <yes|no>\n\rie: 'areas finished yes'\n\r", ch);
	  return;
	}

      iArea = top_area;
      pArea    = area_first;

      for ( iArea = 0; pArea != NULL ; iArea++ )
      {
		if(pArea == NULL
			|| pArea->credits == '\0'
			|| !(strcmp(pArea->credits,"(null)"))) {
			;} else {
        if(!str_cmp(argument, "yes") && !str_cmp (pArea->credits, "FINISHED!!"))
        {
          if(pArea->low_range == 52 && pArea->high_range == 57)
          {
            sprintf( buf, "{D%s [{wPROMOTE{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
             count++;
	      add_buf( output, buf );
          }
          else
          {
            sprintf( buf, "{D%s [{w%s%d-%s%d{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, 
             (pArea->low_range < 10) ? "00" : (pArea->low_range > 9 && pArea->low_range < 100) ? "0" : "",
             pArea->low_range,
             (pArea->high_range < 10) ? "00" : (pArea->high_range > 9 && pArea->high_range < 100) ? "0" : "",
             pArea->high_range, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
        }
        else if(!str_cmp(argument, "no") && str_cmp (pArea->credits, "FINISHED!!") )
        {
          if(pArea->low_range == 52 && pArea->high_range == 57)
          {
            sprintf( buf, "{D%s [{wPROMOTE{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
             count++;
	      add_buf( output, buf );
          }
          else
          {
            sprintf( buf, "{D%s [{w%s%d-%s%d{D]  {W%-33s {r%-19s {R%s{x\n\r",
             pArea->game, 
             (pArea->low_range < 10) ? "00" : (pArea->low_range > 9 && pArea->low_range < 100) ? "0" : "",
             pArea->low_range,
             (pArea->high_range < 10) ? "00" : (pArea->high_range > 9 && pArea->high_range < 100) ? "0" : "",
             pArea->high_range, pArea->name, pArea->authors,
             (!str_cmp (pArea->credits, "FINISHED!!")) ? "FINISHED!!" : "");
            count++;
	      add_buf( output, buf );
          }
        }
	}
	pArea = pArea->next;
      }
    }


    else
    {
      send_to_char("Syntax: areas [game|range|author|finished] <game|range|author|(yes/no)>\n\r",ch);
      return;
    }
    

    send_to_char("{DGAME [ {wLEVEL {D]  {WAREA NAME                         "
                 "{rBUILDER(S)          {RFINISHED?!{x\n\r"
    "{D--------------------------------------------------------------------------------{w\n\r",ch);
    if(count > 0)
    {
      sprintf(buf,"Areas found: %d\n\r",count);
      add_buf( output, buf);
    }
    page_to_char(buf_string(output), ch);
    return;
    free_buf(output);
}



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


That should be everything.  I don't think I missed anything, but anything is possible.
I claim no responsibility for any of this code to work or it to be compatible with your
game.  The code was written for a heavily modified Rom 2.4.  It was written specifically
for release on http://www.mudbytes.net/

Here is what I added to my areas helpfile:

Syntax: areas
        areas [game|range|author|finished] <game|range|author|(yes/no)>


AREAS shows you a list of areas in the game.  The command followed by the
parameter 'game' and an appropriate argument will show all of the areas
built from a specific game.  Such as 'areas game FF05' will show all of the
Final Fantasy 5 areas, while 'areas game CC' will show all of the Chrono Cross.
Followed by range, you may supply a level range.  Typing 'areas range 60 65'
will supply areas that are listed as having something for characters in that
level range.  Finally, areas followed by author will show areas created by
the supplied author.  Such as 'areas author Diablos' will show all of the
areas that are credited, even partially, to Diablos.  Typing 'area finished yes'
will show all of the finished areas in the game.