/
dirt31/
dirt31/bin/
#include "kernel.h"
#include "zones.h"
#include "levels.h"
#include "mobile.h"
#include "rooms.h"
#include "objsys.h"
#include "clone.h"

/*
 * Return the zone index for a given zone name (abbreviation).
 * -1 if no such zone is found.
 */
int get_zone_by_name(char *name)
{
	int x;
	int w = strlen(name);

	for (x = 0; x < numzon; x++) {
		if (strncasecmp(name, zname(x), w) == 0)  return x;
	}

	return -1;
}


/* Return the zone index among the non-permanent zones which matches
 * the given name _exacely_. If none exists, create one and return that index.
 */
int get_wizzone_by_name(char *name)
{
	int i;

	for (i = num_const_zon; i < numzon; i++) {
		if (strcasecmp(name, zname(i)) == 0) return i;
	}

	if (numzon == zon_array_len) {

		zon_array_len += 20;

		zoname = resize_array(zoname, sizeof(ZONE),
				      numzon, zon_array_len);
	}

	zname(numzon) = COPY(name);
	ztemporary(numzon) = True;

	init_intset(zlocs(numzon), 5);
	init_intset(zmobs(numzon), 3);
	init_intset(zobjs(numzon), 3);

	return numzon++;
}


/*
 * Return the ZONE entry index for the zone that 'loc' is member of.
 * Return -1 if invalid loc number.
 */
int loc2zone(int loc)
{
	return exists(loc) ? lzone(loc) : -1;
}


/*
 * Take a 'loc' as argument and return the zone name and the offset within
 * the zone for this loc.
 * If buff = NULL, return the name in a static buffer.
 */
int findzone(int loc, char *buff)
{
	int z, x;

	if ((z = loc2zone(loc)) == -1) {
		strcpy(buff, "TCHAN");
		return 0;
	}

	strcpy(buff, zname(z));

/* Remove mudlog later if everything seems ok: */
	if (!(x = find_int(loc, zlocs(z)))) {
		mudlog("Internal error: location %d was not in its zone %d.",
		       loc, z);
	}

	return x;
}

/*
 * This function is inverse of findzone in that it
 * from a zone index and offset number finds the loc that it makes up.
 * 0 is returned on error.
 */
int getlocid(int z, int off)
{
	int a;

	if (z == -1 || z >= numzon) return 0;

	if (off == 0) off = 1;
	else if (off < 0) return 0;

	return (a = find_int_number(off - 1, zlocs(z))) == SET_END ? 0 : a;
}

/*
 * This function is inverse of findzone in that it
 * from a zone name and number finds the loc that it makes up.
 * 0 is returned on error.
 */
int getlocnum(char *zname,int off)
{
	return getlocid(get_zone_by_name(zname),off);
}


/* Reset a zone. If r_* != NULL, return the number of locs/objs/mobs that
 * were successfully reset. d_* = number of items destructed.
 *
 * If the zone is a wiz-made zone and the owner hasn't been on for a
 * certain time since 'now', his zone has 'expired' and will be destructed,
 * but if 'now' == NULL, proceed as if it had not expired, (ie reset it),
 * but don't kill any of the temporary (=not stored with STORE) items.
 */
void reset_zone(int z, time_t *now, int *d_locs, int *d_mobs, int *d_objs,
		                    int *r_locs, int *r_mobs, int *r_objs)
{
	PERSONA p;
	Boolean reused;
	int i;
	int xd_locs = 0, xd_mobs = 0, xd_objs = 0,
	    xr_locs = 0, xr_mobs = 0, xr_objs = 0;

	if (zpermanent(z)
	    ||
	   (!ztemporary(z) &&
	           (fpbns(zname(z)) > -1
		         ||
		    getuaf(zname(z), &p) &&
	           (now == NULL || *now - p.p_last_on < WIZZONE_EXIST_H*3600L))
	   )
	){
		for (i = zfirst_mob(z); i != SET_END; i = znext_mob(z))
		        do {
				if (!ptemporary(i)) {
					if (reset_mobile(i)) xr_mobs++;
					break;
				} else {
					if (now == NULL) break;
				}
			} while (destruct_mobile(i, &reused) &&
				(xd_mobs++, reused));

		for (i = zfirst_obj(z); i != SET_END; i = znext_obj(z))
		        do {
				if (!otemporary(i)) {
					if (reset_object(i)) xr_objs++;
					break;
				} else {
					if (now == NULL) break;
				}
			} while (destruct_object(i, &reused) &&
				(xd_objs++, reused));

		for (i = zfirst_loc(z); i != SET_END; i = znext_loc(z))
		        do {
				if (!ltemporary(i)) {
					if (reset_location(i)) xr_locs++;
					break;
				} else {
					if (now == NULL) break;
				}
			} while (destruct_location(i, &reused) &&
				(xd_locs++, reused));

	} else {

		for (i = zfirst_obj(z); i != SET_END; i = znext_obj(z))
			while (destruct_object(i, &reused) && reused);

		for (i = zfirst_mob(z); i != SET_END; i = znext_mob(z))
		        while (destruct_mobile(i, &reused) && reused);

		for (i = zfirst_loc(z); i != SET_END; i = znext_loc(z))
		        while (destruct_location(i, &reused) && reused);
	
		ztemporary(z) = True;
	}

	if (d_locs != NULL) *d_locs = xd_locs;  /* locs destroyed */
	if (d_mobs != NULL) *d_mobs = xd_mobs;  /* mobs destroyed */
	if (d_objs != NULL) *d_objs = xd_objs;  /* objs destroyed */
	if (r_locs != NULL) *r_locs = xr_locs;  /* locs reset */
	if (r_mobs != NULL) *r_mobs = xr_mobs;  /* mobs reset */
	if (r_objs != NULL) *r_objs = xr_objs;  /* objs reset */
}


/* Load a zone from disk into the game.
 * Name, is its owner, which also identifies the files it's stored on.
 * Place the number of items found and the number actually loaded in the
 * positions pointed to by the arguments.
 * Return memory allocated as our function value, -1 on error.
 */
int load_zone(char *name, int *nlocs, int *nlocs_f, int *nmobs, int *nmobs_f,
	      int *nobjs, int *nobjs_f)
{
	Boolean  locs_exist, mobs_exist, objs_exist;
	char     filename[128];
	FILE    *locfile, *mobfile, *objfile;
	int      loc_mem = 0, mob_mem = 0, obj_mem = 0;
	int      z;

	if (nlocs != NULL) *nlocs = 0;	 if (nlocs_f != NULL) *nlocs_f = 0;
	if (nmobs != NULL) *nmobs = 0;	 if (nmobs_f != NULL) *nmobs_f = 0;
	if (nobjs != NULL) *nobjs = 0;	 if (nobjs_f != NULL) *nobjs_f = 0;

	wiz_loc_filename(filename, name);
	locs_exist = (locfile = fopen(filename, "r")) != NULL;

	wiz_mob_filename(filename, name);
	mobs_exist = (mobfile = fopen(filename, "r")) != NULL;

	wiz_obj_filename(filename, name);
	objs_exist = (objfile = fopen(filename, "r")) != NULL;

	if (!(locs_exist || mobs_exist || objs_exist)) {
		return 0;
	}

	z = get_wizzone_by_name(name);
	ztemporary(z) = False;

	if (locs_exist) {
		loc_mem = load_locations(z, locfile, nlocs, nlocs_f);
		fclose(locfile);
	}

	if (mobs_exist) {
		mob_mem = load_mobiles(z, mobfile, nmobs, nmobs_f);
		fclose(mobfile);
	}

	if (objs_exist) {
		obj_mem = load_objects(z, objfile, nobjs, nobjs_f);
		fclose(objfile);
	}

	reset_zone(z, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

	return (loc_mem < 0 || mob_mem < 0 || obj_mem < 0) ? -1
	  : loc_mem + mob_mem + obj_mem;
}



/* From a character name, get the filenames that will contain his zone.
 */
static char *wiz_zone_filename(char *buff, char *name, char *contents)
{
	sprintf(buff, "%s/%s.%s", WIZ_ZONES, name, contents);
	return buff;
}

char *wiz_mob_filename(char *buff, char *name)
{
	return wiz_zone_filename(buff, name, "mobiles");
}

char *wiz_loc_filename(char *buff, char *name)
{
	return wiz_zone_filename(buff, name, "locations");
}

char *wiz_obj_filename(char *buff, char *name)
{
	return wiz_zone_filename(buff, name, "objects");
}



/* The ZONES command.
 */
void zonescom(void)
{
	int a;

	if (plev(mynum) < LVL_WIZARD) {
		erreval();
		return;
	}

	bprintf("     Zone-Name Rooms  Mobiles  Objects  "
		"Zone-Name  Rooms  Mobiles  Objects\n\n");

	for (a = 0; a < num_const_zon; a++) {
		bprintf("%14s%5d %7d %7d", zname(a), znumloc(a),
			znumchars(a), znumobs(a));

		if (a % 2 == 1 || a == num_const_zon - 1)  bprintf("\n");
	}

	bprintf("\nA total of %d permanent zones containing "
		"%d rooms, %d mobiles, %d objects.\n\n",
		num_const_zon, num_const_locs, num_const_chars - max_players,
		num_const_obs);

	if (numzon != num_const_zon) {

		int i = 0;

		bprintf("     Zone-Name Rooms  Mobiles  Objects  "
			"Zone-Name  Rooms  Mobiles  Objects\n\n");

		for (a = num_const_zon; a < numzon; a++) {
			int locs = znumloc(a);
			int mobs = znumchars(a);
			int objs = znumobs(a);

			if (!ztemporary(a) || locs > 0 || mobs > 0 || objs >0){

				bprintf("%14s%5d %7d %7d",
					zname(a), locs, mobs, objs);

				if (i++ % 2 == 1)
				        bprintf("\n");
			}
		}

		bprintf("\nA total of %d Wizard's zones containing "
			"%d rooms, %d mobiles, %d objects.\n",
			i,
			numloc - num_const_locs,
			numchars - num_const_chars,
			numobs - num_const_obs);
	}
}