wileymud-1.187b/
wileymud-1.187b/attic/
wileymud-1.187b/attic/bin/
wileymud-1.187b/attic/lib/
wileymud-1.187b/attic/lib/adm/
wileymud-1.187b/attic/lib/man/
wileymud-1.187b/attic/lib/new-wld/
wileymud-1.187b/attic/lib/new-wld/default/
wileymud-1.187b/attic/lib/old/
wileymud-1.187b/attic/lib/wld/
wileymud-1.187b/attic/public_html/
wileymud-1.187b/attic/public_html/gfx/
wileymud-1.187b/attic/src/bin/
wileymud-1.187b/attic/src/etc/
wileymud-1.187b/attic/src/libauth-4.0-p5/
wileymud-1.187b/attic/src/sedna/
wileymud-1.187b/backups/
wileymud-1.187b/bin/
wileymud-1.187b/docs/
wileymud-1.187b/etc/
wileymud-1.187b/lib/
wileymud-1.187b/lib/adm/
wileymud-1.187b/lib/boards/
wileymud-1.187b/lib/log/
wileymud-1.187b/lib/man/
wileymud-1.187b/lib/ply/
wileymud-1.187b/lib/ply/a/
wileymud-1.187b/lib/ply/b/
wileymud-1.187b/lib/ply/c/
wileymud-1.187b/lib/ply/d/
wileymud-1.187b/lib/ply/g/
wileymud-1.187b/lib/ply/k/
wileymud-1.187b/lib/ply/m/
wileymud-1.187b/lib/ply/s/
wileymud-1.187b/lib/ply/t/
wileymud-1.187b/public_html/gfx/
wileymud-1.187b/src/bin/
wileymud-1.187b/src/convert/attic/
wileymud-1.187b/src/convert/obj/
wileymud-1.187b/src/convert/perl/
wileymud-1.187b/src/convert/perl/MudConvert/
wileymud-1.187b/src/convert/perl/MudConvert/DUMP/
wileymud-1.187b/src/convert/perl/MudConvert/Report/
wileymud-1.187b/src/convert/perl/MudConvert/WileyMUD/
wileymud-1.187b/src/convert/perl/output/
wileymud-1.187b/src/convert/perl/output/DUMP/
wileymud-1.187b/src/convert/perl/output/Report/
wileymud-1.187b/src/convert/perl/output/WileyMUD/
wileymud-1.187b/src/etc/
wileymud-1.187b/src/etc/init.d/
wileymud-1.187b/src/etc/rc.d/
wileymud-1.187b/src/etc/rc.d/init.d/
wileymud-1.187b/src/lib/
wileymud-1.187b/src/lib/adm/
wileymud-1.187b/src/lib/boards/
wileymud-1.187b/src/lib/log/
wileymud-1.187b/src/lib/man/
wileymud-1.187b/src/lib/ply/
wileymud-1.187b/src/lib/ply/a/
wileymud-1.187b/src/lib/ply/b/
wileymud-1.187b/src/lib/ply/c/
wileymud-1.187b/src/lib/ply/d/
wileymud-1.187b/src/lib/ply/e/
wileymud-1.187b/src/lib/ply/f/
wileymud-1.187b/src/lib/ply/g/
wileymud-1.187b/src/lib/ply/h/
wileymud-1.187b/src/lib/ply/i/
wileymud-1.187b/src/lib/ply/j/
wileymud-1.187b/src/lib/ply/k/
wileymud-1.187b/src/lib/ply/l/
wileymud-1.187b/src/lib/ply/m/
wileymud-1.187b/src/lib/ply/n/
wileymud-1.187b/src/lib/ply/o/
wileymud-1.187b/src/lib/ply/p/
wileymud-1.187b/src/lib/ply/q/
wileymud-1.187b/src/lib/ply/r/
wileymud-1.187b/src/lib/ply/s/
wileymud-1.187b/src/lib/ply/t/
wileymud-1.187b/src/lib/ply/u/
wileymud-1.187b/src/lib/ply/v/
wileymud-1.187b/src/lib/ply/w/
wileymud-1.187b/src/lib/ply/x/
wileymud-1.187b/src/lib/ply/y/
wileymud-1.187b/src/lib/ply/z/
wileymud-1.187b/src/obj/
wileymud-1.187b/src/utils/
wileymud-1.187b/src/utils/mobmaker/
/*
 * file: reception.c, Special module for Inn's.           Part of DIKUMUD
 * Usage: Procedures handling saving/loading of player objects
 * Copyright (C) 1990, 1991 - see 'license.doc' for complete information.
 */

#include <stdio.h>
#include <stdlib.h>
/* #include <unistd.h> */
#include <sys/types.h>
#include <string.h>
#include <sys/time.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>

#include "global.h"
#include "bug.h"
#include "comm.h"
#include "handler.h"
#include "db.h"
#include "interpreter.h"
#include "utils.h"
#include "spells.h"
#include "multiclass.h"
#include "act_social.h"
#include "spec_procs.h"
#define _RECEPTION_C
#include "reception.h"

double                                  RENT_RATE = 1.0;

/*
 * Routines used for the "Offer"
 */

void add_obj_cost(struct char_data *ch, struct char_data *re,
		  struct obj_data *obj, struct obj_cost *cost)
{
    int                                     temp = 0;

    if (DEBUG > 2)
	log_info("called %s with %s, %s, %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch),
		 SAFE_NAME(re), SAFE_ONAME(obj), (size_t) cost);

    /*
     * Add cost for an item and it's contents, and next->contents 
     */

    if (obj) {
	if ((obj->item_number > -1) && (cost->ok)) {
	    temp = MAX(0, (int)(obj->obj_flags.cost_per_day * RENT_RATE));
	    cost->total_cost += temp;
	    if (re) {
		cprintf(ch, "%30s : %d coins/day\r\n", obj->short_description, temp);
	    }
	    cost->no_carried++;
	    add_obj_cost(ch, re, obj->contains, cost);
	    add_obj_cost(ch, re, obj->next_content, cost);
	} else if (cost->ok) {
	    if (re) {
		act("$n tells you 'I refuse storing $p'", FALSE, re, obj, ch, TO_VICT);
	    } else {
		act("Sorry, but $p don't keep in storage.", FALSE, 0, obj, ch, TO_VICT);
	    }
	}
    }
}

char recep_offer(struct char_data *ch, struct char_data *recep_mob, struct obj_cost *cost)
{
    int                                     i = 0;

    if (DEBUG > 2)
	log_info("called %s with %s, %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch),
		 SAFE_NAME(recep_mob), (size_t) cost);

    cost->total_cost = 0;				       /* Minimum cost */
    cost->no_carried = 0;
    cost->ok = TRUE;					       /* Use if any "-1" objects */
    add_obj_cost(ch, recep_mob, ch->carrying, cost);

    for (i = 0; i < MAX_WEAR; i++)
	add_obj_cost(ch, recep_mob, ch->equipment[i], cost);

    if (!cost->ok)
	return (FALSE);

    if (cost->no_carried == 0) {
	if (recep_mob)
	    act("$n tells you 'But you are not carrying anything?'",
		FALSE, recep_mob, 0, ch, TO_VICT);
	return (FALSE);
    }
    if (cost->no_carried > MAX_OBJ_SAVE) {
	if (recep_mob)
	    act("$n tells you 'Sorry, but I can't store any more than %d items.",
		FALSE, recep_mob, 0, ch, TO_VICT, MAX_OBJ_SAVE);
	return (FALSE);
    }
    if (recep_mob) {
	act("$n tells you 'It will cost you %d coins per day'", FALSE, recep_mob, 0, ch,
	    TO_VICT, cost->total_cost);
	if (cost->total_cost > (GET_GOLD(ch) + GET_BANK(ch))) {
	    if (GetMaxLevel(ch) < LOW_IMMORTAL)
		act("$n tells you 'Which I can see you can't afford'",
		    FALSE, recep_mob, 0, ch, TO_VICT);
	    else {
		act("$n tells you 'Well, since you're a God, I guess it's okay'",
		    FALSE, recep_mob, 0, ch, TO_VICT);
		cost->total_cost = 0;
	    }
	}
    }
    if (cost->total_cost > (GET_GOLD(ch) + GET_BANK(ch)))
	return (FALSE);
    else
	return (TRUE);
}

/*
 * General save/load routines
 */

void update_file(FILE * fl, char *name, struct obj_file_u *st)
{
    struct rental_header                    rh;
    int                                     nlength = 0;

    if (DEBUG > 2)
	log_info("called %s with %08zx, %s, %08zx", __PRETTY_FUNCTION__, (size_t) fl,
		 VNULL(name), (size_t) st);

    if (st->nobjects == 0) {
	rh.inuse = 0;
	nlength = 0;
	rh.length = 0;
    } else {
	rh.inuse = 1;
	nlength = sizeof(*st) + (st->nobjects - MAX_OBJ_SAVE) * sizeof(*st->objects);
	rh.length = nlength;
    }

    strcpy(rh.owner, name);
    fwrite(&rh, sizeof(rh), 1, fl);
    fwrite(st, nlength, 1, fl);
    return;
}

/*
 * Routines used to load a characters equipment from disk
 */

void obj_store_to_char(struct char_data *ch, struct obj_file_u *st)
{
    struct obj_data                        *obj = NULL;
    int                                     i = 0;
    int                                     j = 0;

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), (size_t) st);

    for (i = 0; i < st->nobjects; i++) {
	if (st->objects[i].item_number > -1 && real_object(st->objects[i].item_number) > -1) {
	    obj = read_object(st->objects[i].item_number, VIRTUAL);
	    obj->obj_flags.value[0] = st->objects[i].value[0];
	    obj->obj_flags.value[1] = st->objects[i].value[1];
	    obj->obj_flags.value[2] = st->objects[i].value[2];
	    obj->obj_flags.value[3] = st->objects[i].value[3];
	    obj->obj_flags.extra_flags = st->objects[i].extra_flags;
	    obj->obj_flags.weight = st->objects[i].weight;
	    obj->obj_flags.timer = st->objects[i].timer;
	    obj->obj_flags.bitvector = st->objects[i].bitvector;

	    for (j = 0; j < MAX_OBJ_AFFECT; j++)
		obj->affected[j] = st->objects[i].affected[j];

	    obj_to_char(obj, ch);
	}
    }
}

void load_char_objs(struct char_data *ch)
{
    FILE                                   *fl = NULL;
    float                                   timegold = 0.0;
    int                                     difference = 0;
    struct obj_file_u                      *st = NULL;
    char                                    name[40] = "\0\0\0\0\0\0\0";
    char                                   *t_ptr = NULL;
    char                                    path[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    struct rental_header                    rh;

    if (DEBUG > 2)
	log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(ch));

    strcpy(name, GET_NAME(ch));
    t_ptr = name;
    for (; *t_ptr != '\0'; t_ptr++)
	*t_ptr = LOWER(*t_ptr);
    sprintf(path, "ply/%c/%s.o", name[0], name);

    if (!(fl = fopen(path, "r+b"))) {
	log_info("no .o file for character");
	fl = fopen(path, "w+b");
	rh.inuse = 0;
	rh.length = 0;
	strcpy(rh.owner, "empty");
	fwrite(&rh, sizeof(rh), 1, fl);
    } else
	fread(&rh, sizeof(rh), 1, fl);

    if (rh.inuse == 1) {
	CREATE_VOID(st, char, rh.length);

	fread(st, rh.length, 1, fl);
	obj_store_to_char(ch, st);

/*
 * if the character has been out for 12 real hours, they are fully healed
 * upon re-entry.  if they stay out for 24 full hours, all affects are
 * removed, including bad ones.
 */

	if (st->last_update + 6 * SECS_PER_REAL_HOUR < time(0)) {
	    RestoreChar(ch);
	    RemAllAffects(ch);
	}
	if (ch->in_room == NOWHERE && st->last_update + 12 * SECS_PER_REAL_HOUR > time(0)) {
	    log_info("Char reconnecting after game crash");
	} else {
	    if (ch->in_room == NOWHERE)
		log_info("Char reconnecting after autorent");
	    timegold = (int)(((double)(st->total_cost) *
			      (((double)(time(0) - st->last_update)) /
			       ((double)SECS_PER_REAL_DAY))));
	    log_info("Char ran up charges of %g gold in rent", timegold);
	    cprintf(ch, "You ran up charges of %g gold in rent.\r\n", timegold);
/*
 * Sedna's hack begins here.
 * The butler is now friends with the banker.
 */
	    difference = timegold - GET_GOLD(ch);
	    GET_GOLD(ch) -= timegold;

	    if (GET_GOLD(ch) < 0) {
		GET_BANK(ch) -= difference;
		if (GET_BANK(ch) < 0) {
		    log_info("Char ran out of money in rent-is flat broke");
		    cprintf(ch, "You ran out of money, you deadbeat.\r\n");
		    GET_GOLD(ch) = 0;
		    GET_BANK(ch) = 0;
		} else {
		    log_info("Char ran out of money in rent-withdrew from bank");
		    cprintf(ch,
			    "You ran out of money, and had to make a quick trip to the bank.\r\n");
		    GET_GOLD(ch) = 0;
		}
	    }
	}
	DESTROY(st);
    } else {
	log_info("Char has no rental data");
    }

    FCLOSE(fl);
    /*
     * Save char, to avoid strange data if crashing 
     */

    save_char(ch, NOWHERE);
}

/*
 * Routines used to save a characters equipment from disk
 */

/* Puts object in store, at first item which has no -1 */
void put_obj_in_store(struct obj_data *obj, struct obj_file_u *st)
{
    int                                     j = 0;
    struct obj_file_elem                   *oe = NULL;

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx", __PRETTY_FUNCTION__, SAFE_ONAME(obj), (size_t) st);

    if (st->nobjects >= MAX_OBJ_SAVE) {
	log_info("you want to rent more than %d items?!\n", st->nobjects);
	return;
    }
    oe = st->objects + st->nobjects;

    oe->item_number = obj_index[obj->item_number].virtual;
    oe->value[0] = obj->obj_flags.value[0];
    oe->value[1] = obj->obj_flags.value[1];
    oe->value[2] = obj->obj_flags.value[2];
    oe->value[3] = obj->obj_flags.value[3];

    oe->extra_flags = obj->obj_flags.extra_flags;
    oe->weight = obj->obj_flags.weight;
    oe->timer = obj->obj_flags.timer;
    oe->bitvector = obj->obj_flags.bitvector;
    for (j = 0; j < MAX_OBJ_AFFECT; j++)
	oe->affected[j] = obj->affected[j];

    st->nobjects++;
}

static int contained_weight(struct obj_data *container)
{
    struct obj_data                        *tmp = NULL;
    int                                     rval = 0;

    if (DEBUG > 2)
	log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_ONAME(container));

    for (tmp = container->contains; tmp; tmp = tmp->next_content)
	rval += GET_OBJ_WEIGHT(tmp);
    return rval;
}

/* Destroy inventory after transferring it to "store inventory" */
void obj_to_store(struct obj_data *obj, struct obj_file_u *st, struct char_data *ch, int delete)
{
    if (DEBUG > 2)
	log_info("called %s with %s, %08zx, %s, %d", __PRETTY_FUNCTION__, SAFE_ONAME(obj),
		 (size_t) st, SAFE_NAME(ch), delete);

    if (!obj)
	return;

    obj_to_store(obj->contains, st, ch, delete);
    obj_to_store(obj->next_content, st, ch, delete);

    if ((obj->obj_flags.timer < 0) && (obj->obj_flags.timer != OBJ_NOTIMER)) {
	if (delete) {
	    cprintf(ch, "You're told: '%s is just old junk, I'll throw it away for you.'\r\n",
		    obj->short_description);
	    if (obj->in_obj)
		obj_from_obj(obj);
	    obj_from_char(obj);
	    extract_obj(obj);
	}
    } else if (obj->obj_flags.cost_per_day < 0) {
	if (delete) {
	    cprintf(ch, "You're told: '%s is just old junk, I'll throw it away for you.'\r\n",
		    obj->short_description);
	    if (obj->in_obj)
		obj_from_obj(obj);
	    obj_from_char(obj);
	    extract_obj(obj);
	}
    } else if (obj->item_number == -1) {
	if (delete) {
	    if (obj->in_obj)
		obj_from_obj(obj);
	    obj_from_char(obj);
	    extract_obj(obj);
	}
    } else {
	int                                     weight = contained_weight(obj);

	GET_OBJ_WEIGHT(obj) -= weight;
	put_obj_in_store(obj, st);
	GET_OBJ_WEIGHT(obj) += weight;
	if (delete) {
	    if (obj->in_obj)
		obj_from_obj(obj);
	    extract_obj(obj);
	}
    }
}

/* write the vital data of a player to the player file */
void save_obj(struct char_data *ch, struct obj_cost *cost, int delete)
{
    FILE                                   *fl = NULL;
    int                                     i = 0;
    char                                    name[40] = "\0\0\0\0\0\0\0";
    char                                   *t_ptr = NULL;
    char                                    path[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    static struct obj_file_u                st;

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch),
		 (size_t) cost, delete);

    zero_rent(ch);

    st.nobjects = 0;
    st.gold_left = GET_GOLD(ch);
    st.total_cost = cost->total_cost;
    st.last_update = time(0);
    st.minimum_stay = 0;				       /* XXX where does this belong? */

    for (i = 0; i < MAX_WEAR; i++)
	if (ch->equipment[i]) {
	    if (delete) {
		obj_to_store(unequip_char(ch, i), &st, ch, delete);
	    } else {
		obj_to_store(ch->equipment[i], &st, ch, delete);
	    }
	}
    obj_to_store(ch->carrying, &st, ch, delete);

    if (delete)
	ch->carrying = 0;

    strcpy(name, GET_NAME(ch));
    t_ptr = name;
    for (; *t_ptr != '\0'; t_ptr++)
	*t_ptr = LOWER(*t_ptr);

    sprintf(path, "ply/%c/%s.o", name[0], name);
    if (!(fl = fopen(path, "w+b"))) {
	log_fatal("saving PC's objects");
	proper_exit(MUD_HALT);
    }
    update_file(fl, name, &st);
    FCLOSE(fl);
}

void fwrite_obj(struct obj_data *obj, FILE * fp, int ObjId, int ContainedBy)
{
    int                                     i = 0;
    struct extra_descr_data                *ex = NULL;

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx, %d, %d", __PRETTY_FUNCTION__, SAFE_ONAME(obj),
		 (size_t) fp, ObjId, ContainedBy);

    fprintf(fp, "#ITEM\n");
    fprintf(fp, "ObjId              %d\n", ObjId);
    fprintf(fp, "ContainedBy        %d\n", ContainedBy);
    fprintf(fp, "Name               %s~\n", obj->name);
    fprintf(fp, "Description\n%s~\n", obj->description);
    fprintf(fp, "ShortDescr\n%s~\n", obj->short_description);
    fprintf(fp, "ActionDescr\n%s~\n", obj->action_description);
    fprintf(fp, "VNum               %d\n", ObjVnum(obj));
    fprintf(fp, "EquippedAt         %d\n", (int)obj->eq_pos);
    fprintf(fp, "Values             %d %d %d %d\n", obj->obj_flags.value[0],
	    obj->obj_flags.value[1], obj->obj_flags.value[2], obj->obj_flags.value[3]);
    fprintf(fp, "ExtraFlags         %ld\n", obj->obj_flags.extra_flags);
    fprintf(fp, "Weight             %d\n", obj->obj_flags.weight);
    fprintf(fp, "Timer              %d\n", obj->obj_flags.timer);
    fprintf(fp, "BitVector          %ld\n", obj->obj_flags.bitvector);
    fprintf(fp, "Type               %d\n", (int)obj->obj_flags.type_flag);
    fprintf(fp, "WearFlags          %d\n", obj->obj_flags.wear_flags);
    fprintf(fp, "Cost               %d\n", obj->obj_flags.cost);
    fprintf(fp, "CostPerDay         %d\n", obj->obj_flags.cost_per_day);
    for (i = 0; i < MAX_OBJ_AFFECT; i++)
	fprintf(fp, "Affect             %d %d\n",
		(int)obj->affected[i].location, (int)obj->affected[i].modifier);
    for (ex = obj->ex_description; ex; ex = ex->next)
	fprintf(fp, "ExtraDescr         %s~\n%s~\n", ex->keyword, ex->description);
    fprintf(fp, "End\n");
}

int new_save_obj(struct char_data *ch, struct obj_data *obj, FILE * fp, int delete, int ObjId,
		 int ContainedBy)
{
    if (DEBUG > 2)
	log_info("called %s with %s, %s, %08zx, %d, %d, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch),
		 SAFE_ONAME(obj), (size_t) fp, delete, ObjId, ContainedBy);

    if (!obj)
	return ObjId - 1;

    ObjId = new_save_obj(ch, obj->contains, fp, delete, ObjId + 1, ObjId);
    ObjId = new_save_obj(ch, obj->next_content, fp, delete, ObjId + 1, ContainedBy);

    if ((obj->obj_flags.timer < 0) && (obj->obj_flags.timer != OBJ_NOTIMER)) {
	if (delete) {
	    cprintf(ch, "You think %s is just old junk and throw it away.\r\n", OBJS(obj, ch));
	    if (obj->in_obj)
		obj_from_obj(obj);
	    obj_from_char(obj);
	    extract_obj(obj);
	}
	return ObjId - 1;
    } else if (obj->obj_flags.cost_per_day < 0) {
	if (delete) {
	    cprintf(ch, "You think %s is just old junk and throw it away.\r\n", OBJS(obj, ch));
	    if (obj->in_obj)
		obj_from_obj(obj);
	    obj_from_char(obj);
	    extract_obj(obj);
	}
	return ObjId - 1;
    } else if (obj->item_number == -1) {
	if (delete) {
	    if (obj->in_obj)
		obj_from_obj(obj);
	    obj_from_char(obj);
	    extract_obj(obj);
	}
	return ObjId - 1;
    } else {
	int                                     weight = contained_weight(obj);

	GET_OBJ_WEIGHT(obj) -= weight;
	fwrite_obj(obj, fp, ObjId, ContainedBy);
	GET_OBJ_WEIGHT(obj) += weight;
	if (delete) {
	    if (obj->in_obj)
		obj_from_obj(obj);
	    extract_obj(obj);
	}
    }
    return ObjId;
}

void new_save_equipment(struct char_data *ch, struct obj_cost *cost, int delete)
{
    FILE                                   *fp = NULL;
    char                                    name[40] = "\0\0\0\0\0\0\0";
    char                                    filename[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    char                                   *t_ptr = NULL;
    int                                     i = 0;
    int                                     ObjId = 0;

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch),
		 (size_t) cost, delete);

    strcpy(name, GET_NAME(ch));
    t_ptr = name;
    for (; *t_ptr != '\0'; t_ptr++)
	*t_ptr = LOWER(*t_ptr);
    sprintf(filename, "ply/%c/%s.obj", name[0], name);

    zero_rent(ch);

    if (!(fp = fopen(filename, "w"))) {
	log_fatal("new_save_equipment");
	proper_exit(MUD_HALT);
    }
    fprintf(fp, "#RENT\n");
    fprintf(fp, "Owner              %s~\n", GET_NAME(ch));
    fprintf(fp, "Gold               %d\n", GET_GOLD(ch));
    fprintf(fp, "TotalCost          %d\n", cost->total_cost);
    fprintf(fp, "LastUpdate         %ld\n", (long int)time(NULL));
    fprintf(fp, "MinimumStay        0\n");
    fprintf(fp, "End\n");
    fprintf(fp, "#EQUIPMENT\n");
    ObjId = -1;
    for (i = 0; i < MAX_WEAR; i++) {
	if (ch->equipment[i]) {
	    if (delete) {
		ObjId = new_save_obj(ch, unequip_char(ch, i), fp, delete, ObjId + 1, -1);
	    } else {
		ObjId = new_save_obj(ch, ch->equipment[i], fp, delete, ObjId + 1, -1);
	    }
	}
    }
    fprintf(fp, "End\n");
    fprintf(fp, "#CARRIED\n");
    ObjId = new_save_obj(ch, ch->carrying, fp, delete, ObjId + 1, -1);
    fprintf(fp, "End\n");
    fprintf(fp, "#END_RENT\n");
    if (delete)
	ch->carrying = 0;
    FCLOSE(fp);
}

int fread_object(struct obj_data *obj, FILE * fp)
{
    int                                     fMatch = FALSE;
    int                                     done = FALSE;
    char                                   *word;
    static char                             End[4] = "End";

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx", __PRETTY_FUNCTION__, SAFE_ONAME(obj), (size_t) fp);

    for (;;) {						       /* Get equipment slot information */
	word = feof(fp) ? End : fread_word(fp);
	fMatch = FALSE;

	switch (toupper(word[0])) {
	    case '*':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;
	    case '#':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;
	    case 'E':
		if (!str_cmp(word, End)) {
		    fMatch = 1;
		    done = 1;
		    break;
		}
	}
	if (!fMatch) {
	    log_error("Fread_char: no match.");
	    if (!feof(fp))
		fread_to_eol(fp);
	}
	if (done)
	    break;
    }
    return 1;
}

int new_load_equipment(struct char_data *ch, struct obj_cost *cost)
{
    FILE                                   *fp = NULL;
    char                                    name[40] = "\0\0\0\0\0\0\0";
    char                                    filename[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";
    char                                   *t_ptr = NULL;
    static char                             End[4] = "End";

#if 0
    double                                  charges = 0.0;
    struct obj_data                        *obj = NULL;
    struct obj_indexing {
	int                                     ObjId;
	int                                     ContainedBy;
	struct obj_data                        *Myself;
	struct obj_data                        *MyContainer;
    }                                      *inventory;
    int                                     state = 0;
#endif
    int                                     fMatch = FALSE;
    int                                     done = FALSE;
    char                                   *word = NULL;

    if (DEBUG > 2)
	log_info("called %s with %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), (size_t) cost);

    strcpy(name, GET_NAME(ch));
    t_ptr = name;
    for (; *t_ptr != '\0'; t_ptr++)
	*t_ptr = LOWER(*t_ptr);
    sprintf(filename, "ply/%c/%s.obj", name[0], name);
    if (!(fp = fopen(filename, "r"))) {
	log_info("%s has no rental history!", GET_NAME(ch));
	if (!(fp = fopen(filename, "w"))) {
	    log_fatal("new_load_equipment");
	    proper_exit(MUD_HALT);
	}
	fprintf(fp, "#RENT\n");
	fprintf(fp, "Owner              %s~\n", GET_NAME(ch));
	fprintf(fp, "Gold               %d\n", GET_GOLD(ch));
	fprintf(fp, "TotalCost          %d\n", 0);
	fprintf(fp, "LastUpdate         %ld\n", (long int)time(NULL));
	fprintf(fp, "MinimumStay        0\n");
	fprintf(fp, "End\n");
	fprintf(fp, "#EQUIPMENT\n");
	fprintf(fp, "End\n");
	fprintf(fp, "#CARRIED\n");
	fprintf(fp, "End\n");
	fprintf(fp, "#END_RENT\n");
	FCLOSE(fp);
	return -1;
    }
    done = 0;
    for (;;) {						       /* Get rental information */
	word = feof(fp) ? End : fread_word(fp);
	fMatch = FALSE;

	switch (toupper(word[0])) {
	    case '*':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;
	    case '#':
		fMatch = TRUE;
		fread_to_eol(fp);
		break;
	    case 'E':
		if (!str_cmp(word, End)) {
		    fMatch = 1;
		    done = 1;
		    break;
		}
	    case 'G':
		if (!str_cmp(word, "Gold")) {
		    fMatch = TRUE;
		    GET_GOLD(ch) = fread_number(fp);
		    break;
		}
	    case 'L':
		if (!str_cmp(word, "LastUpdate")) {
		    fMatch = TRUE;
		    fread_number(fp);
		    break;
		}
	    case 'M':
		if (!str_cmp(word, "MinimumStay")) {
		    fMatch = TRUE;
		    fread_number(fp);
		    break;
		}
	    case 'O':
		if (!str_cmp(word, "Owner")) {
		    fMatch = TRUE;
		    word = fread_word(fp);
		    if (!str_cmp(word, name))
			log_info("%s loading %s's equipment!", name, word);
		    break;
		}
	    case 'T':
		if (!str_cmp(word, "TotalCost")) {
		    fMatch = TRUE;
		    cost->total_cost = fread_number(fp);
		    break;
		}
	}
	if (!fMatch) {
	    log_error("Fread_char: no match.");
	    if (!feof(fp))
		fread_to_eol(fp);
	}
	if (done)
	    break;
    }
    /*
     * we've now gotten the rental header.... now we have to get the stuff 
     */
    return 0;
}

/*
 * Routine Receptionist
 */

int receptionist(struct char_data *ch, int cmd, char *arg)
{
    struct obj_cost                         cost;
    struct char_data                       *recep = NULL;
    struct char_data                       *temp_char = NULL;
    short int                               save_room = 0;
    short int                               action_tabel[9] =
	{ 23, 24, 36, 105, 106, 109, 111, 142, 147 };

    if (DEBUG > 2)
	log_info("called %s with %s, %d, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), cmd,
		 VNULL(arg));

    if (!ch->desc)
	return (FALSE);					       /* You've forgot FALSE - NPC couldn't leave */

    for (temp_char = real_roomp(ch->in_room)->people; (temp_char) && (!recep);
	 temp_char = temp_char->next_in_room)
	if (IS_MOB(temp_char))
	    if (mob_index[temp_char->nr].func == receptionist)
		recep = temp_char;

    if (!recep) {
	log_fatal("No receptionist.\r\n");
	proper_exit(MUD_HALT);
    }
    if (IS_NPC(ch))
	return (FALSE);

    if ((cmd != 256) && (cmd != 92) && (cmd != 93)) {
	if (!cmd) {
	    if (recep->specials.fighting) {
		return (citizen(recep, 0, ""));
	    }
	}
	if (!number(0, 30))
	    do_action(recep, "", action_tabel[number(0, 8)]);
	return (FALSE);
    }
    if (!AWAKE(recep)) {
	act("$e isn't able to talk to you...", FALSE, recep, 0, ch, TO_VICT);
	return (TRUE);
    }
    if (!CAN_SEE(recep, ch)) {
	act("$n says, 'I don't deal with people I can't see!'", FALSE, recep, 0, 0, TO_ROOM);
	return (TRUE);
    }
    switch (cmd) {
	case 92:
	    {						       /* Rent */
		if (recep_offer(ch, recep, &cost)) {
		    GET_HOME(ch) = ch->in_room;
		    cprintf(ch, "Your home has been set to this room, %s\r\n",
			    real_roomp(ch->in_room)->name);

		    act("$n stores your stuff in the safe, and helps you into your chamber.",
			FALSE, recep, 0, ch, TO_VICT);
		    act("$n helps $N into $S private chamber.", FALSE, recep, 0, ch,
			TO_NOTVICT);

		    new_save_equipment(ch, &cost, FALSE);
		    save_obj(ch, &cost, 1);
		    save_room = ch->in_room;
		    extract_char(ch);
		    ch->in_room = save_room;
		    save_char(ch, ch->in_room);
		}
	    }
	    break;
	case 93:
	    {						       /* Offer */
		recep_offer(ch, recep, &cost);
		act("$N gives $n an offer.", FALSE, ch, 0, recep, TO_ROOM);
	    }
	    break;
	case 256:
	    {						       /* sethome */
		GET_HOME(ch) = ch->in_room;
		save_char(ch, ch->in_room);
		cprintf(ch, "Your home has been set to this room, %s\r\n",
			real_roomp(ch->in_room)->name);
	    }
	    break;
    }
    return (TRUE);
}

/* removes a player from the list of renters */
void zero_rent(struct char_data *ch)
{
    struct rental_header                    rh;
    FILE                                   *fl = NULL;
    char                                    name[40] = "\0\0\0\0\0\0\0";
    char                                   *t_ptr = NULL;
    char                                    path[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0";

    if (DEBUG > 2)
	log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(ch));

    if (IS_NPC(ch))
	return;

    strcpy(name, GET_NAME(ch));
    t_ptr = name;
    for (; *t_ptr != '\0'; t_ptr++)
	*t_ptr = LOWER(*t_ptr);
    sprintf(path, "ply/%c/%s.o", name[0], name);
    if (!(fl = fopen(path, "w+b"))) {
	log_fatal("saving PC's objects");
	proper_exit(MUD_HALT);
    }
    rh.inuse = 0;
    fwrite(&rh, sizeof(rh), 1, fl);
    FCLOSE(fl);
    return;
}

/*
 * This is for future use.  Right now, weights are pre-calculated so the
 * weight of a container IS the weight of itself plus all interior objects.
 * Later, to avoid cup problems, we may change it so you must query the
 * total weight of an object by summing the individual weights.
 */
int TotalWeight(struct obj_data *obj)
{
    struct obj_data                        *tmp = NULL;
    int                                     rval = 0;

    if (DEBUG > 2)
	log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_ONAME(obj));

    if (!obj)
	return 0;
    rval = GET_OBJ_WEIGHT(obj);
    for (tmp = obj->contains; tmp; tmp = tmp->next_content)
	rval += TotalWeight(tmp);
    return rval;
}