/
lib/objects/
lib/rooms/
lib/scripts/
lib/security/
src/banner/
src/util/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/file.h>


#include "protos.h"

/* move to protos.h later */

int SetDefaultLang(struct char_data *ch);

/* end moves */


void log_sev(char *s, int i);
void log (char *s) { log_sev(s, 1); }
extern long SystemFlags;
extern struct time_data time_info;
extern struct descriptor_data *descriptor_list;
extern struct char_data *character_list;
extern struct index_data *mob_index, *obj_index;
extern struct chr_app_type chr_apply[];
extern struct zone_data *zone_table;
#if HASH
extern struct hash_header room_db;	                  /* In db.c */
#else
extern struct room_data *room_db[];	                  /* In db.c */
#endif
extern char *dirs[]; 
extern int  RacialMax[][MAX_CLASS];
extern int top_of_zone_table;
extern int top_of_world;
extern struct descriptor_data *descriptor_list;

/* external functions */
void stop_fighting(struct char_data *ch);
void fake_setup_dir(FILE *fl, long room, int dir);
char *fread_string(FILE *fl);
int check_falling(struct char_data *ch);
void NailThisSucker( struct char_data *ch);

/* interal move to protos.h */
int IS_UNDERGROUND(struct char_data *ch);


#if EGO
int EgoBladeSave(struct char_data *ch)
{
   int total;
   
   if (GetMaxLevel(ch) <= 10) return(FALSE);
   total = (GetMaxLevel(ch) + GET_STR(ch) + GET_CON(ch));
   if (GET_HIT(ch) == 0) return(FALSE);
   total = total - (GET_MAX_HIT(ch) / GET_HIT(ch));
   if (number(1,101) > total) {
      return(FALSE);
   } else return(TRUE);
}
#endif

int MIN(int a, int b)
{
	return a < b ? a:b;
}


int MAX(int a, int b)
{
	return a > b ? a:b;
}

int GetItemClassRestrictions(struct obj_data *obj)
{
  int total=0;

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_MAGE)) {
    total += CLASS_MAGIC_USER;
  }
  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_THIEF)) {
    total += CLASS_THIEF;
  }
  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_FIGHTER)) {
    total += CLASS_WARRIOR;
  }
  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_CLERIC)) {
    total += CLASS_CLERIC;
  }

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_BARBARIAN)) {
    total += CLASS_BARBARIAN;
  }

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_RANGER)) {
    total += CLASS_RANGER;
  }

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_PALADIN)) {
    total += CLASS_PALADIN;
  }

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_PSI)) {
    total += CLASS_PSI;
  }

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_MONK)) {
    total += CLASS_MONK;
  }

  if (IS_SET(obj->obj_flags.extra_flags, ITEM_ANTI_DRUID)) {
    total += CLASS_DRUID;
  }

  return(total);

}

int CAN_SEE(struct char_data *s, struct char_data *o)
{

  if (!o || s->in_room <= 0 || o->in_room <= 0){
    return(FALSE);
    }


  if (o->invis_level > GetMaxLevel(s))  
    return FALSE;                       

  if (IS_IMMORTAL(s)) 
    return(TRUE);

  if (IS_AFFECTED(s, AFF_TRUE_SIGHT))
    return(TRUE);

  if (IS_AFFECTED(s, AFF_BLIND) || IS_AFFECTED(o, AFF_HIDE))
    return(FALSE);

  if (IS_AFFECTED(o, AFF_INVISIBLE)) {
    if (IS_IMMORTAL(o))
      return(FALSE);
    if (!IS_AFFECTED(s, AFF_DETECT_INVISIBLE))
      return(FALSE);
  }

  if ((IS_DARK(s->in_room) || IS_DARK(o->in_room)) &&
        (!IS_AFFECTED(s, AFF_INFRAVISION)))
        return(FALSE);

  if (IS_AFFECTED2(o, AFF2_ANIMAL_INVIS) && IsAnimal(s))
    return(FALSE);

  return(TRUE);
}

int CAN_SEE_OBJ( struct char_data *ch, struct obj_data *obj)
{
int num=0;

  if (IS_IMMORTAL(ch))
    return(1);
  


/* changed the act.info.c, hope this works on traps INSIDE chests etc.. */
/* msw */

#if 1
if ((ITEM_TYPE(obj) == ITEM_TRAP) && (GET_TRAP_CHARGES(obj) > 0)) 
	{
	num = number(1,101);
         if (CanSeeTrap(num,ch))  {
	     return(TRUE);
	   } else return(FALSE);
        } /* not a trap */
#endif

  if (IS_AFFECTED(ch, AFF_TRUE_SIGHT))
    return(1);


  if (IS_DARK(ch->in_room) && !IS_OBJ_STAT(obj, ITEM_GLOW))
    return(0);

  if (IS_AFFECTED(ch, AFF_BLIND))
    return(0);

  if (IS_AFFECTED(ch, AFF_DETECT_INVISIBLE))
    return(1);

  if (IS_OBJ_STAT(obj, ITEM_INVISIBLE))
    return(0);

  return(1);
}

int exit_ok(struct room_direction_data	*exit, struct room_data **rpp)
{
  struct room_data	*rp;
  if (rpp==NULL)
    rpp = &rp;
  if (!exit) {
    *rpp = NULL;
    return FALSE;
  }
  *rpp = real_roomp(exit->to_room);
  return (*rpp!=NULL);
}

long MobVnum( struct char_data *c)
{
  if (IS_NPC(c)) {
    return(mob_index[c->nr].virtual);
  } else {
    return(0);
  }
}

long ObjVnum( struct obj_data *o)
{
  if (o->item_number >= 0)
     return(obj_index[o->item_number].virtual);
  else
    return(-1);
}


void Zwrite (FILE *fp, char cmd, int tf, int arg1, int arg2, int arg3, 
	     char *desc)
{
   char buf[100];

   if (*desc) {
     sprintf(buf, "%c %d %d %d %d   ; %s\n", cmd, tf, arg1, arg2, arg3, desc);
     fputs(buf, fp);
   } else {
     sprintf(buf, "%c %d %d %d %d\n", cmd, tf, arg1, arg2, arg3); 
     fputs(buf, fp);
   }
}

void RecZwriteObj(FILE *fp, struct obj_data *o)
{
   struct obj_data *t;

   if (ITEM_TYPE(o) == ITEM_CONTAINER) {
     for (t = o->contains; t; t=t->next_content) {
       Zwrite(fp, 'P', 1, ObjVnum(t), obj_index[t->item_number].number, ObjVnum(o), 
	      t->short_description);
       RecZwriteObj(fp, t);
     }
   } else {
     return;
   }
}

 
int SaveZoneFile(FILE *fp, int start_room, int end_room)
{
  struct char_data *p;
  struct obj_data *o;
  struct room_data *room;
  char cmd, c, buf[80];
  int i, j, arg1, arg2, arg3;
 
 
  for (i = start_room; i<=end_room; i++) {
    room = real_roomp(i);
    if (room) {
      /*
       *  first write out monsters
       */
      for (p = room->people; p; p = p->next_in_room) {
        if (IS_NPC(p)) {
          cmd = 'M';
          arg1 = MobVnum(p);
          arg2 = mob_index[p->nr].number;
          arg3 = i;
          Zwrite(fp, cmd, 0, arg1, arg2, arg3, p->player.short_descr);
          for (j = 0; j<MAX_WEAR; j++) {
            if (p->equipment[j]) {
              if (p->equipment[j]->item_number >= 0) {
                cmd = 'E';
                arg1 = ObjVnum(p->equipment[j]);
                arg2 = obj_index[p->equipment[j]->item_number].number;
                arg3 = j;
                strcpy(buf, p->equipment[j]->short_description);
                Zwrite(fp, cmd,1,arg1, arg2, arg3, 
                       buf);
                RecZwriteObj(fp, p->equipment[j]);
              }
            }
          }
          for (o = p->carrying; o; o=o->next_content) {
            if (o->item_number >= 0) {
              cmd = 'G';
              arg1 = ObjVnum(o);
              arg2 = obj_index[o->item_number].number;
              arg3 = 0;
              strcpy(buf, o->short_description);
              Zwrite(fp, cmd, 1, arg1, arg2, arg3, buf);
              RecZwriteObj(fp, o);
            }
          }
        }
      }
      /*
       *  write out objects in rooms
       */
      for (o = room->contents; o; o= o->next_content) {
        if (o->item_number >= 0) {
          cmd = 'O';
          arg1 = ObjVnum(o);
          arg2 = obj_index[o->item_number].number;
          arg3 = i;
          strcpy(buf, o->short_description);
          Zwrite(fp, cmd, 0, arg1, arg2, arg3, buf);
          RecZwriteObj(fp, o);
        }
      }
      /*
       *  lastly.. doors
       */
 
      for (j = 0; j < 6; j++) {
        /*
         *  if there is an door type exit, write it.
         */
        if (room->dir_option[j]) {  /* is a door */
          if (room->dir_option[j]->exit_info) {
            cmd = 'D';
            arg1 = i ;
            arg2 = j;
            arg3 = 0;
            if (IS_SET(room->dir_option[j]->exit_info, EX_CLOSED)) {
              arg3 = 1;
            }
            if (IS_SET(room->dir_option[j]->exit_info, EX_LOCKED)) {
              arg3 = 2;
            }
            Zwrite(fp, cmd, 0, arg1, arg2, arg3, room->name);
          }
        }
      }
    }
  }
  fprintf(fp,"S\n");
return 1;
}
 
 
int LoadZoneFile(FILE *fl, int zon)
{
  int cmd_no = 0, expand, tmp, cc = 22;
  char *check, buf[81];
 
  if(zone_table[zon].cmd) {
    free(zone_table[zon].cmd);
  }
 
  /* read the command table */
  cmd_no = 0;
  for (expand = 1;!feof(fl);)          {
    if (expand) {
      if (!cmd_no)
        CREATE(zone_table[zon].cmd, struct reset_com, cc);
      else
       if (cmd_no >= cc) {
         cc += 5;
         if (!(zone_table[zon].cmd =
                (struct reset_com *) realloc(zone_table[zon].cmd,
                               (cc * sizeof(struct reset_com)))))  {
                perror("reset command load");
                assert(0);
         }
       }
    }
 
    expand = 1;
 
    fscanf(fl, " "); /* skip blanks */
    fscanf(fl, "%c", &zone_table[zon].cmd[cmd_no].command);
 
    if (zone_table[zon].cmd[cmd_no].command == 'S')
      break;
 
    if (zone_table[zon].cmd[cmd_no].command == '*')   {
      expand = 0;
      fgets(buf, 80, fl); /* skip command */
      continue;
    }
 
    fscanf(fl, " %d %d %d",
             &tmp,
             &zone_table[zon].cmd[cmd_no].arg1,
             &zone_table[zon].cmd[cmd_no].arg2);
    zone_table[zon].cmd[cmd_no].if_flag=tmp;
 
    switch(zone_table[zon].cmd[cmd_no].command) {
      case 'M':
      case 'O':
      case 'C':
      case 'E':
      case 'P':
      case 'D':
        fscanf(fl, " %d", &zone_table[zon].cmd[cmd_no].arg3);
         break;
    }
    fgets(buf, 80, fl);       /* read comment */
    cmd_no++;
  }
return 1;
}

void CleanZone(int zone)
{
  struct room_data *rp;
  struct char_data *vict, *next_v;
  struct obj_data *obj, *next_o;
  int room,start,end,i;
 
  start=zone?(zone_table[zone-1].top+1):0;
  end=zone_table[zone].top;

  for(i=start;i<=end;i++) {
    rp=real_roomp(i);
    if(!rp) continue;
 
    for (vict = rp->people; vict; vict=next_v) {
      next_v=vict->next_in_room;
      if (IS_NPC(vict) && (!IS_SET(vict->specials.act, ACT_POLYSELF)))
        extract_char(vict);
      else
        send_to_char("\r\n\r\nSwirling winds of Chaos reform reality around you!\r\n\r\n",vict);
    }
    
    for (obj = rp->contents; obj; obj = next_o) {
      next_o=obj->next_content;
      extract_obj(obj);
    }
  }
}
 
 
int FindZone(int zone)
{
        int i;
  for(i=0;i<=top_of_zone_table;i++)
    if(zone_table[i].num==zone)
       break;
  if(zone_table[i].num!=zone)
    return(-1);
  else
    return i;
}
 
FILE *MakeZoneFile( struct char_data *c, int zone)
{
  char buf[256];
  FILE *fp;
 
  sprintf(buf, "zones/%d.zon", zone);
 
  if ((fp = fopen(buf, "wt")) != NULL)
    return(fp);
  else
    return(0);
 
}
 
FILE *OpenZoneFile(struct char_data *c, int zone)
{
  char buf[256];
  FILE *fp;
 
  sprintf(buf, "zones/%d.zon", zone);
 
  if ((fp = fopen(buf, "rt")) != NULL)
    return(fp);
  else
    return(0);
}

int WeaponImmune(struct char_data *ch)
{

  if (IS_SET(IMM_NONMAG, ch->M_immune) ||
      IS_SET(IMM_PLUS1, ch->M_immune) ||
      IS_SET(IMM_PLUS2, ch->M_immune) ||
      IS_SET(IMM_PLUS3, ch->M_immune) ||
      IS_SET(IMM_PLUS4, ch->M_immune))
    return(TRUE);
   return(FALSE);

}

unsigned IsImmune(struct char_data *ch, int bit)
{
  return(IS_SET(bit, ch->M_immune));
}

unsigned IsResist(struct char_data *ch, int bit)
{
  return(IS_SET(bit, ch->immune));
}

unsigned IsSusc(struct char_data *ch, int bit)
{
  return(IS_SET(bit, ch->susc));
}

/* creates a random number in interval [from;to] */
int number(int from, int to) 
{
   if (to - from + 1 )
	return((random() % (to - from + 1)) + from);
   else
       return(from);
}



/* simulates dice roll */
int dice(int number, int size) 
{
  int r;
  int sum = 0;

#if 0
	assert(size >= 0);
#else
/* instead of crashing the mud we set it to 1 */
if (size <= 0)
    size=1;
#endif

  if (size == 0) return(0);

  for (r = 1; r <= number; r++) sum += ((random() % size)+1);
  return(sum);
}


/* Causing memory leak, but is a standard c function, so commenting out. -DM


char *strdup(char *source)
{
	char *new;

	CREATE(new, char, strlen(source)+1);
	return(strcpy(new, source));
}
*/

int scan_number(char *text, int *rval)
{
  int	length;
  if (1!=sscanf(text, " %i %n", rval, &length))
    return 0;
  if (text[length] != 0)
    return 0;
  return 1;
}


/* returns: 0 if equal, 1 if arg1 > arg2, -1 if arg1 < arg2  */
/* scan 'till found different or end of both                 */
int str_cmp(char *arg1, char *arg2)
{
  #if 1 
int chk, i;

  if ((!arg2) || (!arg1))
    return(1);

  for (i = 0; *(arg1 + i) || *(arg2 + i); i++)
    if (chk = LOWER(*(arg1 + i)) - LOWER(*(arg2 + i)))
      if (chk < 0)
	return (-1);
      else 
	return (1);
  return(0);
#else
 return(strcmp(arg1,arg2));
#endif
}



/* returns: 0 if equal, 1 if arg1 > arg2, -1 if arg1 < arg2  */
/* scan 'till found different, end of both, or n reached     */
int strn_cmp(char *arg1, char *arg2, int n)
{
#if 1 
  int chk, i;
  
  for (i = 0; (*(arg1 + i) || *(arg2 + i)) && (n>0); i++, n--)
    if (chk = LOWER(*(arg1 + i)) - LOWER(*(arg2 + i)))
      if (chk < 0)
	return (-1);
      else 
	return (1);
  
  return(0);
#else
return(strncmp(arg1,arg2,n));
#endif

}



/* writes a string to the log */
void log_sev(char *str,int sev)
{
  long ct;
  char *tmstr;
  static char buf[500];
  struct descriptor_data *i;
  
  
  ct = time(0);
  tmstr = asctime(localtime(&ct));
  *(tmstr + strlen(tmstr) - 1) = '\0';
  fprintf(stderr, "%s :: %s\n", tmstr, str);
  
  
  if (str)
    sprintf(buf,"/* %s */\n\r",str);
  for (i = descriptor_list; i; i = i->next)
    if ((!i->connected) && (GetMaxLevel(i->character)>=LOW_IMMORTAL) &&
	(i->character->specials.sev <= sev) &&
	(!IS_SET(i->character->specials.act, PLR_NOSHOUT)))
      SEND_TO_Q(buf, i);
}

void slog(char *str)
{
	long ct;
	char *tmstr;

	ct = time(0);
	tmstr = asctime(localtime(&ct));
	*(tmstr + strlen(tmstr) - 1) = '\0';
	fprintf(stderr, "%s :: %s\n", tmstr, str);

}
	


void sprintbit(unsigned long vektor, char *names[], char *result)
{
  long nr;
  
  *result = '\0';
  
  for(nr=0; vektor; vektor>>=1)
    {
      if (IS_SET(1, vektor))
	if (*names[nr] != '\n') {
	  strcat(result,names[nr]);
	  strcat(result," ");
	} else {
	  strcat(result,"UNDEFINED");
	  strcat(result," ");
	}
      if (*names[nr] != '\n')
	nr++;
    }
  
  if (!*result)
    strcat(result, "NOBITS");
}



void sprinttype(int type, char *names[], char *result)
{
	int nr;

	for(nr=0;(*names[nr]!='\n');nr++);
	if(type < nr)
		strcpy(result,names[type]);
	else
		strcpy(result,"UNDEFINED");
}


/* Calculate the REAL time passed over the last t2-t1 centuries (secs) */
struct time_info_data real_time_passed(time_t t2, time_t t1)
{
	long secs;
	struct time_info_data now;

	secs = (long) (t2 - t1);

  now.hours = (secs/SECS_PER_REAL_HOUR) % 24;  /* 0..23 hours */
  secs -= SECS_PER_REAL_HOUR*now.hours;

  now.day = (secs/SECS_PER_REAL_DAY);          /* 0..34 days  */
  secs -= SECS_PER_REAL_DAY*now.day;

	now.month = -1;
  now.year  = -1;

	return now;
}




/* Calculate the MUD time passed over the last t2-t1 centuries (secs) */
struct time_info_data mud_time_passed(time_t t2, time_t t1)
{
  long secs, monthsecs, daysecs, hoursecs;
  struct time_info_data now;

/* eld (6-9-93) -- Hopefully, this will fix the negative month, day, etc.  */
/*                 problems...                                             */

  if(t2 >= t1) { 
    secs = (long) (t2 - t1);

    now.year = secs/SECS_PER_MUD_YEAR;

    monthsecs = secs % SECS_PER_MUD_YEAR;
    now.month = monthsecs/SECS_PER_MUD_MONTH;
    
    daysecs = monthsecs % SECS_PER_MUD_MONTH;
    now.day = daysecs/SECS_PER_MUD_DAY;

    hoursecs = daysecs % SECS_PER_MUD_DAY;
    now.hours = hoursecs/SECS_PER_MUD_HOUR;
  } else {
    secs = (long) (t1 - t2);

    now.year = secs/SECS_PER_MUD_YEAR;

    monthsecs = secs % SECS_PER_MUD_YEAR;
    now.month = monthsecs/SECS_PER_MUD_MONTH;
    
    daysecs = monthsecs % SECS_PER_MUD_MONTH;
    now.day = daysecs/SECS_PER_MUD_DAY;

    hoursecs = daysecs % SECS_PER_MUD_DAY;
    now.hours = hoursecs/SECS_PER_MUD_HOUR;

    if(now.hours) {
      now.hours = 24 - now.hours;
      now.day = now.day + 1;
    }
    if(now.day) {
      now.day = 35 - now.day;
      now.month = now.month + 1;
    }
    if(now.month) {
      now.month = 17 - now.month;
      now.year = now.year + 1;
    }
    if(now.year)
      now.year = -now.year;                
  }
  return(now);

}

void mud_time_passed2(time_t t2, time_t t1, struct time_info_data *t)
{
  long secs, monthsecs, daysecs, hoursecs;

/* eld (6-9-93) -- Hopefully, this will fix the negative month, day, etc.  */
/*                 problems...                                             */


  if(t2 >= t1) {
    secs = (long) (t2 - t1);
  
    t->year = secs/SECS_PER_MUD_YEAR;

    monthsecs = secs % SECS_PER_MUD_YEAR;
    t->month = monthsecs/SECS_PER_MUD_MONTH;

    daysecs = monthsecs % SECS_PER_MUD_MONTH;
    t->day = daysecs/SECS_PER_MUD_DAY;

    hoursecs = daysecs % SECS_PER_MUD_DAY;
    t->hours = hoursecs/SECS_PER_MUD_HOUR;
  }else {

    secs = (long) (t1 - t2);
  
    t->year = secs/SECS_PER_MUD_YEAR;

    monthsecs = secs % SECS_PER_MUD_YEAR;
    t->month = monthsecs/SECS_PER_MUD_MONTH;

    daysecs = monthsecs % SECS_PER_MUD_MONTH;
    t->day = daysecs/SECS_PER_MUD_DAY;

    hoursecs = daysecs % SECS_PER_MUD_DAY;
    t->hours = hoursecs/SECS_PER_MUD_HOUR;

    if(t->hours) {
      t->hours = 24 - t->hours;
      t->day = t->day + 1;
    }
    if(t->day) {
      t->day = 35 - t->day;
      t->month = t->month + 1;
    }
    if(t->month) {
      t->month = 17 - t->month;
      t->year = t->year + 1;
    }
    if(t->year)
      t->year = -t->year;                
  }
}


void age2(struct char_data *ch, struct time_info_data *g)
{

  mud_time_passed2(time(0),ch->player.time.birth, g);
  
  g->year += 17;   /* All players start at 17 */
  
}

struct time_info_data age(struct char_data *ch)
{
  struct time_info_data player_age;
  
  player_age = mud_time_passed(time(0),ch->player.time.birth);
  
  player_age.year += 17;   /* All players start at 17 */
  
  return(player_age);
}


char in_group ( struct char_data *ch1, struct char_data *ch2)
{



/* 
   possibilities ->
   1.  char is char2's master
   2.  char2 is char's master
   3.  char and char2 follow same.
   4.  char rides char2
   5.. char2 rides char

    otherwise not true.
 
*/
   if (ch1 == ch2)
      return(TRUE);

   if ((!ch1) || (!ch2))
      return(0);

   if ((!ch1->master) && (!ch2->master))
      return(0);

   if (ch1==ch2->master)
     return(1);

   if (ch1->master == ch2)
     return(1);

   if (ch1->master == ch2->master) {
     return(1);
   }

   if (MOUNTED(ch1) == ch2 || RIDDEN(ch1) == ch2)
     return(1);

   return(0);
}


/*
  more new procedures 
*/


/*
   these two procedures give the player the ability to buy 2*bread
   or put all.bread in bag, or put 2*bread in bag...
*/

char getall(char *name, char *newname)
{
   char arg[40],tmpname[80], otname[80];
   char prd;

   arg[0] = '\0';
   tmpname[0] = '\0';
   otname[0] = '\0';

   sscanf(name,"%s ",otname);   /* reads up to first space */

   if (strlen(otname)<5)
      return(FALSE);

   sscanf(otname,"%3s%c%s",arg,&prd,tmpname);

   if (prd != '.')
     return(FALSE);
   if (tmpname == NULL) 
      return(FALSE);
   if (strcmp(arg,"all"))
      return(FALSE);

   while (*name != '.')
       name++;

   name++;

   for (; *newname = *name; name++,newname++);
   /* :( this for loop is efficient yet arcane.. */
   
   return(TRUE);
}


int getabunch(char *name, char  *newname)
{
   int num=0;
   char tmpname[80];

   tmpname[0] = 0;
   sscanf(name,"%d*%s",&num,tmpname);
   if (tmpname[0] == '\0')
      return(FALSE);
   if (num < 1)
      return(FALSE);
   if (num>9)
      num = 9;

   while (*name != '*')
       name++;

   name++;

   for (; *newname = *name; name++,newname++);

   return(num);

}


int DetermineExp( struct char_data *mob, int exp_flags)
{

int base;
int phit;
int sab;
char buf[200];

   if (exp_flags > 100) { 
     sprintf(buf, "Exp flags on %s are > 100 (%d)", GET_NAME(mob), exp_flags);
     log(buf);
   }

/* 
reads in the monster, and adds the flags together 
for simplicity, 1 exceptional ability is 2 special abilities 
*/

    if (GetMaxLevel(mob) < 0)
       return(1);

    switch(GetMaxLevel(mob)) {

    case 0:   base = 5;
              phit = 1;
              sab = 10;
              break;

    case 1:   base = 10;
              phit = 1;
              sab =  15;
              break;

    case 2:   base = 20;
              phit = 2;
              sab =  20;
              break;


    case 3:   base = 35;
              phit = 3;
              sab =  25;
              break;

    case 4:   base = 60;
              phit = 4;
              sab =  30;
              break;

    case 5:   base = 90;
              phit = 5;
              sab =  40;
              break;

    case 6:   base = 150;
              phit = 6;
              sab =  75;
              break;

    case 7:   base = 225;
              phit = 8;
              sab =  125;
              break;

    case 8:   base = 600;
              phit = 12;
              sab  = 175;
              break;

    case 9:   base = 900;
              phit = 14;
              sab  = 300;
              break;

    case 10:   base = 1100;
              phit  = 15;
              sab   = 450;
              break;

    case 11:   base = 1300;
              phit  = 16;
              sab   = 700;
              break;

    case 12:   base = 1550;
              phit  = 17;
              sab   = 700;
              break;

    case 13:   base = 1800;
              phit  = 18;
              sab   = 950;
              break;

    case 14:   base = 2100;
              phit  = 19;
              sab   = 950;
              break;

    case 15:   base = 2400;
              phit  = 20;
              sab   = 1250;
              break;

    case 16:   base = 2700;
              phit  = 23;
              sab   = 1250;
              break;

    case 17:   base = 3000;
              phit  = 25;
              sab   = 1550;
              break;

    case 18:   base = 3500;
              phit  = 28;
              sab   = 1550;
              break;

    case 19:   base = 4000;
              phit  = 30;
              sab   = 2100;
              break;

    case 20:   base = 4500;
              phit  = 33;
              sab   = 2100;
              break;

    case 21:   base = 5000;
              phit  = 35;
              sab   =  2600;
              break;

    case 22:   base = 6000;
              phit  = 40;
              sab   = 3000;
              break;

    case 23:   base = 7000;
              phit  = 45;
              sab   = 3500;
              break;

    case 24:   base = 8000;
              phit  = 50;
              sab   = 4000;
              break;

    case 25:   base = 9000;
              phit  = 55;
              sab   = 4500;
              break;

    case 26:   base = 10000;
              phit  = 60;
              sab   =  5000;
              break;

    case 27:   base = 12000;
              phit  = 70;
              sab   = 6000;
              break;

    case 28:   base = 14000;
              phit  = 80;
              sab   = 7000;
              break;

    case 29:   base = 16000;
              phit  = 90;
              sab   = 8000;
              break;

    case 30:   base = 20000;
              phit  = 100;
              sab   = 10000;
              break;

    case 32:
    case 33:
    case 34:
    case 31 : 
      base = 22000;
      phit = 120;
      sab  = 12000;
      break;
      
    case 35:
    case 36:
    case 37:
    case 38:
    case 39:
      base = 32000;
      phit = 140;
      sab  = 14000;
      break;

    case 40:
    case 41:
      base = 42000;
      phit = 160;
      sab  = 16000;
      break;

    case 42:
    case 43:
      base = 52000;
      phit = 180;
      sab  = 20000;
      break;

    case 44:
    case 45:
      base = 72000;
      phit = 200;
      sab  = 24000;
      break;

    case 46:
    case 47:
      base = 92000;
      phit = 225;
      sab  = 28000;
      break;

    case 48:
    case 49:
      base = 122000;
      phit = 250;
      sab  = 32000;
      break;

    case 50:
      base = 150000;
      phit = 275;
      sab  = 36000;
      break;

    default:
      base = 200000;
      phit = 300;
      sab  = 40000;
      break;

    }

    return(base + (phit * GET_HIT(mob)) + (sab * exp_flags));


}

/*
int  DetermineExp( struct char_data *mob, int exp_flags);
char getall(char *name, char *newname);
int getabunch(char *name, char  *newname);
*/


void down_river( int pulse )
{
   struct char_data *ch, *tmp;
   struct obj_data *obj_object, *next_obj;
   int rd, or;
   char buf[80];
   struct room_data *rp;

   if (pulse < 0) 
      return;

   for (ch = character_list; ch; ch = tmp) {
        tmp = ch->next;
    if (!IS_NPC(ch)) {
     if (ch->in_room != NOWHERE) {
	if (real_roomp(ch->in_room)->sector_type == SECT_WATER_NOSWIM)
           if ((real_roomp(ch->in_room))->river_speed > 0) {
              if ((pulse % (real_roomp(ch->in_room))->river_speed)==0) {
                if (((real_roomp(ch->in_room))->river_dir<=5)&&((real_roomp(ch->in_room))->river_dir>=0)) {
 	 	   rd = (real_roomp(ch->in_room))->river_dir;
       		   for (obj_object = (real_roomp(ch->in_room))->contents;
				obj_object; obj_object = next_obj) {
		      next_obj = obj_object->next_content;
		      if ((real_roomp(ch->in_room))->dir_option[rd]) {
                          obj_from_room(obj_object);
   	                  obj_to_room(obj_object, (real_roomp(ch->in_room))->dir_option[rd]->to_room);
			}
		   }
/*
   flyers don't get moved
*/
                   if (!IS_AFFECTED(ch,AFF_FLYING) && !MOUNTED(ch)) {
		     rp = real_roomp(ch->in_room);
		     if (rp && rp->dir_option[rd] &&
			 rp->dir_option[rd]->to_room && 
			(EXIT(ch, rd)->to_room != NOWHERE)) {
      		         if (ch->specials.fighting) {
                               stop_fighting(ch);
			  }
		         if(IS_IMMORTAL(ch) && 
			    IS_SET(ch->specials.act, PLR_NOHASSLE)) {
			   send_to_char("The waters swirl beneath your feet.\n\r",ch);
			 } else {
			   sprintf(buf, "You drift %s...\n\r", dirs[rd]);
			   send_to_char(buf,ch);
			   if (RIDDEN(ch))
			     send_to_char(buf,RIDDEN(ch));
			   
			   or = ch->in_room;
			   char_from_room(ch);
			   if (RIDDEN(ch))  {
			     char_from_room(RIDDEN(ch));
			     char_to_room(RIDDEN(ch), (real_roomp(or))->dir_option[rd]->to_room);			 
			   }
			   char_to_room(ch,(real_roomp(or))->dir_option[rd]->to_room);
			   
			   do_look(ch, "\0",15);
			   if (RIDDEN(ch)) {
			     do_look(RIDDEN(ch), "\0",15);
			   }
			 }
			 if (IS_SET(RM_FLAGS(ch->in_room), DEATH) && 
			     GetMaxLevel(ch) < LOW_IMMORTAL) {
			   if (RIDDEN(ch))
			     NailThisSucker(RIDDEN(ch));
			   NailThisSucker(ch);
			 }
		       }
		    }
		 }
	      }
	   }
        }
      }
    }
 }

void do_WorldSave(struct char_data *ch, char *argument, char cmd)
{
   char fn[80], temp[2048], buf[128];
   long rstart, rend, i, j, k, x, r;
   struct extra_descr_data *exptr;
   FILE *fp;
   struct room_data     *rp;
   struct room_direction_data   *rdd;
   struct descriptor_data *desc;
 
   if(!ch->desc)
     return;

   rstart = 0;
   rend = top_of_world;
 
   if((fp=fopen("tinyworld.wld.new","w")) == NULL) {
     send_to_char("Can't create .wld file\r\n",ch);
     return;
   }
 
   sprintf(buf,"%s resorts the world (The game will pause for a few moments).\r\n", ch->player.name);
   send_to_all(buf);
   
   sprintf(buf,"Saving World (%ld rooms)\n\r",(long)top_of_world);
   send_to_char(buf,ch);

   for (i=rstart;i<=rend;i++) {
 
     rp = real_roomp(i);
     if (rp==NULL)
       continue;
 
/*
   strip ^Ms from description
*/
     x = 0;
 
     if (!rp->description) 
     {
       CREATE(rp->description, char, 8);
       strcpy(rp->description, "Empty");
     }
 
     for (k = 0; k <= strlen(rp->description); k++) 
     {
       if (rp->description[k] != 13)
         temp[x++] = rp->description[k];
     }
     temp[x] = '\0';
 
     if (temp[0] == '\0') {
       strcpy(temp, "Empty");
     }
 
     fprintf(fp,"#%d\n%s~\n%s~\n",rp->number,rp->name,
                                    temp);
     if (!rp->tele_targ) {
        fprintf(fp,"%d %d %d",rp->zone, rp->room_flags, rp->sector_type);
      } else {
        if (!IS_SET(TELE_COUNT, rp->tele_mask)) {
           fprintf(fp, "%d %d -1 %d %d %d %d", rp->zone, rp->room_flags,
                rp->tele_time, rp->tele_targ, 
                rp->tele_mask, rp->sector_type);
        } else {
           fprintf(fp, "%d %d -1 %d %d %d %d %d", rp->zone, rp->room_flags,
                rp->tele_time, rp->tele_targ, 
                rp->tele_mask, rp->tele_cnt, rp->sector_type);
        } 
      }
     if (rp->sector_type == SECT_WATER_NOSWIM) {
        fprintf(fp," %d %d",rp->river_speed,rp->river_dir);
     }
 
     if (rp->room_flags & TUNNEL) {
       fprintf(fp, " %d ", (int)rp->moblim);
     }
 
     fprintf(fp,"\n");     
 
     for (j=0;j<6;j++) {
       rdd = rp->dir_option[j];
       if (rdd) {
          fprintf(fp,"D%d\n",j);
 
          if (rdd->general_description && *rdd->general_description) {
            if (strlen(rdd->general_description) > 0) {
              temp[0] = '\0';
              x = 0;
              
              for (k = 0; k <= strlen(rdd->general_description); k++) {
                if (rdd->general_description[k] != 13)
                  temp[x++] = rdd->general_description[k];
              }
              temp[x] = '\0';
 
              fprintf(fp,"%s~\n", temp);
            } else {
              fprintf(fp,"~\n");
            }
          } else {
            fprintf(fp,"~\n");
          }
 
          if (rdd->keyword) {
           if (strlen(rdd->keyword)>0)
             fprintf(fp, "%s~\n",rdd->keyword);
           else
             fprintf(fp, "~\n");
          } else {
            fprintf(fp, "~\n");
          }
 
          fprintf(fp,"%d ", rdd->exit_info);
          fprintf(fp,"%d ", rdd->key);
          fprintf(fp,"%d ", rdd->to_room);
          fprintf(fp,"%d", rdd->open_cmd);
          fprintf(fp,"\n");
       }
     }
 
/*
  extra descriptions..
*/
 
   for (exptr = rp->ex_description; exptr; exptr = exptr->next) {
     x = 0;
 
    if (exptr->description) {
      for (k = 0; k <= strlen(exptr->description); k++) {
       if (exptr->description[k] != 13)
         temp[x++] = exptr->description[k];
      }
      temp[x] = '\0';
 
     fprintf(fp,"E\n%s~\n%s~\n", exptr->keyword, temp);
    }
   }
 
   fprintf(fp,"S\n");
 
   }
   fclose(fp);
 
   sprintf(buf,"The world returns to normal as %s finishes the job.\r\n", ch->player.name);
   send_to_all(buf);
   send_to_char("\n\rDone\n\r",ch);
 
 return;
}
 

void RoomSave(struct char_data *ch, long start, long end)
{
   char fn[80], temp[2048], dots[500];
   int rstart, rend, i, j, k, x, r;
   struct extra_descr_data *exptr;
   FILE *fp;
   struct room_data     *rp;
   struct room_direction_data   *rdd;
 
   rstart = start;
   rend = end;
 
   if (((rstart <= -1) || (rend <= -1)) ||
        ((rstart > WORLD_SIZE) || (rend > WORLD_SIZE))){
    send_to_char("I don't know those room #s.  make sure they are all\n\r",ch);
    send_to_char("contiguous.\n\r",ch);
    fclose(fp);
    return;
   }
 
   send_to_char("Saving\n",ch);
   strcpy(dots, "\0");
 
   for (i=rstart;i<=rend;i++) {
 
     rp = real_roomp(i);
     if (rp==NULL)
       continue;
 
     sprintf(fn, "rooms/%d", i);
     if ((fp = fopen(fn,"w")) == NULL)
     {
       send_to_char("Can't write to disk now..try later \n\r",ch);
       return;
     }
 
     strcat(dots, ".");
 
/*
   strip ^Ms from description
*/
     x = 0;
 
     if (!rp->description) 
     {
       CREATE(rp->description, char, 8);
       strcpy(rp->description, "Empty");
     }
 
     for (k = 0; k <= strlen(rp->description); k++) 
     {
       if (rp->description[k] != 13)
         temp[x++] = rp->description[k];
     }
     temp[x] = '\0';
 
     if (temp[0] == '\0') {
       strcpy(temp, "Empty");
     }
 
     fprintf(fp,"#%d\n%s~\n%s~\n",rp->number,rp->name,
                                    temp);
     if (!rp->tele_targ) {
        fprintf(fp,"%d %d %d",rp->zone, rp->room_flags, rp->sector_type);
      } else {
        if (!IS_SET(TELE_COUNT, rp->tele_mask)) {
           fprintf(fp, "%d %d -1 %d %d %d %d", rp->zone, rp->room_flags,
                rp->tele_time, rp->tele_targ, 
                rp->tele_mask, rp->sector_type);
        } else {
           fprintf(fp, "%d %d -1 %d %d %d %d %d", rp->zone, rp->room_flags,
                rp->tele_time, rp->tele_targ, 
                rp->tele_mask, rp->tele_cnt, rp->sector_type);
        } 
      }
     if (rp->sector_type == SECT_WATER_NOSWIM) {
        fprintf(fp," %d %d",rp->river_speed,rp->river_dir);
     }
 
     if (rp->room_flags & TUNNEL) {
       fprintf(fp, " %d ", (int)rp->moblim);
     }
 
     fprintf(fp,"\n");     
 
     for (j=0;j<6;j++) {
       rdd = rp->dir_option[j];
       if (rdd) {
          fprintf(fp,"D%d\n",j);
 
          if (rdd->general_description && *rdd->general_description) {
            if (strlen(rdd->general_description) > 0) {
              temp[0] = '\0';
              x = 0;
              
              for (k = 0; k <= strlen(rdd->general_description); k++) {
                if (rdd->general_description[k] != 13)
                  temp[x++] = rdd->general_description[k];
              }
              temp[x] = '\0';
 
              fprintf(fp,"%s~\n", temp);
            } else {
              fprintf(fp,"~\n");
            }
          } else {
            fprintf(fp,"~\n");
          }
 
          if (rdd->keyword) {
           if (strlen(rdd->keyword)>0)
             fprintf(fp, "%s~\n",rdd->keyword);
           else
             fprintf(fp, "~\n");
          } else {
            fprintf(fp, "~\n");
          }
 
          fprintf(fp,"%d ", rdd->exit_info);
          fprintf(fp,"%d ", rdd->key);
          fprintf(fp,"%d ", rdd->to_room);
          fprintf(fp,"%d", rdd->open_cmd);
          fprintf(fp,"\n");
       }
     }
 
/*
  extra descriptions..
*/
 
   for (exptr = rp->ex_description; exptr; exptr = exptr->next) {
     x = 0;
 
    if (exptr->description) {
      for (k = 0; k <= strlen(exptr->description); k++) {
       if (exptr->description[k] != 13)
         temp[x++] = exptr->description[k];
      }
      temp[x] = '\0';
 
     fprintf(fp,"E\n%s~\n%s~\n", exptr->keyword, temp);
    }
   }
 
   fprintf(fp,"S\n");
   fclose(fp);
 
   }
 
   send_to_char(dots, ch);
   send_to_char("\n\rDone\n\r",ch);
}
 
 
void RoomLoad( struct char_data *ch, int start, int end)
{
  FILE *fp;
  int vnum, found = TRUE, x,r;
  char chk[50], buf[80];
  struct room_data *rp, dummy;
 
 
  send_to_char("Searching and loading rooms\n\r",ch);
 
  for(vnum=start;vnum<=end;vnum++) {
 
    sprintf(buf, "rooms/%d", vnum);
    if ((fp = fopen(buf,"r")) == NULL) {
      found = FALSE;
      send_to_char(".",ch);
      continue;
    }
	fscanf(fp,"#%*d\n");
    if ((rp=real_roomp(vnum)) == 0) {  /* empty room */
      rp = (void*)malloc(sizeof(struct room_data));
      if (rp)
        bzero(rp, sizeof(struct room_data));
#if HASH
                /* this still does not work and needs work by someone */
        room_enter(&room_db, vnum, rp);
#else
        room_enter(room_db, vnum, rp);
#endif
        send_to_char("+",ch);
    } else {
      if (rp->people) {
        act("$n reaches down and scrambles reality.", FALSE, ch, NULL,
              rp->people, TO_ROOM);
      }
      cleanout_room(rp);
      send_to_char("-",ch);
    }
 
    rp->number = vnum;
    load_one_room(fp, rp);
    fclose(fp);
  }
 
  if (!found) {
    send_to_char("\n\rThe room number(s) that you specified could not all be found.\n\r",ch);
  } else {
    send_to_char("\n\rDone.\n\r",ch);
  }
 
} 

 

void fake_setup_dir(FILE *fl, long room, int dir)
{
	int tmp;
	char *temp;

	temp = fread_string(fl); /* descr */
	if (temp)
	  free(temp);
	temp = fread_string(fl); /* key */
	if (temp)
	  free(temp);

	fscanf(fl, " %d ", &tmp); 
	fscanf(fl, " %d ", &tmp);
	fscanf(fl, " %d ", &tmp);
}


int IsHumanoid( struct char_data *ch)
{
/* these are all very arbitrary */
if (!ch)
	return(FALSE);

  switch(GET_RACE(ch))
    {
    case RACE_HUMAN:
    case RACE_GNOME:
    case RACE_DEEP_GNOME:
    case RACE_ELVEN:
    case RACE_GOLD_ELF:
    case RACE_WILD_ELF:
    case RACE_SEA_ELF:
    case RACE_DWARF:
    case RACE_DARK_DWARF:
    case RACE_HALFLING:
    case RACE_ORC:
    case RACE_LYCANTH:
    case RACE_UNDEAD:
  case RACE_UNDEAD_VAMPIRE :
  case RACE_UNDEAD_LICH    : 
  case RACE_UNDEAD_WIGHT   :
 case RACE_UNDEAD_GHAST   :
 case RACE_UNDEAD_SPECTRE :
 case RACE_UNDEAD_ZOMBIE  :
 case RACE_UNDEAD_SKELETON :
 case RACE_UNDEAD_GHOUL    :
    case RACE_GIANT:
  case RACE_GIANT_HILL   :
  case RACE_GIANT_FROST  :
  case RACE_GIANT_FIRE   :
  case RACE_GIANT_CLOUD  :
  case RACE_GIANT_STORM  :
  case RACE_GIANT_STONE  :    
    case RACE_GOBLIN:
    case RACE_DEVIL:
    case RACE_TROLL:
    case RACE_VEGMAN:
    case RACE_MFLAYER:
    case RACE_ENFAN:
    case RACE_PATRYN:
    case RACE_SARTAN:
    case RACE_ROO:
    case RACE_SMURF:
    case RACE_TROGMAN:
    case RACE_LIZARDMAN:
    case RACE_SKEXIE:
    case RACE_TYTAN:
    case RACE_DROW:
    case RACE_GOLEM:
    case RACE_DEMON:
    case RACE_DRAAGDIM:
    case RACE_ASTRAL:
    case RACE_GOD:
    case RACE_HALF_ELVEN:
    case RACE_HALF_ORC:
    case RACE_HALF_OGRE:
    case RACE_HALF_GIANT:
    case RACE_GNOLL:
      return(TRUE);
      break;

    default:
      return(FALSE);
      break;
    }

}

int IsRideable( struct char_data *ch)
{
if (!ch)
	return(FALSE);

  if (IS_NPC(ch) && !IS_PC(ch)) {
    switch(GET_RACE(ch)) {
    case RACE_HORSE:
    case RACE_DRAGON:
 case RACE_DRAGON_RED    :
 case RACE_DRAGON_BLACK  :
 case RACE_DRAGON_GREEN  :
 case RACE_DRAGON_WHITE  :
 case RACE_DRAGON_BLUE   :
 case RACE_DRAGON_SILVER :
 case RACE_DRAGON_GOLD   :
 case RACE_DRAGON_BRONZE :
 case RACE_DRAGON_COPPER :
 case RACE_DRAGON_BRASS  :
      return(TRUE);
      break;
    default:
      return(FALSE);
      break;
    }
  } else return(FALSE);
}

int IsAnimal( struct char_data *ch)
{
if (!ch)
	return(FALSE);

  switch(GET_RACE(ch))
    {
    case RACE_PREDATOR:
    case RACE_FISH:
    case RACE_BIRD:
    case RACE_HERBIV:
    case RACE_REPTILE:
    case RACE_LABRAT:
    case RACE_ROO:
    case RACE_INSECT:
    case RACE_ARACHNID:
      return(TRUE);
      break;
    default:
      return(FALSE);
      break;
    }

}

int IsVeggie( struct char_data *ch)
{
if (!ch)
	return(FALSE);
	
  switch(GET_RACE(ch))
    {
    case RACE_PARASITE:
    case RACE_SLIME:
    case RACE_TREE:
    case RACE_VEGGIE:
    case RACE_VEGMAN:
      return(TRUE);
      break;
    default:
      return(FALSE);
      break;
    }

}

int IsUndead( struct char_data *ch)
{
if (!ch)
	return(FALSE);

  switch(GET_RACE(ch)) {
  case RACE_UNDEAD: 
  case RACE_GHOST:
  case RACE_UNDEAD_VAMPIRE :
  case RACE_UNDEAD_LICH    : 
  case RACE_UNDEAD_WIGHT   :
 case RACE_UNDEAD_GHAST   :
 case RACE_UNDEAD_SPECTRE :
 case RACE_UNDEAD_ZOMBIE  :
 case RACE_UNDEAD_SKELETON :
 case RACE_UNDEAD_GHOUL    :
  
    return(TRUE);
    break;
  default:
    return(FALSE);
    break;
  }

}

int IsLycanthrope( struct char_data *ch)
{
if (!ch)
	return(FALSE);
  switch (GET_RACE(ch)) {
  case RACE_LYCANTH:
    return(TRUE);
    break;
  default:
    return(FALSE);
    break;
  }

}

int IsDiabolic( struct char_data *ch)
{

if (!ch)
	return(FALSE);
  switch(GET_RACE(ch))
    {
    case RACE_DEMON:
    case RACE_DEVIL:
      return(TRUE);
      break;
    default:
      return(FALSE);
      break;
    }

}

int IsReptile( struct char_data *ch)
{
if (!ch)
	return(FALSE);
  switch(GET_RACE(ch)) {
    case RACE_REPTILE:
    case RACE_DRAGON:
 case RACE_DRAGON_RED    :
 case RACE_DRAGON_BLACK  :
 case RACE_DRAGON_GREEN  :
 case RACE_DRAGON_WHITE  :
 case RACE_DRAGON_BLUE   :
 case RACE_DRAGON_SILVER :
 case RACE_DRAGON_GOLD   :
 case RACE_DRAGON_BRONZE :
 case RACE_DRAGON_COPPER :
 case RACE_DRAGON_BRASS  : 
    case RACE_DINOSAUR:
    case RACE_SNAKE:
    case RACE_TROGMAN:
    case RACE_LIZARDMAN:
    case RACE_SKEXIE:
      return(TRUE);
      break;
    default:
      return(FALSE);
      break;
    }
}

int HasHands( struct char_data *ch)
{
if (!ch)
	return(FALSE);

  if (IsHumanoid(ch))
    return(TRUE);
  if (IsUndead(ch)) 
    return(TRUE);
  if (IsLycanthrope(ch)) 
    return(TRUE);
  if (IsDiabolic(ch))
    return(TRUE);
  if (GET_RACE(ch) == RACE_GOLEM || GET_RACE(ch) == RACE_SPECIAL)
    return(TRUE);
  return(FALSE);
}

int IsPerson( struct char_data *ch)
{
if (!ch)
	return(FALSE);


  switch(GET_RACE(ch))
    {
    case RACE_HUMAN:
    case RACE_ELVEN:
    case RACE_DROW:
    case RACE_DWARF:
    case RACE_DARK_DWARF:
    case RACE_HALFLING:
    case RACE_GNOME:
    case RACE_DEEP_GNOME:
    case RACE_GOLD_ELF:
    case RACE_WILD_ELF:
    case RACE_SEA_ELF:
    case RACE_GOBLIN:
    case RACE_ORC:
      return(TRUE);
      break;

    default:
      return(FALSE);
      break;

    }
}

int IsGiantish( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  switch(GET_RACE(ch)) {
  case RACE_ENFAN:

  case RACE_GOBLIN:  /* giantish for con's only... */
  case RACE_ORC:
  
  case RACE_GIANT:
  case RACE_GIANT_HILL   :
  case RACE_GIANT_FROST  :
  case RACE_GIANT_FIRE   :
  case RACE_GIANT_CLOUD  :
  case RACE_GIANT_STORM  :
  case RACE_GIANT_STONE  :  
  case RACE_TYTAN:
  case RACE_TROLL:
  case RACE_DRAAGDIM:

  case RACE_HALF_ORC:
  case RACE_HALF_OGRE:
  case RACE_HALF_GIANT:
    return(TRUE);
  default:
    return(FALSE);
    break;      
  }
}

int IsSmall( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  switch(GET_RACE(ch)) {
  case RACE_SMURF:
  case RACE_GNOME:
  case RACE_HALFLING:
  case RACE_GOBLIN:
  case RACE_ENFAN:
  case RACE_DEEP_GNOME:
    return(TRUE);
  default:
    return(FALSE);
  }
}

int IsGiant ( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  switch(GET_RACE(ch)) {
  case RACE_GIANT:
  case RACE_GIANT_HILL   :
  case RACE_GIANT_FROST  :
  case RACE_GIANT_FIRE   :
  case RACE_GIANT_CLOUD  :
  case RACE_GIANT_STORM  :
  case RACE_GIANT_STONE  :
  case RACE_HALF_GIANT	:
  case RACE_TYTAN:
  case RACE_GOD:
    return(TRUE);
  default:
    return(FALSE);
  }
}

int IsExtraPlanar( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  switch(GET_RACE(ch)) {
  case RACE_DEMON:
  case RACE_DEVIL:
  case RACE_PLANAR:
  case RACE_ELEMENT:
  case RACE_ASTRAL:
  case RACE_GOD:
    return(TRUE);
    break;
  default:
    return(FALSE);
    break;
  }
}
int IsOther( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  switch(GET_RACE(ch)) {
  case RACE_MFLAYER:
  case RACE_SPECIAL:
  case RACE_GOLEM:
  case RACE_ELEMENT:
  case RACE_PLANAR:
  case RACE_LYCANTH:
    return(TRUE);
  default:
    return(FALSE);
    break;
  }
}

int IsGodly( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  if (GET_RACE(ch) == RACE_GOD) return(TRUE);
  if (GET_RACE(ch) == RACE_DEMON || GET_RACE(ch) == RACE_DEVIL)
    if (GetMaxLevel(ch) >= 45)
      return(TRUE);

}

/*
int IsUndead( struct char_data *ch)
int IsUndead( struct char_data *ch)
int IsUndead( struct char_data *ch)
int IsUndead( struct char_data *ch)

*/

int IsDragon( struct char_data *ch)
{

if (!ch)
	return(FALSE);

  switch(GET_RACE(ch))
   {
 case RACE_DRAGON:
 case RACE_DRAGON_RED    :
 case RACE_DRAGON_BLACK  :
 case RACE_DRAGON_GREEN  :
 case RACE_DRAGON_WHITE  :
 case RACE_DRAGON_BLUE   :
 case RACE_DRAGON_SILVER :
 case RACE_DRAGON_GOLD   :
 case RACE_DRAGON_BRONZE :
 case RACE_DRAGON_COPPER :
 case RACE_DRAGON_BRASS  : 
      return(TRUE);
      break;
  default:
   return(FALSE);
   break;
  }
}

void SetHunting( struct char_data *ch, struct char_data *tch)
{
   int persist, dist;
   char buf[256];

#if NOTRACK
return;
#endif

if (!ch || !tch) {
	log("!ch || !tch in SetHunting");
	return;
}

	
 
   persist =  GetMaxLevel(ch);
   persist *= (int) GET_ALIGNMENT(ch) / 100;

   if (persist < 0)
     persist = -persist;

   dist = GET_ALIGNMENT(tch) - GET_ALIGNMENT(ch);
   dist = (dist > 0) ? dist : -dist;
   if (Hates(ch, tch))
       dist *=2;

   SET_BIT(ch->specials.act, ACT_HUNTING);
   ch->specials.hunting = tch;
   ch->hunt_dist = dist;
   ch->persist = persist;
   ch->old_room = ch->in_room;
#if 0
    if (GetMaxLevel(tch) >= IMMORTAL) {
        sprintf(buf, ">>%s is hunting you from %s\n\r", 
       	   (ch->player.short_descr[0]?ch->player.short_descr:"(null)"),
       	   (real_roomp(ch->in_room)->name[0]?real_roomp(ch->in_room)->name:"(null)"));
        send_to_char(buf, tch);
    }
#endif

}


void CallForGuard
  ( struct char_data *ch, struct char_data *vict, int lev, int area)
{
  struct char_data *i;
  int type1, type2;
  
  switch(area) {
  case MIDGAARD:
    type1 = 3060;
    type2 = 3069;
    break;
  case NEWTHALOS:
    type1 = 3661;
    type2 = 3682;
    break;
  case TROGCAVES:
    type1 = 21114;
    type2 = 21118;
    break;
  case OUTPOST:
    type1 = 21138;
    type2 = 21139;
    break;

  case PRYDAIN:
    type1 = 6606;
    type2 = 6614;
    break;

 default:
    type1 = 3060;
    type2 = 3069;
    break;
  }


  if (lev == 0) lev = 3;

  for (i = character_list; i && lev>0; i = i->next) {
      if (IS_NPC(i) && (i != ch)) {
	 if (!i->specials.fighting) {
	    if (mob_index[i->nr].virtual == type1) {
	       if (number(1,6) == 1) {
	         if (!IS_SET(i->specials.act, ACT_HUNTING)) {
                   if (vict) {
		      SetHunting(i, vict);
                      lev--;
		    }
	         }
	       }
	    } else if (mob_index[i->nr].virtual == type2) {
	       if (number(1,6) == 1) {
	          if (!IS_SET(i->specials.act, ACT_HUNTING)) {
		    if (vict) {
		      SetHunting(i, vict);
	              lev-=2;
		    }
		  }
		}
	    }
	  }
       }
    }
}

void StandUp (struct char_data *ch)
{
   if ((GET_POS(ch)<POSITION_STANDING) && 
       (GET_POS(ch)>POSITION_STUNNED)) {
       if (ch->points.hit > (ch->points.max_hit / 2))
         act("$n quickly stands up.", 1, ch,0,0,TO_ROOM);
       else if (ch->points.hit > (ch->points.max_hit / 6))
         act("$n slowly stands up.", 1, ch,0,0,TO_ROOM);
       else 
         act("$n gets to $s feet very slowly.", 1, ch,0,0,TO_ROOM);
       GET_POS(ch)=POSITION_STANDING;
   }
}


void MakeNiftyAttack( struct char_data *ch)
{
  int num;


  if (!ch->skills) {
    SpaceForSkills(ch);
    return;
    }

if (!ch || !ch->skills)
	{
		log("!or !ch-skills in MakeNiftyAttack() in utility.c");
		return;
	}
  if (!ch->specials.fighting) 
     return;

  num = number(1,4);
  if (num <= 2) {
      if (!ch->skills[SKILL_BASH].learned)
         ch->skills[SKILL_BASH].learned = 10 + GetMaxLevel(ch)*4;
      do_bash(ch, GET_NAME(ch->specials.fighting), 0);
  } else if (num == 3) {
     if (ch->equipment[WIELD]) {
         if (!ch->skills[SKILL_DISARM].learned)
            ch->skills[SKILL_DISARM].learned = 10 + GetMaxLevel(ch)*4;
         do_disarm(ch, GET_NAME(ch->specials.fighting), 0);
     } else {
       if (!ch->skills[SKILL_KICK].learned)
         ch->skills[SKILL_KICK].learned = 10 + GetMaxLevel(ch)*4;
       do_kick(ch, GET_NAME(ch->specials.fighting), 0);
     }
  } else {
      if (!ch->skills[SKILL_KICK].learned)
         ch->skills[SKILL_KICK].learned = 10 + GetMaxLevel(ch)*4;
      do_kick(ch, GET_NAME(ch->specials.fighting), 0);
   }

}


void FighterMove( struct char_data *ch)
{
  struct char_data *friend;

  if (!ch->skills) {
    SET_BIT(ch->player.class, CLASS_WARRIOR);
    SpaceForSkills(ch);
  }

  if (ch->specials.fighting && ch->specials.fighting->specials.fighting != 0) {
    friend = ch->specials.fighting->specials.fighting;
    if (friend == ch) {
      MakeNiftyAttack(ch);
    } else {
      /* rescue on a 1 or 2, other on a 3 or 4 */
      if (GET_RACE(friend) == (GET_RACE(ch))) {
	 if (GET_HIT(friend) < GET_HIT(ch)) { 
	   if (!ch->skills[SKILL_RESCUE].learned)
	     ch->skills[SKILL_RESCUE].learned = GetMaxLevel(ch)*3+30;
	   do_rescue(ch, GET_NAME(friend), 0);
	 } else {
	   MakeNiftyAttack(ch);
	 }
       } else {
	   MakeNiftyAttack(ch);
       }
    }
  } else {
    return;
  }

}



void MonkMove( struct char_data *ch)
{

  if (!ch->skills) {
    SpaceForSkills(ch);
    ch->skills[SKILL_DODGE].learned = GetMaxLevel(ch)+50;
    SET_BIT(ch->player.class, CLASS_MONK);
  }

  if (!ch->specials.fighting) return;

  if (GET_POS(ch) < POSITION_FIGHTING) {
    if (!ch->skills[SKILL_SPRING_LEAP].learned) 
      ch->skills[SKILL_SPRING_LEAP].learned = (GetMaxLevel(ch)*3)/2+25;
    do_springleap(ch, GET_NAME(ch->specials.fighting), 0);
    return;
  } else {
    char buf[100];

    /* Commented out as a temporary fix to monks fleeing challenges. */
    /* Was easier than rooting around in the spec_proc for the monk */
    /* challenge for it, which is proobably what should be done. */
    /* jdb - was commented back in with the change to use 
       command_interpreter */

    if (GET_HIT(ch) < GET_MAX_HIT(ch)/20) {
      if (!ch->skills[SKILL_RETREAT].learned)  
	ch->skills[SKILL_RETREAT].learned = GetMaxLevel(ch)*2+10;
      strcpy(buf, "flee");
      command_interpreter(ch, buf);
      return;
    } else {

      if (GetMaxLevel(ch)>30 && !number(0,4)) {
	if (GetMaxLevel(ch->specials.fighting) <= GetMaxLevel(ch)) {
	  if (GET_MAX_HIT(ch->specials.fighting) < 2*GET_MAX_HIT(ch)) {
	    if ((!affected_by_spell(ch->specials.fighting, SKILL_QUIV_PALM)) &&
		(!affected_by_spell(ch, SKILL_QUIV_PALM)) && 
		ch->in_room == 551) {
	      if(ch->specials.fighting->skills[SKILL_QUIV_PALM].learned &&
		 ch->in_room == 551) {
		if (!ch->skills[SKILL_QUIV_PALM].learned && ch->in_room == 551)
		  ch->skills[SKILL_QUIV_PALM].learned = GetMaxLevel(ch)*2-5;
		do_quivering_palm(ch, GET_NAME(ch->specials.fighting), 0);
		return;
	      }
	    }
	  }
	}
      }
      if (ch->specials.fighting->equipment[WIELD]) {
	if (!ch->skills[SKILL_DISARM].learned)
	  ch->skills[SKILL_DISARM].learned = (GetMaxLevel(ch)*3)/2+25;
	do_disarm(ch, GET_NAME(ch->specials.fighting), 0);
	return;
      }
      if (!ch->skills[SKILL_KICK].learned)
	ch->skills[SKILL_KICK].learned = (GetMaxLevel(ch)*3)/2+25;
      do_kick(ch, GET_NAME(ch->specials.fighting), 0);
    }
  }
}

void DevelopHatred( struct char_data *ch, struct char_data *v)
{
   int diff, patience, var;

   if (Hates(ch, v))
     return;

  if (ch == v)
    return;

  diff = GET_ALIGNMENT(ch) - GET_ALIGNMENT(v);
  if (diff < 0) diff = -diff;
  
  diff /= 20;

  if (GET_MAX_HIT(ch)) {
     patience = (int) 100 * (float) (GET_HIT(ch) / GET_MAX_HIT(ch));
  } else {
     patience = 10;
  }

  var = number(1,40) - 20;

  if (patience+var < diff)
     AddHated(ch, v);

}

int HasObject( struct char_data *ch, int ob_num)
{
int j, found;
struct obj_data *i;

/*
   equipment too
*/

found = 0;

        for (j=0; j<MAX_WEAR; j++)
     	   if (ch->equipment[j])
       	     found += RecCompObjNum(ch->equipment[j], ob_num);

      if (found > 0)
	return(TRUE);

  /* carrying  */
       	for (i = ch->carrying; i; i = i->next_content)
       	  found += RecCompObjNum(i, ob_num);

     if (found > 0)
       return(TRUE);
     else
       return(FALSE);
}


int room_of_object(struct obj_data *obj)
{
  if (obj->in_room != NOWHERE)
    return obj->in_room;
  else if (obj->carried_by)
    return obj->carried_by->in_room;
  else if (obj->equipped_by)
    return obj->equipped_by->in_room;
  else if (obj->in_obj)
    return room_of_object(obj->in_obj);
  else
    return NOWHERE;
}

struct char_data *char_holding(struct obj_data *obj)
{
  if (obj->in_room != NOWHERE)
    return NULL;
  else if (obj->carried_by)
    return obj->carried_by;
  else if (obj->equipped_by)
    return obj->equipped_by;
  else if (obj->in_obj)
    return char_holding(obj->in_obj);
  else
    return NULL;
}


int RecCompObjNum( struct obj_data *o, int obj_num)
{

int total=0;
struct obj_data *i;

  if (obj_index[o->item_number].virtual == obj_num)
    total = 1;

  if (ITEM_TYPE(o) == ITEM_CONTAINER) {
    for (i = o->contains; i; i = i->next_content)
      total += RecCompObjNum( i, obj_num);
  }
  return(total);

}

void RestoreChar(struct char_data *ch)
{

  GET_MANA(ch) = GET_MAX_MANA(ch);
  GET_HIT(ch) = GET_MAX_HIT(ch);
  GET_MOVE(ch) = GET_MAX_MOVE(ch); 
  if (GetMaxLevel(ch) < LOW_IMMORTAL) {
    GET_COND(ch,THIRST) = 24;
    GET_COND(ch,FULL) = 24;
  } else {
    GET_COND(ch,THIRST) = -1;
    GET_COND(ch,FULL) = -1;
  }

}


void RemAllAffects( struct char_data *ch)
{
  spell_dispel_magic(IMPLEMENTOR,ch,ch,0);

}

int CheckForBlockedMove
  (struct char_data *ch, int cmd, char *arg, int room, int dir, int class)
{
  
  char buf[256], buf2[256];
  
  if (cmd>6 || cmd<1)
    return(FALSE);
  
  strcpy(buf,  "The guard humiliates you, and block your way.\n\r");
  strcpy(buf2, "The guard humiliates $n, and blocks $s way.");
  
  if ((IS_NPC(ch) && (IS_POLICE(ch))) || (GetMaxLevel(ch) >= DEMIGOD) ||
      (IS_AFFECTED(ch, AFF_SNEAK)))
    return(FALSE);


  if ((ch->in_room == room) && (cmd == dir+1)) {
    if (!HasClass(ch,class))  {
      act(buf2, FALSE, ch, 0, 0, TO_ROOM);
      send_to_char(buf, ch);
      return TRUE;
    }  
  }
  return FALSE;

}


void TeleportPulseStuff(int pulse)
{
  
  /*
    check_mobile_activity(pulse);
    Teleport(pulse);
    */
  
  register struct char_data *ch;
  struct char_data *next, *tmp, *bk, *n2;
  int tick, tm;
  struct room_data *rp, *dest;
  struct obj_data *obj_object, *temp_obj;
  
  tm = pulse % PULSE_MOBILE;    /* this is dependent on P_M = 3*P_T */
  
  if (tm == 0) {
    tick = 0;
  } else if (tm == PULSE_TELEPORT) {
    tick = 1;
  } else if (tm == PULSE_TELEPORT*2) {
    tick = 2;
  }
  
  for (ch = character_list; ch; ch = next) {
    next = ch->next;
    if (IS_MOB(ch)) {
      if (ch->specials.tick == tick && !ch->specials.fighting) {
	mobile_activity(ch);
      }
    } else if (IS_PC(ch)) {
      rp = real_roomp(ch->in_room);
      if (rp &&
	  (rp)->tele_targ > 0 &&
	  rp->tele_targ != rp->number &&
	  (rp)->tele_time > 0 &&
	  (pulse % (rp)->tele_time)==0) {
	
	dest = real_roomp(rp->tele_targ);
	if (!dest) {
	  log("invalid tele_targ");
	  continue;
	}
	
	obj_object = (rp)->contents;
	while (obj_object) {
	  temp_obj = obj_object->next_content;
	  obj_from_room(obj_object);
	  obj_to_room(obj_object, (rp)->tele_targ);
	  obj_object = temp_obj;
	}
	
	bk = 0;

	while(rp->people/* should never fail */) {
	  
	  tmp = rp->people;   /* work through the list of people */
	  if (!tmp) break;

	  if (tmp == bk) break;

	  bk = tmp;

	  char_from_room(tmp); /* the list of people in the room has changed */
	  char_to_room(tmp, rp->tele_targ);

	  if (IS_SET(TELE_LOOK, rp->tele_mask) && IS_PC(tmp)) {
	    do_look(tmp, "\0",15);
	  }

       	  if (IS_SET(dest->room_flags, DEATH) && (!IS_IMMORTAL(tmp))) {
	    if (tmp == next) 
	      next = tmp->next;
	    NailThisSucker(tmp);
	    continue;
	  }
	  if (dest->sector_type == SECT_AIR) {
	    n2 = tmp->next;
	    if (check_falling(tmp)) {	      
	      if (tmp == next)
		next = n2;
	    }
	  }
	}

	if (IS_SET(TELE_COUNT, rp->tele_mask)) {
	  rp->tele_time = 0;   /* reset it for next count */
	}
	if (IS_SET(TELE_RANDOM, rp->tele_mask)) {
	  rp->tele_time = number(1,10)*100;
	}
      }
    }
  }
}

void RiverPulseStuff(int pulse)
{
  /*
    down_river(pulse);
    MakeSound();
    */
  struct descriptor_data *i;
  register struct char_data *ch;
  struct char_data *tmp;
  register struct obj_data *obj_object;
  struct obj_data *next_obj;
  int rd, or;
  char buf[80], buffer[100];
  struct room_data *rp;
  
  if (pulse < 0) 
    return;

  for (i = descriptor_list; i; i=i->next) {
    if (!i->connected) {
      ch = i->character;
      
      if (IS_PC(ch) || RIDDEN(ch)) {
	if (ch->in_room != NOWHERE) {
	  if ((real_roomp(ch->in_room)->sector_type == SECT_WATER_NOSWIM) ||
	      (real_roomp(ch->in_room)->sector_type == SECT_UNDERWATER))
	    if ((real_roomp(ch->in_room))->river_speed > 0) {
	    if ((pulse % (real_roomp(ch->in_room))->river_speed)==0) {
	      if (((real_roomp(ch->in_room))->river_dir<=5)&&
		  ((real_roomp(ch->in_room))->river_dir>=0)) {
		rd = (real_roomp(ch->in_room))->river_dir;
		for (obj_object = (real_roomp(ch->in_room))->contents;
		     obj_object; obj_object = next_obj) {
		  next_obj = obj_object->next_content;
		  if ((real_roomp(ch->in_room))->dir_option[rd]) {
		    obj_from_room(obj_object);
		    obj_to_room(obj_object, 
				(real_roomp(ch->in_room))->dir_option[rd]->to_room);
		  }
		}
		/*
		  flyers don't get moved
		  */
		if(IS_IMMORTAL(ch) &&
		   IS_SET(ch->specials.act, PLR_NOHASSLE)) {
		  send_to_char("The waters swirl and eddy about you.\n\r",ch);
		} else {
		  if(!IS_AFFECTED(ch,AFF_FLYING) ||
		     (real_roomp(ch->in_room)->sector_type == SECT_UNDERWATER)) {
		    if (!MOUNTED(ch)) {
		      rp = real_roomp(ch->in_room);
		      if (rp && rp->dir_option[rd] &&
			  rp->dir_option[rd]->to_room && 
			  (EXIT(ch, rd)->to_room != NOWHERE)) {
			if (ch->specials.fighting) {
			  stop_fighting(ch);
			}
			sprintf(buf, "You drift %s...\n\r", dirs[rd]);
			send_to_char(buf,ch);
			if (RIDDEN(ch))
			  send_to_char(buf,RIDDEN(ch));
			or = ch->in_room;
			char_from_room(ch);
			if (RIDDEN(ch))  {
			  char_from_room(RIDDEN(ch));
			  char_to_room(RIDDEN(ch),
				       (real_roomp(or))->dir_option[rd]->to_room);
			}
			char_to_room(ch,
				     (real_roomp(or))->dir_option[rd]->to_room);
			do_look(ch, "\0",15);
			if (RIDDEN(ch)) {
			  do_look(RIDDEN(ch), "\0",15);
			}
			
			
			if (IS_SET(RM_FLAGS(ch->in_room), DEATH) && 
			    GetMaxLevel(ch) < LOW_IMMORTAL) {
			  NailThisSucker(ch);
			  if (RIDDEN(ch))
			    NailThisSucker(RIDDEN(ch));
			}
		      }
		    }
		  }
		}		/* end of else for is_immort() */
	      }
	    }
	  }
	}
      }
    }
  }

  if (!number(0,4)) {
    for (ch = character_list; ch; ch = tmp) {
      tmp = ch->next;
      
      /*
       *   mobiles
       */	
      if (!IS_PC(ch) && (ch->player.sounds) && (number(0,5)==0)) {
	if (ch->specials.default_pos > POSITION_SLEEPING) {
	  if (GET_POS(ch) > POSITION_SLEEPING) {
	    /*
	     *  Make the sound;
	     */
	    MakeNoise(ch->in_room, ch->player.sounds, 
		      ch->player.distant_snds);
	  } else if (GET_POS(ch) == POSITION_SLEEPING) {
	    /*
	     * snore 
	     */	 
	    sprintf(buffer, "%s snores loudly.\n\r", 
		    ch->player.short_descr);
	    MakeNoise(ch->in_room, buffer, 
		      "You hear a loud snore nearby.\n\r");
	  }
	} else if (GET_POS(ch) == ch->specials.default_pos) {
	  /*
	   * Make the sound
	   */       
	  MakeNoise(ch->in_room, ch->player.sounds, ch->player.distant_snds);
	}
      }
    }      
  }
}

/*
**  Apply soundproof is for ch making noise
*/
int apply_soundproof(struct char_data *ch)
{
  struct room_data *rp;

  if (IS_AFFECTED(ch, AFF_SILENCE)) {
    send_to_char("You are silenced, you can't make a sound!\n\r", ch);
    return(TRUE);
  }

  rp = real_roomp(ch->in_room);

  if (!rp) return(FALSE);  

  if (IS_SET(rp->room_flags, SILENCE)) {
     send_to_char("You are in a silence zone, you can't make a sound!\n\r",ch);
     return(TRUE);   /* for shouts, emotes, etc */
  }

  if (rp->sector_type == SECT_UNDERWATER) {
    send_to_char("Speak underwater, are you mad????\n\r", ch);
    return(TRUE);
  }
  return(FALSE);

}

/*
**  check_soundproof is for others making noise
*/
int check_soundproof(struct char_data *ch)
{
  struct room_data *rp;

  if (IS_AFFECTED(ch, AFF_SILENCE)) {
    return(TRUE);
  }

  rp = real_roomp(ch->in_room);

  if (!rp) return(FALSE);  

  if (IS_SET(rp->room_flags, SILENCE)) {
     return(TRUE);   /* for shouts, emotes, etc */
  }
  if (rp->sector_type == SECT_UNDERWATER)
    return(TRUE);

  return(FALSE);
}

int MobCountInRoom( struct char_data *list)
{
  int i;
  struct char_data *tmp;

  for (i=0, tmp = list; tmp; tmp = tmp->next_in_room, i++)
    ;

  return(i);

}

void *Mymalloc( long size)
{
  if (size < 1) {
    fprintf(stderr, "attempt to malloc negative memory - %d\n", size);
    assert(0);
  }
  return(malloc(size));
}

int SpaceForSkills(struct char_data *ch)
{

  /*
    create space for the skills for some mobile or character.
  */


  ch->skills = (struct char_skill_data *)malloc(MAX_SKILLS*sizeof(struct char_skill_data));

  if (ch->skills == 0)
    assert(0);

}

int CountLims(struct obj_data *obj)
{
  int total=0;

  if (!obj)
    return(0);

  if (obj->contains)
    total += CountLims(obj->contains);
  if (obj->next_content)
    total += CountLims(obj->next_content);
  if (obj->obj_flags.cost_per_day > LIM_ITEM_COST_MIN)
    total+=1;
  return(total);
}


char *lower(char *s)
{
  static char c[1000];
  static char *p;
  int i=0;
  
  strcpy(c, s);

  while (c[i]) {
    if (c[i] < 'a' && c[i] >= 'A' && c[i] <= 'Z')
      c[i] = (char)(int)c[i]+32;
    i++;
  }
  p = c;
  return(p);
}

int getFreeAffSlot( struct obj_data *obj)
{
  int i;

  for (i=0; i < MAX_OBJ_AFFECT; i++)
    if (obj->affected[i].location == APPLY_NONE)
      return(i);

  assert(0);
}

void SetRacialStuff( struct char_data *mob)
{

  switch(GET_RACE(mob)) {
  case RACE_BIRD:
    SET_BIT(mob->specials.affected_by, AFF_FLYING);    
    break;
  case RACE_FISH:
    SET_BIT(mob->specials.affected_by, AFF_WATERBREATH);
    break;
  case RACE_ELVEN:
  case RACE_DROW:
  case RACE_GOLD_ELF:
  case RACE_WILD_ELF:
  case RACE_SEA_ELF:
	SET_BIT(mob->specials.affected_by,AFF_INFRAVISION);
	SET_BIT(mob->immune, IMM_CHARM);
	break;	
  case RACE_DWARF:
  case RACE_DARK_DWARF:
  case RACE_DEEP_GNOME:
  case RACE_GNOME:
  case RACE_MFLAYER:
  case RACE_TROLL:
  case RACE_ORC:
  case RACE_GOBLIN:
  case RACE_HALFLING:
  case RACE_GNOLL:
    SET_BIT(mob->specials.affected_by, AFF_INFRAVISION);
    break;
  case RACE_INSECT:
  case RACE_ARACHNID:
    if (IS_PC(mob)) {
      GET_STR(mob) = 18;
      GET_ADD(mob) = 100;
    }
    break;
  case RACE_LYCANTH:
    SET_BIT(mob->M_immune, IMM_NONMAG);
    break;
  case RACE_PREDATOR:
    if (mob->skills)
      mob->skills[SKILL_HUNT].learned = 100;
    break;

  case RACE_GIANT_FROST  :
    SET_BIT(mob->M_immune, IMM_COLD);
    SET_BIT(mob->susc,IMM_FIRE);
    break;
  case RACE_GIANT_FIRE   :
    SET_BIT(mob->M_immune, IMM_FIRE);
    SET_BIT(mob->susc,IMM_COLD);    
    break;
  case RACE_GIANT_CLOUD  :
    SET_BIT(mob->M_immune, IMM_SLEEP);  /* should be gas... but no IMM_GAS */
    SET_BIT(mob->susc,IMM_ACID);    
    break;
  case RACE_GIANT_STORM  :
    SET_BIT(mob->M_immune, IMM_ELEC);
    break;

  case RACE_GIANT_STONE  :
    SET_BIT(mob->M_immune, IMM_PIERCE);
    break;
  case RACE_UNDEAD:
  case RACE_UNDEAD_VAMPIRE : 
  case RACE_UNDEAD_LICH    : 
  case RACE_UNDEAD_WIGHT   :
  case RACE_UNDEAD_GHAST   :
  case RACE_UNDEAD_GHOUL   :
  case RACE_UNDEAD_SPECTRE :   
  case RACE_UNDEAD_ZOMBIE  :
  case RACE_UNDEAD_SKELETON : 
   SET_BIT(mob->specials.affected_by, AFF_INFRAVISION);
   SET_BIT(mob->M_immune,IMM_POISON+IMM_DRAIN+IMM_SLEEP+IMM_HOLD+IMM_CHARM);
   break;

 case RACE_DRAGON_RED    : SET_BIT(mob->M_immune,IMM_FIRE);
 			   SET_BIT(mob->susc,IMM_COLD);
 			   break;
 case RACE_DRAGON_BLACK  : SET_BIT(mob->M_immune,IMM_ACID);
 			   break;

 case RACE_DRAGON_GREEN  : SET_BIT(mob->M_immune,IMM_SLEEP);
 			   break;

 case RACE_DRAGON_WHITE  : SET_BIT(mob->M_immune,IMM_COLD);
 			   SET_BIT(mob->susc,IMM_FIRE);
 			   break;
 case RACE_DRAGON_BLUE   : SET_BIT(mob->M_immune,IMM_ELEC);
 			   break;
 case RACE_DRAGON_SILVER : SET_BIT(mob->M_immune,IMM_ENERGY);
 			   break;
 case RACE_DRAGON_GOLD   : SET_BIT(mob->M_immune,IMM_SLEEP+IMM_ENERGY);
 			   break;
 case RACE_DRAGON_BRONZE : SET_BIT(mob->M_immune,IMM_COLD+IMM_ACID);
 			   break;
 case RACE_DRAGON_COPPER : SET_BIT(mob->M_immune,IMM_FIRE);
 			   break;
 case RACE_DRAGON_BRASS  : SET_BIT(mob->M_immune,IMM_ELEC);
 			   break;
 
case RACE_HALF_ELVEN:
case RACE_HALF_OGRE:
case RACE_HALF_ORC:
case RACE_HALF_GIANT:
   SET_BIT(mob->specials.affected_by, AFF_INFRAVISION);
   break;

  default:
    break;
  }

   /* height and weight      / Hatred Foes! / */
 if (IS_NPC(mob))
{ 
 switch(GET_RACE(mob)) 
 {
  case RACE_HUMAN:break;

  case RACE_ELVEN:
  case RACE_GOLD_ELF:
  case RACE_WILD_ELF:
  case RACE_SEA_ELF:
   AddHatred(mob,OP_RACE,RACE_ORC);
   break;
  case RACE_GNOME:break;

  case RACE_DWARF:
      AddHatred(mob,OP_RACE,RACE_GOBLIN);
      AddHatred(mob,OP_RACE,RACE_ORC);
      break;
  case RACE_HALFLING:break;

  case RACE_LYCANTH:
   AddHatred(mob,OP_RACE,RACE_HUMAN);
   break;
  
  case RACE_UNDEAD:break;
  case RACE_DARK_DWARF:		  /* these guys hate good people */
  case RACE_UNDEAD_VAMPIRE :
  case RACE_UNDEAD_LICH    : 
  case RACE_UNDEAD_WIGHT   :
  case RACE_UNDEAD_GHAST   :
  case RACE_UNDEAD_GHOUL   :
  case RACE_UNDEAD_SPECTRE :   AddHatred(mob,OP_GOOD,1000);
  				break;
  case RACE_UNDEAD_ZOMBIE  :break;
  case RACE_UNDEAD_SKELETON :break;

  

  case RACE_VEGMAN:break;
  case RACE_MFLAYER:break;

  case RACE_DROW:
      AddHatred(mob,OP_RACE,RACE_ELVEN);
      break;
  case RACE_SKEXIE:break;
  case RACE_TROGMAN:break;
  case RACE_LIZARDMAN:break;
  case RACE_SARTAN:break;
  case RACE_PATRYN:break;
  case RACE_DRAAGDIM:break;
  case RACE_ASTRAL: break;

  case RACE_HORSE:
    mob->player.weight = 400;
    mob->player.height = 175;
    break;

  case RACE_ORC:
    AddHatred(mob,OP_GOOD,1000);
    AddHatred(mob,OP_RACE,RACE_ELVEN);
    mob->player.weight = 150;
    mob->player.height = 140;
    break;

  case RACE_SMURF:
    mob->player.weight = 5;
    mob->player.height = 10;
    break;

  case RACE_GOBLIN:
  case RACE_GNOLL:
    AddHatred(mob,OP_GOOD,1000);
    AddHatred(mob,OP_RACE,RACE_DWARF);
    break;

  case RACE_ENFAN:
    mob->player.weight = 120;
    mob->player.height = 100;
    break;

  case RACE_LABRAT:    break;
  case RACE_INSECT:    break;
  case RACE_ARACHNID:    break;
  case RACE_REPTILE:    break;
  case RACE_DINOSAUR: break;
  case RACE_FISH: break;
  case RACE_PREDATOR: break;
  case RACE_SNAKE: break;
  case RACE_HERBIV: break;
  case RACE_VEGGIE: break;
  case RACE_ELEMENT: break;
  case RACE_PRIMATE: break;

  case RACE_GOLEM:
    mob->player.weight = 10+GetMaxLevel(mob)*GetMaxLevel(mob)*2;
    mob->player.height = 20+MIN(mob->player.weight,600);
    break;

 case RACE_DRAGON:
 case RACE_DRAGON_RED    :
 case RACE_DRAGON_BLACK  :
 case RACE_DRAGON_GREEN  :
 case RACE_DRAGON_WHITE  :
 case RACE_DRAGON_BLUE   :
 case RACE_DRAGON_SILVER :
 case RACE_DRAGON_GOLD   :
 case RACE_DRAGON_BRONZE :
 case RACE_DRAGON_COPPER :
 case RACE_DRAGON_BRASS  : 
    mob->player.weight = MAX(60, GetMaxLevel(mob)*GetMaxLevel(mob)*2);
    mob->player.height = 100+ MIN(mob->player.weight, 500);
    break;

  case RACE_BIRD: 
  case RACE_PARASITE: 
  case RACE_SLIME: 
    mob->player.weight = GetMaxLevel(mob)*(GetMaxLevel(mob)/5);
    mob->player.height = 10*GetMaxLevel(mob);
    break;
  

  case RACE_GHOST:
    mob->player.weight = GetMaxLevel(mob)*(GetMaxLevel(mob)/5);
    mob->player.height = 10*GetMaxLevel(mob);
    break;
  case RACE_TROLL: 
    AddHatred(mob,OP_GOOD,1000);
    mob->player.height = 200+GetMaxLevel(mob)*15;
    mob->player.weight = (int)mob->player.height*1.5;
    break;

  case RACE_GIANT:
  case RACE_GIANT_HILL   :
  case RACE_GIANT_FROST  :
  case RACE_GIANT_FIRE   :
  case RACE_GIANT_CLOUD  :
  case RACE_GIANT_STORM  :
    mob->player.height = 200+GetMaxLevel(mob)*15;
    mob->player.weight = (int)mob->player.height*1.5;
    AddHatred(mob,OP_RACE,RACE_DWARF);
    break;

  case RACE_DEVIL: 
  case RACE_DEMON: 
    AddHatred(mob,OP_GOOD,1000);
    mob->player.height = 200+GetMaxLevel(mob)*15;
    mob->player.weight = (int)mob->player.height*1.5;
    break;


   case RACE_PLANAR:    
    mob->player.height = 200+GetMaxLevel(mob)*15;
    mob->player.weight = (int)mob->player.height*1.5;
    break;

  case RACE_GOD: break;
  case RACE_TREE: break;
  case RACE_TYTAN: 
    mob->player.weight = MAX(500, GetMaxLevel(mob)*GetMaxLevel(mob)*10);
    mob->player.height = GetMaxLevel(mob)/2*100;
    break;

 case RACE_HALF_ELVEN:
 case RACE_HALF_OGRE:
 case RACE_HALF_ORC:
 case RACE_HALF_GIANT:    
			break;
  } /* end switch */
} /* if NPC */  

}

int check_nomagic(struct char_data *ch, char *msg_ch, char *msg_rm)
{
  struct room_data *rp;

  rp = real_roomp(ch->in_room);
  if (rp && rp->room_flags&NO_MAGIC) {
    if (msg_ch)
      send_to_char(msg_ch, ch);
    if (msg_rm)
      act(msg_rm, FALSE, ch, 0, 0, TO_ROOM);
    return 1;
  }
  return 0;
}

int NumCharmedFollowersInRoom(struct char_data *ch)
{
  struct char_data *t;
  long count = 0;
  struct room_data *rp;

  rp = real_roomp(ch->in_room);
  if (rp) {
    count=0;
    for (t = rp->people;t; t= t->next_in_room) {
      if (IS_AFFECTED(t, AFF_CHARM) && (t->master == ch))
	count++;
    }
    return(count);
  } else return(0);

  return(0);
}


struct char_data *FindMobDiffZoneSameRace(struct char_data *ch)
{
  int num;
  struct char_data *t;
  struct room_data *rp1,*rp2;

  num = number(1,100);

  for (t=character_list;t;t=t->next, num--) {
    if (GET_RACE(t) == GET_RACE(ch) && IS_NPC(t) && !IS_PC(t) && num==0) {
      rp1 = real_roomp(ch->in_room);
      rp2 = real_roomp(t->in_room);
      if (rp1->zone != rp2->zone)
	return(t);
    }
  }
  return(0);
}

int NoSummon(struct char_data *ch)
{
  struct room_data *rp;

  rp = real_roomp(ch->in_room);
  if (!rp) return(TRUE);

  if (IS_SET(rp->room_flags, NO_SUM)) {
    send_to_char("Cryptic powers block your summons.\n\r", ch);
    return(TRUE);
  }

  if (IS_SET(rp->room_flags, TUNNEL)) {
    send_to_char("Strange forces collide in your brain,\n\r", ch);
    send_to_char("Laws of nature twist, and dissapate before\n\r", ch);
    send_to_char("your eyes, strange ideas wrestle with green furry\n\r", ch);
    send_to_char("things, which are crawling up your super-ego...\n\r", ch);
    send_to_char("  You lose a sanity point.\n\r\n\r", ch);
    send_to_char("  OOPS!  Sorry, wronge Genre.  :-) \n\r", ch);
    return(TRUE);
  }

  return(FALSE);
}

#if 0
int GetNewRace(struct char_file_u *s)
{
  int ok, newrace, i;

  while (1) {
    newrace = number(1,MAX_RACE);
    if (newrace == RACE_UNDEAD)
      continue;
    else {
      ok = TRUE;
      for (i=0;i<MAX_CLASS;i++) {
	if (RacialMax[newrace][i] <= 0) {
	  ok = FALSE;
	  break;
	}
      }
      if (ok) {
	return(newrace);
      }
    }
  }
}
#else
int GetNewRace(struct char_file_u *s)
{
 int return_race,try_again=TRUE;
 
 while (try_again) {
 
   return_race=number(1,MAX_RACE);
   
  switch(return_race) { 
		/* we allow these races to be used in reincarnations */
	case RACE_HUMAN     :
	case RACE_ELVEN     :
	case RACE_DWARF     :
	case RACE_HALFLING  :
	case RACE_GNOME     :
	case RACE_ORC      :
	case RACE_DROW     :
	case RACE_MFLAYER  :
	case RACE_DARK_DWARF: 
	case RACE_DEEP_GNOME :
	case RACE_GNOLL	:
	case RACE_GOLD_ELF	:
	case RACE_WILD_ELF	:
	case RACE_SEA_ELF	:
	case RACE_LIZARDMAN :
	case RACE_HALF_ELVEN :  
	case RACE_HALF_OGRE   : 
	case RACE_HALF_ORC     :
	case RACE_HALF_GIANT   :
	case RACE_GIANT_HILL   :
	case RACE_GIANT_FROST  :
	case RACE_GIANT_FIRE   :
	case RACE_GIANT_CLOUD  :
	case RACE_GIANT_STORM  :
	case RACE_ROO      :
	case RACE_PRIMATE  :
	case RACE_GOBLIN   :
	case RACE_TROLL    :
			try_again=FALSE;
			break;
				/* not a valid race, try again */
	default:try_again=TRUE;
		break;
	}  /* end switch */
   }	 /* end while */
   
   return(return_race);
}
#endif

int GetApprox(int num, int perc)
{
  /* perc = 0 - 100 */
  int adj, r;
  float fnum, fadj;

  adj = 100 - perc;
  if (adj < 0) adj = 0;
  adj *=2;  /* percentage of play (+- x%) */

  r = number(1,adj);

  perc += r;

  fnum = (float)num;
  fadj = (float)perc*2;
  fnum *= (float)(fadj/(200.0));

  num = (int)fnum;

  return(num);
}

int MountEgoCheck(struct char_data *ch, struct char_data *horse)
{
  int ride_ego, drag_ego, align, check;

  if (IsDragon(horse)) {
    if (ch->skills) {
      drag_ego = GetMaxLevel(horse)*2;
      if (IS_SET(horse->specials.act, ACT_AGGRESSIVE) ||
	  IS_SET(horse->specials.act, ACT_META_AGG)) {
	drag_ego += GetMaxLevel(horse);
      }
      ride_ego = ch->skills[SKILL_RIDE].learned/10 +
	GetMaxLevel(ch)/2;
      if (IS_AFFECTED(ch, AFF_DRAGON_RIDE)) {
	ride_ego += ((GET_INT(ch) + GET_WIS(ch))/2);
      }
      align = GET_ALIGNMENT(ch) - GET_ALIGNMENT(horse);
      if (align < 0) align = -align;
      align/=100;
      align -= 5;
      drag_ego += align;
      if (GET_HIT(horse) > 0)
	drag_ego -= GET_MAX_HIT(horse)/GET_HIT(horse);
      else 
	    drag_ego = 0;
      if (GET_HIT(ch) > 0)
	ride_ego -= GET_MAX_HIT(ch)/GET_HIT(ch);
      else 
	ride_ego = 0;
      
      check = drag_ego+number(1,10)-(ride_ego+number(1,10));
      return(check);
      
    } else {
      return(-GetMaxLevel(horse));
    }
  } else {
    if (!ch->skills) return(-GetMaxLevel(horse));

    drag_ego = GetMaxLevel(horse);

    if (drag_ego > 15) 
      drag_ego *= 2;

    ride_ego = ch->skills[SKILL_RIDE].learned/10 +
      GetMaxLevel(ch);

    if (IS_AFFECTED(ch, AFF_DRAGON_RIDE)) {
      ride_ego += (GET_INT(ch) + GET_WIS(ch));
    }
    check = drag_ego+number(1,5)-(ride_ego+number(1,10));
    return(check);
  }    
} 

int RideCheck( struct char_data *ch, int mod)
{
  if (ch->skills) {
    if (!IS_AFFECTED(ch, AFF_DRAGON_RIDE)) {
      if (number(1,90) > ch->skills[SKILL_RIDE].learned+mod) {
	if (number(1,91-mod) > ch->skills[SKILL_RIDE].learned/2) {
	  if (ch->skills[SKILL_RIDE].learned < 90) {
	    send_to_char("You learn from your mistake\n\r", ch);
	    ch->skills[SKILL_RIDE].learned+=2;
	  }
	}
	return(FALSE);
      }
      return(TRUE);
    } else {
      if (number(1,90) > (ch->skills[SKILL_RIDE].learned+
			  GET_LEVEL(ch, BestMagicClass(ch))+mod))
	return(FALSE);
    }
  } else {
    return(FALSE);
  }
}

void FallOffMount(struct char_data *ch, struct char_data *h)
{
  act("$n loses control and falls off of $N", FALSE, ch, 0, h, TO_NOTVICT);
  act("$n loses control and falls off of you", FALSE, ch, 0, h, TO_VICT);
  act("You lose control and fall off of $N", FALSE, ch, 0, h, TO_CHAR);

}

int EqWBits(struct char_data *ch, int bits)
{
  int i;

  for (i=0;i< MAX_WEAR;i++){
    if (ch->equipment[i] && 
        IS_SET(ch->equipment[i]->obj_flags.extra_flags, bits))
      return(TRUE);
  }
  return(FALSE);
}

int InvWBits(struct char_data *ch, int bits)
{
  struct obj_data *o;

  for (o = ch->carrying;o;o=o->next_content) {
    if (IS_SET(o->obj_flags.extra_flags, bits))
      return(TRUE);
  }
  return(FALSE);
}

int HasWBits(struct char_data *ch, int bits)
{
  if (EqWBits(ch, bits))
    return(TRUE);
  if (InvWBits(ch, bits))
    return(TRUE);
  return(FALSE);
}

int LearnFromMistake(struct char_data *ch, int sknum, int silent, int max)
{
char buf[128];

  if (!ch->skills) return(0);
    
  if (!IS_SET(ch->skills[sknum].flags, SKILL_KNOWN)) 
    return(0);

  if (ch->skills[sknum].learned < max && ch->skills[sknum].learned > 0)   {
    if (number(1, 101) > ch->skills[sknum].learned/2)     {
      if (!silent)
	send_to_char("You learn from your mistake\n\r", ch);
      ch->skills[sknum].learned+=1;
      if (ch->skills[sknum].learned >= max)
	if (!silent)
	  send_to_char("You are now learned in this skill!\n\r", ch);
    }
  }
}

/* if (!IsOnPmp(roomnumber)) then they are on another plane! */
int IsOnPmp(int room_nr)
{
  extern struct zone_data *zone_table;

  if (real_roomp(room_nr)) {
    if (!IS_SET(zone_table[real_roomp(room_nr)->zone].reset_mode, ZONE_ASTRAL))
      return(TRUE);
    return(FALSE);
  } else {
    return(FALSE);
  }

}


int GetSumRaceMaxLevInRoom( struct char_data *ch)
{
  struct room_data *rp;
  struct char_data *i;
  int sum=0;

  rp = real_roomp(ch->in_room);

  if (!rp) return(0);

  for (i = rp->people; i; i=i->next_in_room) {
    if (GET_RACE(i) == GET_RACE(ch)) {
      sum += GetMaxLevel(i);
    }
  }
  return(sum);
}

int too_many_followers(struct char_data *ch) 
{
  struct follow_type *k;
  int max_followers,actual_fol;
  char buf[80];

  max_followers = (int) chr_apply[GET_CHR(ch)].num_fol;
  
  for(k=ch->followers,actual_fol=0; k; k=k->next) 
    if (IS_AFFECTED(k->follower, AFF_CHARM)) 
      actual_fol++;

  if(actual_fol < max_followers)
    return FALSE;
}

int follow_time(struct char_data *ch)
{
  int fol_time=0;
  fol_time= (int) (24*GET_CHR(ch)/11);
  return fol_time;
}

int ItemAlignClash(struct char_data *ch, struct obj_data *obj)
{
  if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch))) {
    return(TRUE);
  }
  return(FALSE);
}

int ItemEgoClash(struct char_data *ch, struct obj_data *obj, int bon)
{

#ifndef EGO
  return(0);
#else

  int obj_ego, p_ego, tmp;

  obj_ego = obj->obj_flags.cost_per_day;

 if (strstr(obj->name,"scroll") ||  strstr(obj->name,"potion") ||
     strstr(obj->name,"bag") ||     
     strstr(obj->name,"key"   ) ) {
      return(0);
     }
     
  if (obj_ego >= MAX(LIM_ITEM_COST_MIN,14000) || obj_ego < 0) {
    
    if (obj_ego < 0)
      obj_ego = 50000;

    obj_ego /= 666;

/*    
  alignment stuff
    */    

    if (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) || 
	(IS_OBJ_STAT(obj, ITEM_ANTI_EVIL))) {
      if (IS_NEUTRAL(ch))
	obj_ego += obj_ego/4;
    }

    if (IS_PC(ch)) {
      p_ego = GetMaxLevel(ch)+HowManyClasses(ch);

      if (p_ego > 40) {
	p_ego *= (p_ego-39);
      } else if (p_ego > 20) {
	p_ego += (p_ego -20);
      }
      
    } else {
      p_ego = 10000;
    }

    tmp = GET_INT(ch)+GET_WIS(ch)+GET_CHR(ch);
    tmp /= 3;


    tmp *= GET_HIT(ch);
    tmp /= GET_MAX_HIT(ch);


    return((p_ego + tmp + bon + number(1,6))-(obj_ego+number(1,6)));
  }

  return(1);

#endif
}

void IncrementZoneNr(int nr)
{
  struct char_data *c;
  extern struct char_data *character_list;

  if (nr > top_of_zone_table)
    return;

  if (nr >= 0) {
    for (c = character_list;c;c=c->next) {
      if (c->specials.zone >= nr)
	c->specials.zone++;
    }
  } else {
    for (c = character_list;c;c=c->next) {
      if (c->specials.zone >= nr)
	c->specials.zone--;
    }    
  }
}

int IsDarkOutside(struct room_data *rp)
{
  extern int gLightLevel;

  if (gLightLevel >= 4)
    return(0);

  if (IS_SET(rp->room_flags, INDOORS) || IS_SET(rp->room_flags, DEATH))
    return(0);

  if (rp->sector_type == SECT_FOREST) {
    if (gLightLevel <= 1)
      return(1);
  } else {
    if (gLightLevel == 0)
      return(0);
  }
}

int anti_barbarian_stuff(struct obj_data *obj_object)
{
if ((IS_OBJ_STAT(obj_object,ITEM_GLOW))  || (IS_OBJ_STAT(obj_object,ITEM_HUM)) ||
   (IS_OBJ_STAT(obj_object,ITEM_MAGIC)) || (IS_OBJ_STAT(obj_object,ITEM_BLESS)) ||	      
   (IS_OBJ_STAT(obj_object,ITEM_NODROP)) )
    return(TRUE); else
    return(FALSE);
}

int CheckGetBarbarianOK(struct char_data *ch,struct obj_data *obj_object)
{
#ifndef BARB_GET_DISABLE
 if (GET_LEVEL(ch,BARBARIAN_LEVEL_IND) !=0 && 
       (anti_barbarian_stuff(obj_object)) && (GetMaxLevel(ch)<LOW_IMMORTAL)  )
       {
	act("$n you sense magic on $p and drop it.",FALSE,ch,obj_object,0,TO_CHAR);	        
        act("$n shakes $s head and refuses to take $p.", FALSE, ch, obj_object, 0, TO_ROOM);	        
        return(FALSE);
       }
#endif
  return(TRUE);
}

int CheckGiveBarbarianOK(struct char_data *ch,struct char_data *vict,
						struct obj_data *obj)
{
  char buf[MAX_STRING_LENGTH];

#ifndef BARB_GET_DISABLE 
 if (GET_LEVEL(vict,BARBARIAN_LEVEL_IND) !=0 && 
         anti_barbarian_stuff(obj) && GetMaxLevel(vict)<LOW_IMMORTAL  )
       {
	 if (GET_POS(vict)<=POSITION_SLEEPING)  {
	   sprintf(buf,"You think it best to not give this item to %s.\n\r",GET_NAME(vict));
 	   return(FALSE);
	  } else  {
	    sprintf(buf,"%s senses magic on the object and refuses it!\n\r",GET_NAME(vict));
	   }            
        send_to_char(buf,ch);
	return(FALSE);
       } 
#endif
 return(TRUE);
}

int CheckEgo(struct char_data *ch, struct obj_data *obj) 
{
 int j=0;

#if DISABLE_EGO
return(TRUE);
#else
if (!obj || !ch) {
	log("!obj || !ch in CheckEgo, utility.c");
	return(FALSE);
	}
	
  /*
    if the item is limited, check its ego.
    use some funky function to determine if pc's ego is higher than objs'
    ego.. if it is, proceed.. otherwise, deny.
    */
  j = ItemEgoClash(ch, obj, 0);
  if ((j < -5) && (GetMaxLevel(ch) < IMPLEMENTOR))
  {
    act("$p almost seems to say 'You're much too puny to use me, twerp!'",0,
	ch, obj, 0, TO_CHAR); 

 if (obj->in_obj==NULL) {
     act("$p falls to the floor",0,ch, obj, 0, TO_CHAR); 
     act("$p removes itself from $n, and falls to the floor",0,ch, obj, 0, TO_ROOM); 
    }
    return(FALSE);
  } else 
  if ((j < 0) && (GetMaxLevel(ch) < IMPLEMENTOR))  {
    act("$p almost seems to say 'You're pretty puny.  I don't want to be seen with you!\n", 0, ch, obj, 0, TO_CHAR);

if (obj->in_obj==NULL) { 
    act("$p falls to the floor",0,ch, obj, 0, TO_CHAR); 
    act("$p removes itself from $n, and falls to the floor",0,ch, obj, 0, TO_ROOM); 
 }
    return(FALSE);
  } else 
    return(TRUE);
  
  return(FALSE);
#endif
}

int CheckGetEgo(struct char_data *ch, struct obj_data *obj) 
{
  return(TRUE);
}

int CheckEgoGive(struct char_data *ch,struct char_data *vict,
					 struct obj_data *obj) 
{
 int j=0;

#if DISABLE_EGO
return(TRUE);
#else
  /*
    if the item is limited, check its ego.
    use some funky function to determine if pc's ego is higher than objs'
    ego.. if it is, proceed.. otherwise, deny.
    */
  j = ItemEgoClash(vict, obj, 0);
  if ((j < -5) && (GetMaxLevel(vict) < IMPLEMENTOR))
  {
if (AWAKE(vict)) {
      act("$p almost seems to say 'You're much too puny to use me, twerp!'",0,
 	vict, obj, 0, TO_CHAR); 
     act("$p refuses to leave $N's hands",0,vict, obj, ch, TO_CHAR); 
    }
    act("$p refuses to be given to $n by $N ",0,vict, obj, ch, TO_ROOM); 
    return(FALSE);
  } else 
  if ((j < 0) && (GetMaxLevel(vict) < IMPLEMENTOR))  {
  if (AWAKE(vict)) {
    act("$p almost seems to say 'You're pretty puny.  I don't want to be seen with you!\n", 0, vict, obj, 0, TO_CHAR);
    act("$p refuses to leave $N's hands",0,vict, obj, ch, TO_CHAR); 
    }
    act("$p refuses to be given to $n by $N.",0,vict, obj, ch ,TO_ROOM); 
    return(FALSE);
  } else 
    return(TRUE);
  
  return(FALSE);
#endif
}





int IsSpecialized(int sk_num)
{
 return(IS_SET(sk_num,SKILL_SPECIALIZED));
}

				 /* this persons max specialized skills */
int HowManySpecials(struct char_data *ch)
{
int i,ii=0;

for (i=0;i<MAX_SPL_LIST;i++)
 if (IsSpecialized(ch->skills[i].special)) ii++;
 return(ii);
}

int MAX_SPECIALS(struct char_data *ch)
{
 return(GET_INT(ch));              
}

int CanSeeTrap(int num,struct char_data *ch)
{
if (HasClass(ch,CLASS_THIEF)) {
 return((affected_by_spell(ch,SPELL_FIND_TRAPS)) ||
        (ch->skills && num < (ch->skills[SKILL_FIND_TRAP].learned)
         && !MOUNTED(ch)));
 } 
if (HasClass(ch,CLASS_RANGER) && OUTSIDE(ch)) {
   return((affected_by_spell(ch,SPELL_FIND_TRAPS)) ||
        (ch->skills && num < (ch->skills[SKILL_FIND_TRAP].learned)
         && !MOUNTED(ch)));
  }

if (affected_by_spell(ch,SPELL_FIND_TRAPS) && !MOUNTED(ch))
    return(TRUE);
    
 return(FALSE);
}

/* this is where we figure the max limited items the char may rent with    */
/* for his/her current level, pc's wanted it this way. MAX_LIM_ITEMS is in */
/* structs.h 								   */
int MaxLimited(int lev)
{
 if (lev <= 10) {
   return(2);
  } else 
 if (lev <= 15) {
   return(5);
  } else 
 if (lev <= 20) {
   return(7);
  } else
 if (lev <= 25) {
   return(9);
  } else
 if (lev <= 30) {
   return(13);
  } else
 if (lev <= 35) {
   return(15);
  } else
 if (lev <= 40) {
   return(16);
  } else
 if (lev <= 45) {
   return(17);
  } else
 return(MAX_LIM_ITEMS);    
}

int SiteLock (char *site)
{
#if SITELOCK

int i,length;
extern numberhosts;
extern char hostlist[MAX_BAN_HOSTS][30];

 length = strlen(site);

for (i=0;i<numberhosts;i++) {
  if (strncmp(hostlist[i],site,length)==0)
	return(TRUE);
   }
  return(FALSE);
#else
 return(FALSE);  
#endif
}

int MaxDexForRace(struct char_data *ch)
{
	switch(GET_RACE(ch)) {
	case RACE_ELVEN:
	case RACE_WILD_ELF:
	case RACE_GOLD_ELF:
	case RACE_HALFLING:
			return(19);
			break;
	case RACE_DROW:
			return(20);
			break;
	case RACE_DWARF:
	case RACE_HALF_OGRE:
			return(17);
			break;
	case RACE_HALF_GIANT:
			return(16);
			break;						
	default:return(18);
		break;		
	}/* end switch */
}

int MaxIntForRace(struct char_data *ch)
{
	switch(GET_RACE(ch)) {
	case RACE_GOLD_ELF:
	case RACE_GNOME :return(19);
			break;
	case RACE_HALF_GIANT:
	case RACE_HALF_OGRE:
		return(17);
		break;

	default:return(18);
			break;
	}/* end switch */
}

int MaxWisForRace(struct char_data *ch)
{
	switch(GET_RACE(ch)) {
	case RACE_GOLD_ELF:
	case RACE_WILD_ELF:
	case RACE_GNOME:
		return(17);
		break;
	case RACE_HALF_GIANT:
		return(17);
		break;		
	default:return(18);
		break;
	}/* end switch */
}

int MaxConForRace(struct char_data *ch)
{
	switch(GET_RACE(ch)) {
	 case RACE_HALF_ORC:
	 case RACE_DWARF:
	 case RACE_HALF_OGRE:return(19);
	 			break;
	 case RACE_ELVEN:
	 case RACE_GOLD_ELF:
	 case RACE_SEA_ELF:
	 case RACE_DROW:
	 		return(17);
	 		break;	 			
	 default:return(18);
	 	break;
	}/* end switch */
}

int MaxChrForRace(struct char_data *ch)
{
	switch(GET_RACE(ch)) {
	case RACE_HALF_ORC:
	case RACE_ORC:
	case RACE_DROW:
	case RACE_DWARF:
	case RACE_DARK_DWARF:
		return(17);
		break;
	default:return(18);
		break;
	}/* end switch */
}

int MaxStrForRace(struct char_data *ch)
{

if (GetMaxLevel(ch) >= SILLYLORD)
	return(25);

	switch(GET_RACE(ch)) {
	case RACE_TROLL:
	case RACE_HALF_GIANT:return(19);
				break;
				
	case RACE_HALFLING:
	case RACE_GOBLIN:
			return(17);
			break;				
	default:return(18);
		break;
	}/* end switch */
}


int IS_MURDER(struct char_data *ch)
{
#if 0
char buf[256];
 if (IS_PC(ch) && IS_SET(ch->player.user_flags,MURDER_1) && !IS_IMMORTAL(ch)) {
 sprintf(buf,"%s has the MURDER set.",GET_NAME(ch));
 log(buf); 
 return (TRUE); 
} 
#endif
  return(FALSE);
}

int IS_STEALER(struct char_data *ch)
{
#if 0
char buf[256];

 if (IS_PC(ch) && IS_SET(ch->player.user_flags,STOLE_1) && !IS_IMMORTAL(ch)) {
 sprintf(buf,"%s has STOLE set.",GET_NAME(ch));
 log(buf); 
 return(TRUE); 
}
#endif
  return(FALSE);
}

int MEMORIZED(struct char_data *ch, int spl) 
{
  if (ch->skills[spl].nummem >0)
     return(TRUE); else

   if (ch->skills[spl].nummem < 0) 
     ch->skills[spl].nummem = 0;
 return(FALSE);
}

int FORGET(struct char_data *ch, int spl) 
{
 if (ch->skills[spl].nummem)
     ch->skills[spl].nummem -=1;
}

/* return the amount max a person can memorize a single spell */
int MaxCanMemorize(struct char_data *ch, int spell)
{
int  BONUS;  /* use this later to figure item bonuses or something */

if (OnlyClass(ch,CLASS_SORCERER))
	BONUS=2; else
	BONUS=0;	/* multies get less... */

if (GET_INT(ch) > 18)
    BONUS +=(GET_INT(ch)-18);  /* +1 spell per intel over 18 */
    
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 4) {
   return(3+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 11) {
   return(3+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 18) {
  return(3+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 21) {
  return(4+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 26) {
  return(4+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 21) {
  return(5+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 23) {
  return(5+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 26) {
  return(6+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 28) {
  return(6+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 31) {
  return(7+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 34) {
  return(7+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 36) {
  return(7+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 41) {
  return(8+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 46) {
  return(9+BONUS);
  } else
if (GET_LEVEL(ch,SORCERER_LEVEL_IND) < 51) {
  return(10+BONUS);
  } else
   /* should never get here, cept for immos */
   return((int)GetMaxLevel(ch)/10);
}




int IS_LINKDEAD(struct char_data *ch)
{
 if (IS_PC(ch) && !ch->desc)
     return(TRUE);

if (IS_SET(ch->specials.act,ACT_POLYSELF) && !ch->desc)
      return(TRUE);
      
   return(FALSE);
}

int IS_UNDERGROUND(struct char_data *ch)
{
 struct room_data *rp;
 extern struct zone_data *zone_table;

  if ((rp = real_roomp(ch->in_room))!=NULL) {
   if (IS_SET(zone_table[rp->zone].reset_mode, ZONE_UNDER_GROUND)) 
   return(TRUE);
  }
 
return(FALSE);
}

int SetDefaultLang(struct char_data *ch)
{
int i;
		
switch (GET_RACE(ch)) {
	case RACE_ELVEN:
	case RACE_GOLD_ELF:
	case RACE_WILD_ELF:
	case RACE_SEA_ELF:
	case RACE_DROW:	i = LANG_ELVISH;
			break;
	case RACE_TROLL:
	case RACE_HALF_GIANT:i= LANG_GIANTISH;
				break;
	case RACE_HALF_OGRE:i=LANG_OGRE;
				break;
	case RACE_HALFLING:i=LANG_HALFLING;
				break;
	case RACE_DWARF:i=LANG_DWARVISH;
			break;
	case RACE_DEEP_GNOME:
	case RACE_GNOME:i=LANG_GNOMISH;
			break;
	default:i= LANG_COMMON;
		break;
	} /* end switch */
	ch->skills[i].learned = 95;
	SET_BIT(ch->skills[i].flags,SKILL_KNOWN);
	
	/* end default langauges sets */
}

int IsMagicSpell(int spell_num) 
{
int tmp=FALSE;

	/* using non magic items, since everything else is almost magic */
	/* lot smaller switch this way */
switch(spell_num) {
	case SKILL_BACKSTAB:
	case SKILL_SNEAK:
	case SKILL_HIDE:
	case SKILL_PICK_LOCK:
	case SKILL_KICK:
	case SKILL_BASH:
	case SKILL_RESCUE:
	case SKILL_FIRST_AID:
	case SKILL_SIGN:
	case SKILL_RIDE:
	case SKILL_SWITCH_OPP:
	case SKILL_DODGE:
	case SKILL_REMOVE_TRAP:
	case SKILL_RETREAT:
	case SKILL_QUIV_PALM:
	case SKILL_SAFE_FALL:
	case SKILL_FEIGN_DEATH:
	case SKILL_HUNT:
	case SKILL_FIND_TRAP:
	case SKILL_SPRING_LEAP:
	case SKILL_DISARM:
	case SKILL_EVALUATE:
	case SKILL_SPY:
	case SKILL_DOORBASH:
	case SKILL_SWIM:
	case SKILL_CONS_UNDEAD:
	case SKILL_CONS_VEGGIE:
	case SKILL_CONS_DEMON:
	case SKILL_CONS_ANIMAL:
	case SKILL_CONS_REPTILE:
	case SKILL_CONS_PEOPLE:
	case SKILL_CONS_GIANT:
	case SKILL_CONS_OTHER:
	case SKILL_DISGUISE:
	case SKILL_CLIMB:
	case SKILL_BERSERK:
	case SKILL_TAN:
	case SKILL_AVOID_BACK_ATTACK:
	case SKILL_FIND_FOOD:
	case SKILL_FIND_WATER:
	case SPELL_PRAYER:
	case SKILL_MEMORIZE:
	case SKILL_BELLOW:
	case SKILL_DOORWAY:
	case SKILL_PORTAL:
	case SKILL_SUMMON:
	case SKILL_INVIS:
	case SKILL_CANIBALIZE:
	case SKILL_FLAME_SHROUD:
	case SKILL_AURA_SIGHT:
	case SKILL_GREAT_SIGHT:
	case SKILL_PSIONIC_BLAST:
	case SKILL_HYPNOSIS:
	case SKILL_MEDITATE:
	case SKILL_SCRY:
	case SKILL_ADRENALIZE:
	case SKILL_RATION:
	case SKILL_HOLY_WARCRY:
	case SKILL_HEROIC_RESCUE:
	case SKILL_DUAL_WIELD:
	case SKILL_PSI_SHIELD:
	case LANG_COMMON:
	case LANG_ELVISH:
	case LANG_HALFLING:
	case LANG_DWARVISH:
	case LANG_ORCISH:
	case LANG_GIANTISH:
	case LANG_OGRE:
	case LANG_GNOMISH:
	case SKILL_ESP:				/* end skills */

	case TYPE_HIT:				/* weapon types here */
	case TYPE_BLUDGEON:
	case TYPE_PIERCE:
	case TYPE_SLASH:
	case TYPE_WHIP:
	case TYPE_CLAW:
	case TYPE_BITE:
	case TYPE_STING:
	case TYPE_CRUSH:
	case TYPE_CLEAVE:
	case TYPE_STAB:
	case TYPE_SMASH:
	case TYPE_SMITE:
	case TYPE_BLAST:
	case TYPE_SUFFERING:
	case TYPE_RANGE_WEAPON:
		tmp = FALSE;	/* these are NOT magical! */
		break;
		
	default :tmp = TRUE; /* default to IS MAGIC */
		 break;
  } /* end switch */
  
 return(tmp);
}


int exist(char *s)
{
  int f;
  
    f=open(s,O_RDONLY);
	close(f);
	
        if (f>0)
        return(TRUE);
              else
        return(FALSE);
}
                  

	/* Good side just means they are of the first races and on the */
	/* general good side of life, it does NOT refer to alignment */
	/* only good side people can kill bad side people PC's */
int IsGoodSide(struct char_data *ch)
{
  
  switch(GET_RACE(ch)) {

	case RACE_HUMAN     :
	case	 RACE_ELVEN     :
	case RACE_GOLD_ELF:
	case RACE_WILD_ELF:
	case RACE_SEA_ELF:
	case	 RACE_DWARF     :
	case	 RACE_HALFLING  :
	case	 RACE_GNOME     :
	case	 RACE_HALF_ELVEN  :
	case	 RACE_HALF_OGRE   : 
	case	 RACE_HALF_ORC    : 
	case	 RACE_HALF_GIANT  : 

	case 	RACE_DROW:
				return(TRUE);	 
     } /* */
    
  return(FALSE);
}

	/* this just means the PC is a troll/orc or the like not releated to */
	/* to alignment what-so-ever */
	/* only bad side people can hit and kill good side people PC's */
int IsBadSide(struct char_data *ch)
{
	
	switch(GET_RACE(ch))  {
	 case RACE_GOBLIN:
	 case RACE_DARK_DWARF:
	 case RACE_ORC:
	 case RACE_TROLL:
	 case RACE_MFLAYER:
 			return(TRUE);
	} /* */
	
  return(FALSE);
}

/* good side can fight bad side people pc to pc fighting only, not used */
/* for NPC fighting to pc fighting */
int CanFightEachOther(struct char_data *ch,struct char_data *ch2)
{

 if (IS_NPC(ch) && !IS_SET(ch->specials.act,ACT_POLYSELF) ||
    (IS_NPC(ch2) && !IS_SET(ch2->specials.act,ACT_POLYSELF)))
     return(TRUE);

if (IS_SET(SystemFlags,SYS_NOKILL))
    return(FALSE);
         
     if (IsGoodSide(ch) && IsGoodSide(ch2) ||
         IsBadSide(ch)  && IsBadSide (ch2)) 
         return(FALSE); else 
if (IS_SET(ch->player.user_flags,RACE_WAR) &&
    IS_SET(ch2->player.user_flags,RACE_WAR))  {
        return(TRUE);
    }
 
  return(FALSE);
}


int fighting_in_room(int room_n)
{
 struct char_data *ch;
 struct room_data *r;
                 
  r=real_roomp(room_n);
    
    if(!r) 
     return FALSE;
  
  for(ch=r->people;ch;ch=ch->next_in_room) 
    if(ch->specials.fighting) 
       return TRUE;
  
  return FALSE;
}
                                        
                                        

int str_cmp2(char *arg1, char *arg2)
{
  int chk, i;
  
  if (((!arg2) || (!arg1)) || (strlen(arg1)==0))
   return(1);

  for (i = 0; i<strlen(arg1); i++)
   if (chk = LOWER(*(arg1 + i)) - LOWER(*(arg2 + i)))
	if (chk < 0)
  return (-1);
	else
  return (1);
  return(0);
}

int make_exit_ok(struct char_data *ch, struct room_data **rpp, int dir) 
{
 long l;
 int rdir;
 char buf[255];
 struct zone_data *zd,*tmpz;
 struct room_data *newrp;
   
 if (GetMaxLevel(ch) < LOW_IMMORTAL || !rpp || !ch->desc ||
 	!IS_SET(ch->player.user_flags,FAST_AREA_EDIT))
	 return(FALSE);

 if(GetMaxLevel(ch) < GOD &&  (*rpp)->zone != GET_ZONE(ch))  {
    send_to_char("Sorry, you are not authorized to edit this zone. Get one assigned to you.\n\r", ch);
    return(FALSE);
  }
/* check for first room avalible in this zone */
  zd = zone_table+(*rpp)->zone;
  tmpz = zone_table+(*rpp)->zone-1;
l=tmpz->top+1;
newrp=real_roomp(l);
for (l=tmpz->top+1,newrp=real_roomp(l);
     l<zd->top && newrp;l++,newrp=real_roomp(l))

if (newrp || l >zd->top) {
	send_to_char("No more empty rooms!\n\r",ch);
	return(FALSE);
	}
	
/* create new room  */
	sprintf(buf,"%ld %ld",l,l);
	do_create(ch,buf,0);

	/* check and make sure it loaded alright... */
	newrp=real_roomp(l);
	if (!newrp) {
		send_to_char("Could not create the next room!\n\r",ch);
		return(FALSE);
		}
		
/* 	set room flags and types to current rooms settings */
	newrp->zone= (*rpp)->zone;
	newrp->continent = (*rpp)->continent;
	newrp->sector_type = (*rpp)->sector_type;
	newrp->river_dir  = (*rpp)->river_dir;
	newrp->river_speed= (*rpp)->river_speed;
	newrp->tele_time = (*rpp)->tele_time;
	newrp->tele_targ = (*rpp)->tele_targ;
	newrp->tele_mask = (*rpp)->tele_mask;
	newrp->tele_cnt	 = (*rpp)->tele_cnt;
	newrp->moblim= (*rpp)->moblim;
	newrp->room_flags= (*rpp)->room_flags;

/* 	figure out number for reverse direction of dir */
	switch(dir-1) 
		{
			case NORTH:	rdir= SOUTH;
				break;
			case SOUTH:	rdir= NORTH;
				break;
			case EAST:	rdir= WEST;
				break;
			case WEST:	rdir=EAST;
				break;
			case UP	:	rdir=DOWN;
				break;
			case DOWN:	rdir=UP;
				break;
 		       default: 
 		           rdir=NORTH;
				break;
		} /* end switch */
		
/* 	make the exit to return in current room in new room */
	sprintf(buf,"exit %d 0 -1 %ld",rdir,(*rpp)->number);
	do_edit(ch,buf,0);

/*	use dir number for direction in this one */
/*	make exit in current room to new room */
	sprintf(buf,"exit %d 0 -1 %ld",dir-1,newrp->number);
	do_edit(ch,buf,0);


	
/* return(TRUE); */

 return(FALSE);
}


/* Used to search for corrupted memory, call before and after suspect functions */
void memory_check(char *p)
{
#if DEBUG
  if(!malloc_verify()) {	/* some systems might not have this lib */
    fprintf(stderr,"memory_check failed: %s!\r\n", p);
    fflush(stderr);
    abort();
  }
#endif  
}

void dlog(char *s)
{
#if DEBUG_LOG
	slog(s);
#endif
}