smaug1.8/area/imc/
smaug1.8/boards/
smaug1.8/councils/
smaug1.8/deity/
smaug1.8/doc/mudprogs/
smaug1.8/gods/
smaug1.8/houses/
smaug1.8/log/
smaug1.8/vault/
/*
 *  Renumber Imm command
 *  Author: Cronel (cronel_kal@hotmail.com)
 *  of FrozenMUD (empire.digiunix.net 4000)
 *
 *  Permission to use and distribute this code is granted provided
 *  this header is retained and unaltered, and the distribution
 *  package contains all the original files unmodified.
 *  If you modify this code and use/distribute modified versions
 *  you must give credit to the original author(s).
 */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "mud.h"

#define NOT_FOUND (-1)
enum {REN_ROOM, REN_OBJ, REN_MOB};
struct renumber_data
{
	int		old_vnum;
	int		new_vnum;

	struct renumber_data *next;
};
typedef struct renumber_data RENUMBER_DATA;
struct renumber_area
{
	int		low_obj, hi_obj;
	RENUMBER_DATA	*r_obj;
	int		low_mob, hi_mob;
	RENUMBER_DATA	*r_mob;
	int		low_room, hi_room;
	RENUMBER_DATA	*r_room;
};
typedef struct renumber_area RENUMBER_AREA;

void renumber_area( CHAR_DATA *ch, AREA_DATA *area, RENUMBER_AREA *r_area, bool area_is_proto, bool verbose );

RENUMBER_AREA *gather_renumber_data( AREA_DATA *area, int new_base, bool fill_gaps );
RENUMBER_DATA *gather_one_list( sh_int type, int low, int high, int new_base, bool fill_gaps, int *max_vnum );
void free_renumber_data( RENUMBER_DATA *r_data );

AREA_DATA *find_area( char *filename, bool *p_is_proto );
bool check_vnums( CHAR_DATA *ch, AREA_DATA *tarea, RENUMBER_AREA *r_area );

int find_translation( int vnum, RENUMBER_DATA *r_data );
void translate_reset( RESET_DATA *reset, RENUMBER_AREA *r_data );
void translate_objvals( CHAR_DATA *ch, AREA_DATA *area, RENUMBER_AREA *r_data, bool verbose );
void translate_exits( CHAR_DATA *ch, AREA_DATA *area, RENUMBER_AREA *r_area, bool verbose );
void warn_progs( CHAR_DATA *ch, int low, int high, AREA_DATA *area, RENUMBER_AREA *r_area );
void warn_in_prog( CHAR_DATA *ch, int low, int high, char *where, int vnum, MPROG_DATA *mprog, RENUMBER_AREA *r_area );

/* from db.c */
extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];
extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
extern OBJ_INDEX_DATA *obj_index_hash[MAX_KEY_HASH];

void do_renumber( CHAR_DATA *ch, char *argument )
{
	RENUMBER_AREA *r_area;
	AREA_DATA *area;
	bool is_proto;
	char arg1[ MAX_INPUT_LENGTH ];
	int new_base;
	bool fill_gaps, verbose;

	/* parse the first two parameters */
	/* first, area */
	argument = one_argument( argument, arg1 );
	if( arg1[0] == '\0' ) 
	{
		ch_printf(ch, "What area do you want to renumber?\n\r");
		return;
	}
	area = find_area( arg1, &is_proto );
	if( area == NULL )
	{
		ch_printf( ch, "No such area '%s'.\n\r", arg1 );
		return;
	}

	/* and new vnum base */
	argument = one_argument( argument, arg1 );
	if( arg1[0] == '\0' ) 
	{
		ch_printf(ch, "What will be the new vnum base for this area?\n\r" );
		return;
	}
	if( !is_number(arg1) )
	{
		ch_printf(ch, "Sorry, '%s' is not a valid vnum base number!\n\r", arg1 );
		return;
	}
	new_base = atoi( arg1 ) ;

	/* parse the flags */
	fill_gaps = FALSE;
	verbose = FALSE;
	for(;;)
	{
		argument = one_argument( argument, arg1 );
		if( arg1[0] == '\0' )
			break;
		else if( !str_prefix( arg1, "fillgaps") )
			fill_gaps = TRUE;
		else if( !str_prefix( arg1, "verbose" ) )
			verbose = TRUE;
		else
		{
			ch_printf(ch, "Invalid flag '%s'.\n\r",
				arg1 );
			return;
		}
	}

	/* sanity check */
	if( new_base == area->low_r_vnum &&
		new_base == area->low_o_vnum &&
		new_base == area->low_m_vnum &&
		!fill_gaps )
	{
		ch_printf(ch, "You don't want to change the base vnum and you don't want to fill gaps...\n\rSo what DO you wanna do?\n\r" );
		return;
	}

	/* some restrictions */
	if( IS_NPC(ch) )
	{
		ch_printf(ch, "Yeah, right.\n\r" );
		return;
	}
	if( ch->level < LEVEL_SAVIOR )
	{
		ch_printf(ch, "You don't have enough privileges.\n\r" );
		return;
	}
	if( ch->level == LEVEL_SAVIOR )
	{
		if( area->low_r_vnum < ch->pcdata->r_range_lo || area->hi_r_vnum > ch->pcdata->r_range_hi ||
			area->low_m_vnum < ch->pcdata->m_range_lo || area->hi_m_vnum > ch->pcdata->m_range_hi ||
			area->low_o_vnum < ch->pcdata->o_range_lo || area->hi_o_vnum > ch->pcdata->o_range_hi )
		{
			ch_printf(ch, "You can't renumber that area ('%s').\n\r",
				area->filename );
			return;
		}
	}

	/* get the renumber data */
	r_area = gather_renumber_data( area, new_base, fill_gaps );

	/* one more restriction */
	if( ch->level == LEVEL_SAVIOR )
	{
		if( r_area->low_room < ch->pcdata->r_range_lo || r_area->hi_room > ch->pcdata->r_range_hi ||
			r_area->low_obj < ch->pcdata->o_range_lo || r_area->hi_obj > ch->pcdata->o_range_hi ||
			r_area->low_mob < ch->pcdata->m_range_lo || r_area->hi_mob > ch->pcdata->m_range_hi )
		{
			ch_printf(ch, "The renumbered area would be outside your assigned vnum range.\n\r" );
			return;
		}
	}
	else if( is_proto )
	{
		if( r_area->low_room < area->low_r_vnum || r_area->hi_room > area->hi_r_vnum ||
			r_area->low_obj < area->low_o_vnum || r_area->hi_obj > area->hi_o_vnum ||
			r_area->low_mob < area->low_m_vnum || r_area->hi_mob > area->hi_m_vnum )
		{
			ch_printf(ch, "Moving a proto area out of its range would create problems.\n\rWait till the area is finished to move it.\n\r" );
			return;
		}
	}

	/* no overwriting of dest vnums */
	if( check_vnums( ch, area, r_area ) )
		return;

	/* another sanity check :) */
	if( r_area == NULL || 
		(r_area->r_obj == NULL && r_area->r_mob == NULL && r_area->r_room == NULL) )
	{
		ch_printf(ch, "No changes to make.\n\r" );
		if( r_area != NULL )
			DISPOSE(r_area );
		return;
	}

	/* ok, do it! */
	pager_printf(ch, "Renumbering area '%s' to new base %d, filling gaps: %s\n\r",
		area->filename, new_base, fill_gaps ? "yes" : "no" );
	renumber_area( ch, area, r_area, is_proto, verbose );
	pager_printf(ch, "Done.\n\r" );

	/* clean up and goodbye */
	if( r_area->r_room != NULL )
		free_renumber_data( r_area->r_room );
	if( r_area->r_obj != NULL )
		free_renumber_data( r_area->r_obj );
	if( r_area->r_mob != NULL )
		free_renumber_data( r_area->r_mob );
	DISPOSE( r_area );
}

bool check_vnums( CHAR_DATA *ch, AREA_DATA *tarea, RENUMBER_AREA *r_area )
{
	int high, low;
	AREA_DATA *area;
	bool proto;

	/* this function assumes all the lows are allways gonna be
	   lower or equal to all the highs .. */
	high = UMAX(r_area->hi_room, UMAX(r_area->hi_obj, r_area->hi_mob));
	low = UMIN(r_area->low_room, UMIN(r_area->low_obj, r_area->low_mob));

	/* in do_check_vnums they use first_bsort, first_asort but.. i dunno.. */
	area = first_area;
	proto = FALSE;
	while( area )
	{
		if( tarea == area )
			;
		else if( !(high < area->low_r_vnum || low > area->hi_r_vnum) ||
			!(high < area->low_o_vnum || low > area->hi_o_vnum) ||
			!(high < area->low_m_vnum || low > area->hi_m_vnum ) )
		{
			ch_printf(ch, "This operation would overwrite area %s! Use checkvnums first.\n\r",
				area->filename);
			return TRUE;
		}

		area = area->next;
		if( area == NULL && !proto )
		{
			area = first_build;
			proto = TRUE;
		}
	}
	return FALSE;
}

RENUMBER_AREA *gather_renumber_data( AREA_DATA *area, int new_base, bool fill_gaps )
/* this function actualy gathers all the renumber data for an area */
{
	RENUMBER_AREA *r_area;
	int max;

	CREATE(r_area, RENUMBER_AREA, 1);

	r_area->r_mob = gather_one_list( REN_MOB, area->low_m_vnum, area->hi_m_vnum, new_base, fill_gaps, &max );
	r_area->low_mob = new_base;
	r_area->hi_mob = max;

	r_area->r_obj = gather_one_list( REN_OBJ, area->low_o_vnum, area->hi_o_vnum, new_base, fill_gaps, &max );
	r_area->low_obj = new_base;
	r_area->hi_obj = max;

	r_area->r_room = gather_one_list( REN_ROOM, area->low_r_vnum, area->hi_r_vnum, new_base, fill_gaps, &max );
	r_area->low_room = new_base;
	r_area->hi_room = max;

	return r_area;
}

RENUMBER_DATA *gather_one_list( sh_int type, int low, int high, int new_base, bool fill_gaps, int *max_vnum )
/* this function builds a list of renumber data for a type (obj, room, or mob) */
{
	int cur_vnum;
	RENUMBER_DATA *r_data, root;
	bool found;
	ROOM_INDEX_DATA *room;
	OBJ_INDEX_DATA *obj;
	MOB_INDEX_DATA *mob;
	int i;
	int highest;

	memset( &root, 0, sizeof(RENUMBER_DATA) );
	r_data = &root;

	cur_vnum = new_base;
	highest = -1;
	for( i=low ; i<=high ; i++ )
	{
		found = FALSE;
		switch(type)
		{
			case REN_ROOM: 
				room = get_room_index( i );
				if( room != NULL ) 
					found = TRUE;
				break;
			case REN_OBJ:
				obj = get_obj_index( i );
				if( obj != NULL )
					found = TRUE;
				break;
			case REN_MOB:
				mob = get_mob_index( i );
				if( mob != NULL )
					found = TRUE;
				break;
		}

		if( found )
		{
			if( cur_vnum > highest )
				highest = cur_vnum;
			if( cur_vnum != i ) 
			{
				CREATE(r_data->next, RENUMBER_DATA, 1);
				r_data = r_data->next;
				r_data->old_vnum = i;
				r_data->new_vnum = cur_vnum;
			}
			cur_vnum++;
		}
		else if( !fill_gaps )
			cur_vnum++;
	}
	*max_vnum = highest;
	return root.next;
}

void free_renumber_data( RENUMBER_DATA *r_data )
/* disposes of a list of renumber data items */
{
	RENUMBER_DATA *r_next;

	while( r_data != NULL )
	{
		r_next = r_data->next;
		DISPOSE(r_data);
		r_data = r_next;
	}
}

void renumber_area( CHAR_DATA *ch, AREA_DATA *area, RENUMBER_AREA *r_area, bool area_is_proto, bool verbose )
/* this is the function that actualy does the renumbering of "area" according
   to the renumber data in "r_area". "ch" is to show messages. */
{
	RENUMBER_DATA *r_data;
	ROOM_INDEX_DATA *room, *room_prev, *room_list, *room_next;
	MOB_INDEX_DATA *mob, *mob_prev, *mob_list, *mob_next;
	OBJ_INDEX_DATA *obj, *obj_prev, *obj_list, *obj_next;
	RESET_DATA *reset;
	int iHash;
	int low, high;

	high = UMAX(area->hi_r_vnum, UMIN(area->hi_o_vnum, area->hi_m_vnum));
	low = UMIN( area->low_r_vnum, UMIN(area->low_o_vnum, area->low_m_vnum));

	pager_printf(ch, "(Room) Renumbering...\n\r" );

	/* what we do here is, for each list (room/obj/mob) first we
	 * take each element out of the hash array, change the vnum,
	 * and move it to our own list. after everything's moved out
	 * we put it in again. this is to avoid problems in situations
	 * where where room A is being moved to position B, but theres
	 * already a room B wich is also being moved to position C.
	 * a straightforward approach would result in us moving A to
	 * position B first, and then again to position C, and room
	 * B being lost inside the hash array, still there, but not
	 * foundable (its "covered" by A because they'd have the same 
	 * vnum). 
	 */

	room_list = NULL;
	for( r_data = r_area->r_room ; r_data ; r_data = r_data->next )
	{
		if( verbose )
			pager_printf(ch, "(Room) %d -> %d\n\r", 
				r_data->old_vnum, r_data->new_vnum );

		room = get_room_index( r_data->old_vnum );
		if( !room )
		{
			bug( "renumber_area: NULL room %d", r_data->old_vnum );
			continue;
		}

		/* remove it from the hash list */
		iHash = r_data->old_vnum % MAX_KEY_HASH;
		if( room_index_hash[iHash] == room )
			room_index_hash[iHash] = room->next;
		else
		{
			for( room_prev = room_index_hash[iHash] ; room_prev && room_prev->next != room ; room_prev = room_prev->next )
				;
			if( room_prev == NULL )
			{
				bug( "renumber_area: Couldn't find a room in the hash table! Skipping it.\n\r" );
				continue;
			}
			room_prev->next = room->next;
			room->next = NULL;
		}

		/* change the vnum */
		room->vnum = r_data->new_vnum;

		/* move it to the temporary list */
		room->next = room_list;
		room_list = room;
	}
	/* now move everything back into the hash array */
	for(room = room_list ; room ; room = room_next )
	{
		room_next = room->next;
		/* add it to the hash list again (new position) */
		iHash = room->vnum % MAX_KEY_HASH;
		room->next = room_index_hash[iHash];
		room_index_hash[iHash] = room;
	}
	/* if nothing was moved, or if the area is proto, dont change this */
	if( r_area->r_room != NULL && !area_is_proto )
	{
		area->low_r_vnum = r_area->low_room;
		area->hi_r_vnum = r_area->hi_room;
	}

	pager_printf(ch, "(Mobs) Renumbering...\n\r" );
	mob_list = NULL;
	for( r_data = r_area->r_mob ; r_data ; r_data = r_data->next )
	{
		if( verbose )
			pager_printf(ch, "(Mobs) %d -> %d\n\r", 
				r_data->old_vnum, r_data->new_vnum );

		mob = get_mob_index( r_data->old_vnum );
		if( !mob )
		{
			bug( "renumber_area: NULL mob %d", r_data->old_vnum );
			continue;
		}

		/* fix references to this mob from shops while renumbering this mob */
		if( mob->pShop )
		{
			if( verbose )
				pager_printf(ch, "(Mobs) Fixing shop for mob %d -> %d\n\r", 
				r_data->old_vnum, r_data->new_vnum );
			mob->pShop->keeper = r_data->new_vnum;
		}
		if( mob->rShop )
		{
			if( verbose )
				pager_printf(ch, "(Mobs) Fixing repair shop for mob %d -> %d\n\r", 
				r_data->old_vnum, r_data->new_vnum );
			mob->rShop->keeper = r_data->new_vnum;
		}

		/* remove it from the hash list */
		iHash = r_data->old_vnum % MAX_KEY_HASH;
		if( mob_index_hash[iHash] == mob )
			mob_index_hash[iHash] = mob->next;
		else
		{
			for( mob_prev = mob_index_hash[iHash] ; mob_prev && mob_prev->next != mob ; mob_prev = mob_prev->next )
				;
			if( mob_prev == NULL )
			{
				bug( "renumber_area: Couldn't find a mob in the hash table! Skipping it.\n\r" );
				continue;
			}
			mob_prev->next = mob->next;
			mob->next = NULL;
		}

		/* change the vnum */
		mob->vnum = r_data->new_vnum;

		/* move to private list */
		mob->next = mob_list;
		mob_list = mob;
	}
	for( mob = mob_list ; mob ; mob = mob_next )
	{
		mob_next = mob->next;
		/* add it to the hash list again */
		iHash = mob->vnum % MAX_KEY_HASH;
		mob->next = mob_index_hash[iHash];
		mob_index_hash[iHash] = mob;
	}
	if( r_area->r_mob && !area_is_proto )
	{
		area->low_m_vnum = r_area->low_mob;
		area->hi_m_vnum = r_area->hi_mob;
	}

	pager_printf(ch, "(Objs) Renumbering...\n\r" );
	obj_list = NULL;
	for( r_data = r_area->r_obj ; r_data ; r_data = r_data->next )
	{
		if( verbose )
			pager_printf(ch, "(Objs) %d -> %d\n\r", 
				r_data->old_vnum, r_data->new_vnum );	
		obj = get_obj_index( r_data->old_vnum );
		if( !obj )
		{
			bug( "renumber_area: NULL obj %d", r_data->old_vnum );
			continue;
		}

		/* remove it from the hash list */
		iHash = r_data->old_vnum % MAX_KEY_HASH;
		if( obj_index_hash[iHash] == obj )
			obj_index_hash[iHash] = obj->next;
		else
		{
			for( obj_prev = obj_index_hash[iHash] ; obj_prev && obj_prev->next != obj ; obj_prev = obj_prev->next )
				;
			if( obj_prev == NULL )
			{
				bug( "renumber_area: Couldn't find an obj in the hash table! Skipping it.\n\r" );
				continue;
			}
			obj_prev->next = obj->next;
			obj->next = NULL;
		}

		/* change the vnum */
		obj->vnum = r_data->new_vnum;

		/* to our list */
		obj->next = obj_list;
		obj_list = obj;
	}
	for( obj = obj_list ; obj ; obj = obj_next )
	{
		obj_next = obj->next;
		/* add it to the hash list again */
		iHash = obj->vnum % MAX_KEY_HASH;
		obj->next = obj_index_hash[iHash];
		obj_index_hash[iHash] = obj;
	}
	if( r_area->r_obj && !area_is_proto )
	{
		area->low_o_vnum = r_area->low_obj;
		area->hi_o_vnum = r_area->hi_obj;
	}

	pager_printf(ch, "Fixing references...\n\r" );

	pager_printf(ch, "... fixing objvals...\n\r" );
	translate_objvals( ch, area, r_area, verbose );

	pager_printf(ch, "... fixing exits...\n\r" );
	translate_exits( ch, area, r_area, verbose );

	pager_printf(ch, "... fixing resets...\n\r");
	for( reset = area->first_reset ; reset ; reset = reset->next )
		translate_reset( reset, r_area );

	if( verbose )
	{
		pager_printf(ch, "Searching progs for references to renumbered vnums...\n\r" );
		warn_progs( ch, low, high, area, r_area );
	}
}

void translate_exits( CHAR_DATA *ch, AREA_DATA *area, RENUMBER_AREA *r_area, bool verbose )
{
	int i, new_vnum;
	EXIT_DATA *exit, *rev_exit;
	ROOM_INDEX_DATA *room;
	int old_vnum;

	for( i=area->low_r_vnum ; i<=area->hi_r_vnum ; i++ )
	{
		room = get_room_index( i );
		if( !room )
			continue;
		for( exit = room->first_exit ; exit ; exit = exit->next )
		{
			/* translate the exit destination, if it was moved */
			new_vnum = find_translation( exit->vnum, r_area->r_room );
			if( new_vnum != NOT_FOUND )
				exit->vnum = new_vnum;
			/* if this room was moved */
			if( exit->rvnum != i )
			{
				old_vnum = exit->rvnum;
				exit->rvnum = i;
				/* all reverse exits in other areas will be wrong */
				rev_exit = get_exit_to( exit->to_room, rev_dir[exit->vdir], old_vnum );
				if( rev_exit && exit->to_room->area != area )
				{
					if( rev_exit->vnum != i )
					{
						pager_printf(ch, "...    fixing reverse exit in area %s.\n\r", 
							exit->to_room->area->filename );
						rev_exit->vnum = i;
					}
				}
			}

			/* translate the key */
			if( exit->key != -1 )
			{
				new_vnum = find_translation( exit->key, r_area->r_obj );
				if( new_vnum == NOT_FOUND )
					continue;
				exit->key = new_vnum;
			}
		}
	}
}

void translate_objvals( CHAR_DATA *ch, AREA_DATA *area, RENUMBER_AREA *r_area, bool verbose )
{
	int i, new_vnum;
	OBJ_INDEX_DATA *obj;

	for( i=area->low_o_vnum ; i<=area->hi_o_vnum ; i++ )
	{
		obj = get_obj_index( i ) ;
		if( !obj )
			continue;

		if( obj->item_type == ITEM_CONTAINER )
		{
			new_vnum = find_translation( obj->value[2], r_area->r_obj );
			if( new_vnum != NOT_FOUND )
			{
				if( verbose )
					pager_printf(ch, "...    container %d; fixing objval2 (key vnum) %d -> %d\n\r",
						i, obj->value[2], new_vnum );
				obj->value[2] = new_vnum;
			}
			else if( verbose )
				pager_printf(ch, "...    container %d; no need to fix.\n\r" ,
					i );
		}
		else if( obj->item_type == ITEM_SWITCH || obj->item_type == ITEM_LEVER ||
			obj->item_type == ITEM_PULLCHAIN || obj->item_type == ITEM_BUTTON )
		{
			/* levers might have room vnum references in their objvals */
			if( IS_SET(obj->value[0], TRIG_TELEPORT)
			|| IS_SET(obj->value[0], TRIG_TELEPORTALL )
			|| IS_SET(obj->value[0], TRIG_TELEPORTPLUS )
			|| IS_SET(obj->value[0], TRIG_RAND4)
			|| IS_SET(obj->value[0], TRIG_RAND6 )
			|| IS_SET(obj->value[0], TRIG_DOOR ) )
			{
				new_vnum = find_translation( obj->value[1], r_area->r_room );
				if( new_vnum != NOT_FOUND )
				{
					if( verbose )
						pager_printf(ch, "...    lever %d: fixing source room (%d -> %d)\n\r",
							i, obj->value[1], new_vnum );
					obj->value[1] = new_vnum;
				}
				if( IS_SET(obj->value[0], TRIG_DOOR)
				&& IS_SET(obj->value[0], TRIG_PASSAGE) )
				{
					new_vnum = find_translation( obj->value[2], r_area->r_room );
					if( new_vnum != NOT_FOUND )
					{
						if( verbose )
						pager_printf(ch, "...    lever %d: fixing dest room (passage) (%d -> %d)\n\r",
							i, obj->value[2], new_vnum );
						obj->value[2] = new_vnum;
					}
				}
			}
		}
	}
}

void warn_progs( CHAR_DATA *ch, int low, int high, AREA_DATA *area, RENUMBER_AREA *r_area )
{
	ROOM_INDEX_DATA *room;
	OBJ_INDEX_DATA *obj;
	MOB_INDEX_DATA *mob;
	MPROG_DATA *mprog;
	int i;

	for( i=area->low_r_vnum ; i<=area->hi_r_vnum ; i++ )
	{
		room = get_room_index( i );
		if( !room )
			continue;
		mprog = room->mudprogs;
		while( mprog )
		{
			warn_in_prog( ch, low, high, "room", i, mprog, r_area );
			mprog = mprog->next;
		}
	}

	for( i=area->low_o_vnum ; i<=area->hi_o_vnum ; i++ )
	{
		obj = get_obj_index( i );
		if( !obj )
			continue;
		mprog = obj->mudprogs;
		while( mprog )
		{
			warn_in_prog( ch, low, high, "obj", i, mprog, r_area );
			mprog = mprog->next;
		}
	}

	for( i=area->low_m_vnum ; i<=area->hi_m_vnum ; i++ )
	{
		mob = get_mob_index( i );
		if( !mob )
			continue;
		mprog = mob->mudprogs;
		while( mprog )
		{
			warn_in_prog( ch, low, high, "mob", i, mprog, r_area );
			mprog = mprog->next;
		}
	}
}



void warn_in_prog( CHAR_DATA *ch, int low, int high, char *where, int vnum, MPROG_DATA *mprog, RENUMBER_AREA *r_area )
{
	char *p, *start_number, cTmp;
	int num;

	p = mprog->comlist;
	while( *p )
	{
		if( isdigit(*p) )
		{
			start_number = p;
			while( isdigit(*p) && *p )
				p++;
			cTmp = *p;
			*p = 0;
			num = atoi( start_number );
			*p = cTmp;
			if( num >= low && num <= high )
			{
				pager_printf(ch, "Warning! %s prog in %s vnum %d might contain a reference to %d.\n\r(Translation: Room %d, Obj %d, Mob %d)\n\r",
					mprog_type_to_name(mprog->type),
					where,
					vnum,
					num,
					find_translation( num, r_area->r_room),
					find_translation( num, r_area->r_obj),
					find_translation( num, r_area->r_mob) );
			}
			if( *p == '\0' )
				break;
		}
		p++;
	}
}


void translate_reset( RESET_DATA *reset, RENUMBER_AREA *r_data )
/* this function translates a reset according to the renumber data in r_data */
{
	/* a list based approach to fixing the resets. instead
	   of having a bunch of several instances of very 
	   similar code, i just made this array that tells the
	   code what to do. it's pretty straightforward */
	char *action_table[] = 
		{"Mm1r3", "Oo1r3", "Ho1", "Po1o3", 
		 "Go1", "Eo1", "Dr1", "Rr1", NULL };
	char *p;
	RENUMBER_DATA *r_table;
	int *parg, new_vnum, i;

	/* T is a special case */
	if( reset->command == 'T' )
	{
		if( IS_SET(reset->extra, TRAP_ROOM ) )
			r_table = r_data->r_room;
		else if( IS_SET(reset->extra, TRAP_OBJ ) )
			r_table = r_data->r_obj;
		else
		{
			bug("translate_reset: Invalid 'T' reset found.\n\r" );
			return;
		}
		new_vnum = find_translation( reset->arg3, r_table );
		if( new_vnum != NOT_FOUND )
			reset->arg3 = new_vnum;
		return;
	}

	/* B is another special case */
	if( reset->command == 'B' )
	{
		bug( "translate_reset: B command found." );
		if( (reset->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_DOOR ||
		    (reset->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_ROOM )
		{
			new_vnum = find_translation( reset->arg1, r_data->r_obj );
			if( new_vnum != NOT_FOUND )
				reset->arg1 = new_vnum;	
		}
		return;
	}
	
	for( i=0 ; action_table[i] != NULL ; i++ )
	{
		if( reset->command == action_table[i][0] )
		{
			p = action_table[i] + 1;
			while( *p )
			{
				if( *p == 'm' )
					r_table = r_data->r_mob;
				else if( *p == 'o' )
					r_table = r_data->r_obj;
				else if( *p == 'r' )
					r_table = r_data->r_room;
				else
				{
					bug( "translate_reset: Invalid action found in action table.\n\r" );
					p+=2;
					continue;
				}
				p++;

				if( *p == '1' )
					parg = &(reset->arg1);
				else if( *p == '2' )
					parg = &(reset->arg2);
				else if( *p == '3' )
					parg = &(reset->arg3);
				else
				{
					bug("translate_reset: Invalid argument number found in action table.\n\r" );
					p++;
					continue;
				}
				p++;

				new_vnum = find_translation( *parg, r_table );
				if( new_vnum != NOT_FOUND )
					*parg = new_vnum;

			}
			return;
		}
	}

	if( action_table[i] == NULL )
		bug("translate_reset: Invalid reset '%c' found.\n\r", reset->command );
}

int find_translation( int vnum, RENUMBER_DATA *r_data )
/* returns the new vnum for the old vnum "vnum" according to the info in
 * r_data 
 */
{
	RENUMBER_DATA *r_temp;

	for( r_temp = r_data ; r_temp ; r_temp = r_temp->next )
	{
		if( r_temp->old_vnum == vnum )
			return r_temp->new_vnum;
	}
	return NOT_FOUND;
}


AREA_DATA *find_area( char *filename, bool *p_is_proto )
/* simply returns a pointer to a "filename" or NULL if no such area. stores
   TRUE in *p_is_proto if the area is proto */
{
	bool found;
	AREA_DATA *area;

	found = FALSE;

	for( area = first_area; area ; area = area->next )
	{
		if( !str_cmp( area->filename, filename ) )
		{
			found = TRUE;
			break;
		}
	}

	if( found )
	{
		*p_is_proto = FALSE;
		return area;
	}

	for( area = first_build ; area ; area = area->next )
	{
		if( !str_cmp( area->filename, filename ) )
		{
			found = TRUE;
			break;
		}
	}

	if( found )
	{
		*p_is_proto = TRUE;
		return area;
	}
	else
		return NULL;
}