alanthia/area/
alanthia/gods/
alanthia/player/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  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.                                                  *
 ***************************************************************************/

/***************************************************************************
*	ROM 2.4 is copyright 1993-1996 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@efn.org)				   *
*	    Gabrielle Taylor						   *
*	    Brian Moore (zump@rom.org)					   *
*	By using this code, you have agreed to follow the terms of the	   *
*	ROM license, in the file Rom24/doc/rom.license			   *
***************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif

#include "merc.h"
#include "utils.h"
#include "db.h"
#include "lookup.h"

#include "tables.h"
/* values for db2.c */
extern int flag_lookup
args((const char *name, const struct flag_type * flag_table));
struct social_type social_table[MAX_SOCIALS];
int social_count;

/* snarf a socials file */
void load_socials(FILE * fp)
{
    for (;;) {
	struct social_type social;
	char *temp;
	/* clear social */
	social.char_no_arg = NULL;
	social.others_no_arg = NULL;
	social.char_found = NULL;
	social.others_found = NULL;
	social.vict_found = NULL;
	social.char_not_found = NULL;
	social.char_auto = NULL;
	social.others_auto = NULL;

	temp = fread_word(fp);
	if (!strcmp(temp, "#0"))
	    return;		/* done */
#if defined(social_debug)
	else
	    fprintf(stderr, "%s\n\r", temp);
#endif

	strcpy(social.name, temp);
	fread_to_eol(fp);

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.char_no_arg = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.char_no_arg = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.others_no_arg = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.others_no_arg = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.char_found = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.char_found = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.others_found = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.others_found = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.vict_found = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.vict_found = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.char_not_found = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.char_not_found = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.char_auto = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.char_auto = temp;

	temp = fread_string_eol(fp);
	if (!strcmp(temp, "$"))
	    social.others_auto = NULL;
	else if (!strcmp(temp, "#")) {
	    social_table[social_count] = social;
	    social_count++;
	    continue;
	} else
	    social.others_auto = temp;

	social_table[social_count] = social;
	social_count++;
    }
    return;
}






/*
 * Snarf a mob section.  new style
 */
void load_mobiles(FILE * fp)
{
    MOB_INDEX_DATA *pMobIndex;

    if (!area_last) {		/* OLC */
	bug("Load_mobiles: no #AREA seen yet.", 0);
	exit(1);
    }
    for (;;) {
	long vnum;
	char letter;
	int iHash;

	letter = fread_letter(fp);
	if (letter != '#') {
	    bug("Load_mobiles: # not found.", 0);
	    exit(1);
	}
	vnum = fread_number(fp);
	if (vnum == 0)
	    break;

	fBootDb = FALSE;
	if (get_mob_index(vnum) != NULL) {
	    bug("Load_mobiles: vnum %d duplicated.", vnum);
	    exit(1);
	}
	fBootDb = TRUE;

	pMobIndex = alloc_perm(sizeof(*pMobIndex));
	pMobIndex->vnum = vnum;
	pMobIndex->area = area_last;	/* OLC */
	pMobIndex->new_format = TRUE;
	newmobs++;
	pMobIndex->player_name = fread_string(fp);
	pMobIndex->short_descr = fread_string(fp);
	pMobIndex->long_descr = fread_string(fp);
	pMobIndex->description = fread_string(fp);

	pMobIndex->race = race_lookup(fread_string(fp));

	pMobIndex->long_descr[0] = UPPER(pMobIndex->long_descr[0]);
	pMobIndex->description[0] = UPPER(pMobIndex->description[0]);

	pMobIndex->act = fread_flag(fp) | ACT_IS_NPC
	    | pMobIndex->race->act;
	pMobIndex->affected_by = fread_flag(fp)
	    | pMobIndex->race->aff;
	pMobIndex->pShop = NULL;
	pMobIndex->alignment = fread_number(fp);
	pMobIndex->group = fread_number(fp);

	pMobIndex->level = fread_number(fp);

	pMobIndex->hitroll = fread_number(fp);




	/* read hit dice */
	pMobIndex->hit[DICE_NUMBER] = fread_number(fp);
	/* 'd'          */ fread_letter(fp);
	pMobIndex->hit[DICE_TYPE] = fread_number(fp);
	/* '+'          */ fread_letter(fp);
	pMobIndex->hit[DICE_BONUS] = fread_number(fp);

	/* read mana dice */
	pMobIndex->mana[DICE_NUMBER] = fread_number(fp);
	fread_letter(fp);
	pMobIndex->mana[DICE_TYPE] = fread_number(fp);
	fread_letter(fp);
	pMobIndex->mana[DICE_BONUS] = fread_number(fp);

	/* read damage dice */
	pMobIndex->damage[DICE_NUMBER] = fread_number(fp);
	fread_letter(fp);
	pMobIndex->damage[DICE_TYPE] = fread_number(fp);
	fread_letter(fp);
	pMobIndex->damage[DICE_BONUS] = fread_number(fp);
	pMobIndex->dam_type = attack_lookup(fread_word(fp));

	/* read armor class */
	pMobIndex->ac[AC_PIERCE] = fread_number(fp) * 10;
	pMobIndex->ac[AC_BASH] = fread_number(fp) * 10;
	pMobIndex->ac[AC_SLASH] = fread_number(fp) * 10;
	pMobIndex->ac[AC_EXOTIC] = fread_number(fp) * 10;

	/* read flags and add in data from the race table */
	pMobIndex->off_flags = fread_flag(fp)
	    | pMobIndex->race->off;
	pMobIndex->imm_flags = fread_flag(fp)
	    | pMobIndex->race->imm;
	pMobIndex->res_flags = fread_flag(fp)
	    | pMobIndex->race->res;
	pMobIndex->vuln_flags = fread_flag(fp)
	    | pMobIndex->race->vuln;

	/* vital statistics */
	pMobIndex->start_pos = position_lookup(fread_word(fp));
	pMobIndex->default_pos = position_lookup(fread_word(fp));
	pMobIndex->sex = sex_lookup(fread_word(fp));

	pMobIndex->wealth = fread_number(fp);

	pMobIndex->form = fread_flag(fp)
	    | pMobIndex->race->form;
	pMobIndex->parts = fread_flag(fp)
	    | pMobIndex->race->parts;
	/* size */
	pMobIndex->size = size_lookup(fread_word(fp));
	pMobIndex->material = str_dup(fread_word(fp));

	for (;;) {
	    letter = fread_letter(fp);

	    if (letter == 'F') {
		char *word;
		long vector;

		word = fread_word(fp);
		vector = fread_flag(fp);

		if (!str_prefix(word, "act"))
		    REMOVE_BIT(pMobIndex->act, vector);
		else if (!str_prefix(word, "aff"))
		    REMOVE_BIT(pMobIndex->affected_by, vector);
		else if (!str_prefix(word, "off"))
		    REMOVE_BIT(pMobIndex->off_flags, vector);
		else if (!str_prefix(word, "imm"))
		    REMOVE_BIT(pMobIndex->imm_flags, vector);
		else if (!str_prefix(word, "res"))
		    REMOVE_BIT(pMobIndex->res_flags, vector);
		else if (!str_prefix(word, "vul"))
		    REMOVE_BIT(pMobIndex->vuln_flags, vector);
		else if (!str_prefix(word, "for"))
		    REMOVE_BIT(pMobIndex->form, vector);
		else if (!str_prefix(word, "par"))
		    REMOVE_BIT(pMobIndex->parts, vector);
		else {
		    bug("Flag remove: flag not found.", 0);
		    exit(1);
		}
	    } else if (letter == 'M') {
		MPROG_LIST *pMprog;
		char *word;
		int trigger = 0;

		pMprog = alloc_perm(sizeof(*pMprog));
		word = fread_word(fp);
		if (!(trigger = flag_lookup(word, mprog_flags))) {
		    bug("MOBprogs: invalid trigger.", 0);
		    exit(1);
		}
		SET_BIT(pMobIndex->mprog_flags, trigger);
		pMprog->trig_type = trigger;
		pMprog->vnum = fread_number(fp);
		pMprog->trig_phrase = fread_string(fp);
		pMprog->next = pMobIndex->mprogs;
		pMobIndex->mprogs = pMprog;
	    } else {
		ungetc(letter, fp);
		break;
	    }
	}


	iHash = vnum % MAX_KEY_HASH;
	pMobIndex->next = mob_index_hash[iHash];
	mob_index_hash[iHash] = pMobIndex;
	top_mob_index++;
	top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob;	/* OLC */
	assign_area_vnum(vnum);	/* OLC */
	kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL - 1)].number++;
    }

    return;
}

/*
 * Snarf an obj section. new style
 */
void load_objects(FILE * fp)
{
    OBJ_INDEX_DATA *pObjIndex;

    if (!area_last) {		/* OLC */
	bug("Load_objects: no #AREA seen yet.", 0);
	exit(1);
    }
    for (;;) {
	long vnum;
	char letter;
	int iHash;

	letter = fread_letter(fp);
	if (letter != '#') {
	    bug("Load_objects: # not found.", 0);
	    exit(1);
	}
	vnum = fread_number(fp);
	if (vnum == 0)
	    break;

	fBootDb = FALSE;
	if (get_obj_index(vnum) != NULL) {
	    bug("Load_objects: vnum %d duplicated.", vnum);
	    exit(1);
	}
	fBootDb = TRUE;

	pObjIndex = alloc_perm(sizeof(*pObjIndex));
	pObjIndex->vnum = vnum;
	pObjIndex->area = area_last;	/* OLC */
	pObjIndex->new_format = TRUE;
	pObjIndex->reset_num = 0;
	newobjs++;
	pObjIndex->name = fread_string(fp);
	pObjIndex->short_descr = fread_string(fp);
	pObjIndex->description = fread_string(fp);
	pObjIndex->material = fread_string(fp);

	pObjIndex->item_type = item_lookup(fread_word(fp));
	pObjIndex->extra_flags = fread_flag(fp);
	pObjIndex->wear_flags = fread_flag(fp);
	switch (pObjIndex->item_type) {
	case ITEM_WEAPON:
	    pObjIndex->value[0] = weapon_type(fread_word(fp));
	    pObjIndex->value[1] = fread_number(fp);
	    pObjIndex->value[2] = fread_number(fp);
	    pObjIndex->value[3] = attack_lookup(fread_word(fp));
	    pObjIndex->value[4] = fread_flag(fp);
	    break;
	case ITEM_CONTAINER:
	    pObjIndex->value[0] = fread_number(fp);
	    pObjIndex->value[1] = fread_flag(fp);
	    pObjIndex->value[2] = fread_number(fp);
	    pObjIndex->value[3] = fread_number(fp);
	    pObjIndex->value[4] = fread_number(fp);
	    break;
	case ITEM_DRINK_CON:
	case ITEM_BLOOD_CON:
	case ITEM_FOUNTAIN:
	    pObjIndex->value[0] = fread_number(fp);
	    pObjIndex->value[1] = fread_number(fp);
	    pObjIndex->value[2] = liq_lookup(fread_word(fp));
	    pObjIndex->value[3] = fread_number(fp);
	    pObjIndex->value[4] = fread_number(fp);

	    if (pObjIndex->value[2] == -1)
		pObjIndex->value[2] = 0;

	    break;
	case ITEM_WAND:
	case ITEM_STAFF:
	    pObjIndex->value[0] = fread_number(fp);
	    pObjIndex->value[1] = fread_number(fp);
	    pObjIndex->value[2] = fread_number(fp);
	    pObjIndex->value[3] = skill_lookup(fread_word(fp));
/*
		if (pObjIndex->value[3] == -1) {
		pObjIndex->value[3] = skill_lookup("bolt");
		}
*/
	    pObjIndex->value[4] = fread_number(fp);
	    break;
	case ITEM_POTION:
	case ITEM_PILL:
	case ITEM_SCROLL:
	    pObjIndex->value[0] = fread_number(fp);
	    pObjIndex->value[1] = skill_lookup(fread_word(fp));
	    pObjIndex->value[2] = skill_lookup(fread_word(fp));
	    pObjIndex->value[3] = skill_lookup(fread_word(fp));
	    pObjIndex->value[4] = skill_lookup(fread_word(fp));
	    break;
	default:
	    pObjIndex->value[0] = fread_flag(fp);
	    pObjIndex->value[1] = fread_flag(fp);
	    pObjIndex->value[2] = fread_flag(fp);
	    pObjIndex->value[3] = fread_flag(fp);
	    pObjIndex->value[4] = fread_flag(fp);
	    break;
	}
	pObjIndex->level = fread_number(fp);
	if (pObjIndex->level < 1)
	    pObjIndex->level = 1;

	pObjIndex->weight = fread_number(fp);
	pObjIndex->cost = fread_number(fp);
	pObjIndex->timer = fread_number(fp);

	if ((pObjIndex->item_type == ITEM_ARMOR
	     || pObjIndex->item_type == ITEM_WEAPON)
	    && (pObjIndex->cost > pObjIndex->level * 25)
	    && (pObjIndex->vnum < 6700 && pObjIndex->vnum > 6799))
	    pObjIndex->cost = pObjIndex->level * 25;


	if (0) {
	    pObjIndex->cost = pObjIndex->level * 4;

	    switch (pObjIndex->item_type) {
	    case ITEM_WEAPON:
		switch (pObjIndex->value[0]) {
		case WEAPON_EXOTIC:
		case WEAPON_WHIP:
		case WEAPON_DAGGER:
		    pObjIndex->value[1] = pObjIndex->level / 4 + 1;
		    pObjIndex->value[2] = pObjIndex->level / 6 + 1;
		    /* Need to evaluate flags. pObjIndex->value[4];  */
		    pObjIndex->cost *=
			((pObjIndex->value[1] / 2) +
			 (pObjIndex->value[2] / 2));
		    pObjIndex->weight = pObjIndex->level * 3;
		    break;
		case WEAPON_SWORD:
		case WEAPON_AXE:
		    pObjIndex->value[1] = pObjIndex->level / 8 + 1;
		    pObjIndex->value[2] = pObjIndex->level / 12 + 1;
		    /* Need to evaluate flags. pObjIndex->value[4];  */
		    pObjIndex->cost *=
			((pObjIndex->value[1] / 2) +
			 (pObjIndex->value[2] / 2));
		    pObjIndex->weight = pObjIndex->level * 3;
		    break;
		case WEAPON_SPEAR:
		case WEAPON_POLEARM:
		    pObjIndex->value[1] = pObjIndex->level / 6 + 1;
		    pObjIndex->value[2] = pObjIndex->level / 11 + 1;
		    /* Need to evaluate flags. pObjIndex->value[4];  */
		    pObjIndex->cost *=
			((pObjIndex->value[1] / 2) +
			 (pObjIndex->value[2] / 2));
		    pObjIndex->weight = pObjIndex->level * 3;
		    break;
		case WEAPON_MACE:
		case WEAPON_FLAIL:
		    pObjIndex->value[1] = pObjIndex->level / 7 + 1;
		    pObjIndex->value[2] = pObjIndex->level / 10 + 1;
		    /* Need to evaluate flags. pObjIndex->value[4];  */
		    pObjIndex->cost *=
			((pObjIndex->value[1] / 2) +
			 (pObjIndex->value[2] / 2));
		    pObjIndex->weight = pObjIndex->level * 3;
		    break;
		default:
		    pObjIndex->value[1] = pObjIndex->level / 4 + 1;
		    pObjIndex->value[2] = pObjIndex->level / 6 + 1;
		    /* Need to evaluate flags. pObjIndex->value[4];  */
		    pObjIndex->cost *=
			((pObjIndex->value[1] / 2) +
			 (pObjIndex->value[2] / 2));
		    pObjIndex->weight = pObjIndex->level * 3;
		    break;
		}
		break;
	    case ITEM_CONTAINER:
		pObjIndex->value[0] = pObjIndex->level / 5 + 1;
		pObjIndex->value[3] = pObjIndex->level * 3;
		pObjIndex->value[4] = 100;
		pObjIndex->cost += pObjIndex->level;
		break;

	    case ITEM_DRINK_CON:
	    case ITEM_BLOOD_CON:
		pObjIndex->value[0] = pObjIndex->level;
		pObjIndex->value[1] = pObjIndex->level;
		pObjIndex->cost += pObjIndex->level;
		break;

	    case ITEM_WAND:
	    case ITEM_STAFF:
		pObjIndex->value[0] = pObjIndex->level;
		pObjIndex->value[1] = pObjIndex->level / 10 + 1;
		pObjIndex->value[2] = pObjIndex->level / 10 + 1;
		pObjIndex->cost += pObjIndex->level * pObjIndex->value[2];
		pObjIndex->weight = pObjIndex->level * 4 / 3;
		break;

	    case ITEM_POTION:
	    case ITEM_PILL:
	    case ITEM_SCROLL:
		pObjIndex->value[0] = pObjIndex->level;
		if (pObjIndex->level < 51)
		    pObjIndex->value[3] = -1;
		if (pObjIndex->level < 101)
		    pObjIndex->value[4] = -1;
		break;

	    case ITEM_ARMOR:
		pObjIndex->value[0] = pObjIndex->level / 3;
		pObjIndex->value[1] = pObjIndex->level / 3;
		pObjIndex->value[2] = pObjIndex->level / 3;
		pObjIndex->cost += pObjIndex->level * pObjIndex->value[2];
		pObjIndex->weight = pObjIndex->level * 4 / 3;
		break;

	    case ITEM_LIGHT:
		pObjIndex->value[2] = pObjIndex->level * 10;
		pObjIndex->cost = pObjIndex->level * 5;
		pObjIndex->weight = pObjIndex->level * 4 / 3;
		break;

	    case ITEM_FOOD:
		pObjIndex->value[0] = number_range(1, 24);
		pObjIndex->value[1] = 0;
		pObjIndex->cost = pObjIndex->value[0] * 5;
		pObjIndex->weight = pObjIndex->value[0];
		pObjIndex->level = 1;
		break;

	    case ITEM_JEWELRY:
	    case ITEM_TREASURE:
	    case ITEM_GEM:
		pObjIndex->cost = pObjIndex->level * 20;
		pObjIndex->weight = pObjIndex->level;
		pObjIndex->level = 1;
		break;

	    default:
		pObjIndex->cost = pObjIndex->level + 1;
		pObjIndex->weight = pObjIndex->level * 4 / 3;
		break;
	    }
	}
	/* condition */
	letter = fread_letter(fp);
	switch (letter) {
	case ('P'):
	    pObjIndex->condition = 100;
	    break;
	case ('G'):
	    pObjIndex->condition = 90;
	    break;
	case ('A'):
	    pObjIndex->condition = 75;
	    break;
	case ('W'):
	    pObjIndex->condition = 50;
	    break;
	case ('D'):
	    pObjIndex->condition = 25;
	    break;
	case ('B'):
	    pObjIndex->condition = 10;
	    break;
	case ('R'):
	    pObjIndex->condition = 0;
	    break;
	default:
	    pObjIndex->condition = 100;
	    break;
	}

	for (;;) {
	    char letter;

	    letter = fread_letter(fp);

	    if (letter == 'A') {
		AFFECT_DATA *paf;

		paf = alloc_perm(sizeof(*paf));
		paf->where = TO_OBJECT;
		paf->type = -1;
		paf->level = pObjIndex->level;
		paf->duration = -1;
		paf->location = fread_number(fp);
		paf->modifier = fread_number(fp);
		paf->bitvector = 0;
		paf->next = pObjIndex->affected;
		pObjIndex->affected = paf;
		top_affect++;
	    } else if (letter == 'F') {
		AFFECT_DATA *paf;

		paf = alloc_perm(sizeof(*paf));
		letter = fread_letter(fp);
		switch (letter) {
		case 'A':
		    paf->where = TO_AFFECTS;
		    break;
		case 'I':
		    paf->where = TO_IMMUNE;
		    break;
		case 'R':
		    paf->where = TO_RESIST;
		    break;
		case 'V':
		    paf->where = TO_VULN;
		    break;
		default:
		    bug("Load_objects: Bad where on flag set.", 0);
		    exit(1);
		}
		paf->type = -1;
		paf->level = pObjIndex->level;
		paf->duration = -1;
		paf->location = fread_number(fp);
		paf->modifier = fread_number(fp);
		paf->bitvector = fread_flag(fp);
		paf->next = pObjIndex->affected;
		pObjIndex->affected = paf;
		top_affect++;
	    } else if (letter == 'E') {
		EXTRA_DESCR_DATA *ed;

		ed = alloc_perm(sizeof(*ed));
		ed->keyword = fread_string(fp);
		ed->description = fread_string(fp);
		ed->next = pObjIndex->extra_descr;
		pObjIndex->extra_descr = ed;
		top_ed++;
	    } else {
		ungetc(letter, fp);
		break;
	    }
	}

	iHash = vnum % MAX_KEY_HASH;
	pObjIndex->next = obj_index_hash[iHash];
	obj_index_hash[iHash] = pObjIndex;
	top_obj_index++;
	top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj;	/* OLC */
	assign_area_vnum(vnum);	/* OLC */
    }

    return;
}