deltamud/deltamud/
deltamud/deltamud/bin/
deltamud/deltamud/cnf/
deltamud/deltamud/lib/
deltamud/deltamud/lib/etc/
deltamud/deltamud/lib/misc/
deltamud/deltamud/lib/plrobjs/
deltamud/deltamud/lib/text/
deltamud/deltamud/lib/text/help/
deltamud/deltamud/lib/world/
deltamud/deltamud/lib/world/trg/
/* ************************************************************************
   *   File: utils.c                                       Part of CircleMUD *
   *  Usage: various internal functions of a utility nature                  *
   *                                                                         *
   *  All rights reserved.  See license.doc for complete information.        *
   *                                                                         *
   *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
   *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
   ************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "screen.h"
#include "spells.h"
#include "handler.h"

extern struct time_data time_info;
extern struct room_data *world;
extern int sunlight;
extern int stat_table[9][12];

/* local functions */
char *stripcr(char *dest, const char *src);

int GET_RACE_MIN(int race, int stat) { return (race >= 0 && race <= 8 && stat >= 1 && stat<= 6 ?
stat_table[race][stat*2-2] : 0); }
int GET_RACE_MAX(int race, int stat) { return (race >= 0 && race <= 8 && stat >= 1 && stat<= 6 ?
stat_table[race][stat*2-1] : 0); }

/* Creates a supercompact sine graph with an amplitude of 1 and a period of 1.
  Looks like:
1    x   x   x
0   x x x x x x x
-1     x   x   x
    1   2   3   4
*/
int roundf (float x) {
  float y=x;
  while (y>1) y-=1;
  while (y<0) y+=1;

  if (x<0) {
    if (y<-0.5) return x+y;
    else return x+y-1;
  }
  if (x>0) {
    if (y<0.5) return x-y;
    else return x-y+1;
  }
  return 0;
}
float freq_graph_y ( float x ) {
  float tempx=x, tempy;
  while (tempx > 1) tempx-=1;
  while (tempx < 0) tempx+=1;

  if (tempx <= 0.25)
    tempy=-4*((tempx-0.25)*(tempx-0.25));
  else if (tempx <= 0.50)
    tempy=-4*((0.25-tempx)*(0.25-tempx));
  else if (tempx<=1.00)
    return -freq_graph_y(tempx-0.50);
  else tempy=0;

  tempy*=4; // Vertical stretch by a factor of 4 to give us an amplitude of 1. Goes FIRST!!
  tempy+=1; // Shift it up, so we have 0 as our baseline.
  return tempy;
}

void biorythm(struct char_data *ch) {
  char graph[31][44];
  float x, tx, y;
  int i, j;
  int tn=number(0, 20);
  for (i=0; i < 31; i++) for (j=0; j < 43; j++) graph[i][j]=' ';
  for (i=0; i < 31; i++) graph[i][43]='\0';
  for (x=0; x<=1.00; x+=0.025) {
    tx=40*x;
    y=10-10*freq_graph_y(x);
    graph[y < 0 ? 0 : (y > 30 ? 30 : roundf(y))][roundf(tx)]= roundf(tx) == tn ? '+' : 'x';
  }
  for (j=0; j<31; j++) {
    send_to_char(graph[j], ch);
    send_to_char("\r\n", ch);
  }
}

/* What is the percent chance that ch will hit vict with a spell/skill or weapon? */
int chance (struct char_data *ch, struct char_data *vict, int type) {
  sh_int p;
  /* Type = 0 | Normal Attack 
     Type = 1 | Magical Attack 
     Return: 0 - Total faliure, no possibility of hit.
             50 - *Equal* 50/50 chance there is a hit.
             100 - Total success, no possibility of miss.
  */
  switch (type) {
    case 0:
      p=GET_TECHNIQUE(ch)-GET_TECHNIQUE(vict);
      p+=(GET_DEX(ch)-GET_DEX(vict))*10;
      break;
    case 1:
      p=GET_TECHNIQUE(ch)-GET_TECHNIQUE(vict);
      p+=(GET_INT(ch)-GET_WIS(vict))*10;
      break;
    default:
      return 0;
      break;
  }
  p/=10; //Just making our ranges LARGE, -1000 to 1000
  // p can range from -100 (fail) to 100 (success) normally
  p=(p+100)/2; // Percentage here.. 0% or 100%
  p = p < 0 ? 0 : (p > 100 ? 100 : p); // If some fool happens to be 150% better, cap it :P
  return p;
}

/* What is the damage multiplier for ch when ch hits vict? */
float dam_multi (struct char_data *ch, struct char_data *vict, int type) {
  float p;
  /* Type = 0 | Normal Attack 
     Type = 1 | Magical Attack
     A person with an offense of 100 attacking a person with defense of -100 */
  switch (type) {
    case 0:
      p=GET_POWER(ch)-GET_DEFENSE(vict);
      p+=(GET_STR(ch)-GET_CON(vict))*10;
      break;
    case 1:
      p=GET_MPOWER(ch)-GET_MDEFENSE(vict);
      p+=(GET_INT(ch)-GET_WIS(vict))*10;
      break;
    default:
      return 1;
      break;
  }
  p/=10; //Just making our ranges LARGE, -1000 to 1000
  if (p>=0)
    p=1+(2*p/100);
  else {
    p*=-1;
    p=1-(2/300*p);
  }
  /* In essence, here are the values:
                           |------Normal Ranges---------|
   Rating     : Better     |         Neutral            |      Worst
   Value(p)   : 200   150  |100   50    0     -50   -100| -150  -200
   Multiplier : 5     4    |3     2     1     0.6   0.3 | 0     -0.3
                           |----------------------------|

    p is how player 1 compares to player 2 (offense vs defense)
    multiplier is the damage multiplier they receive (this can
      go below 1 [normal] if player 1 is a weaker hitter than player
      2 is a defender, this will *never* go negative [as it does above]
      because of the sanitycheck below -- we don't want healing hits :P
  */
  return p < 0 ? 0 : p;
}

double power ( double num, int power ) {
  int i;
  double fnum=num;
  if (power==0) return 1;
  for (i=1; i<power; i++)
    fnum*=num;
  if (power<0) return (1/fnum);
  return fnum;
}

/* We don't need this anymore, look under 'sqrt' function below to find out why.

double ln ( double num ) {
  register double x=1, fnum=0;
  register int i;
     Natural logarithm is an infinite series, but since we can't
     calculate an irrational number with a rational limit (15
     digits as far as 'double' goes, we'll loop it 48 times for ((I chose 48 because it gave me the closest numbers I wanted when I was fine-tuning the program.))
     a little more accuracy.
     Natural logarithm 'by hand' is as follows:
     ln(x)=2[(x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 
           + (1/5)((x-1)/(x+1))^5 + (1/7)((x...]
  for (i=1; i<=48; i++) {
    fnum+=(1/x)*power((num-1)/(num+1), x);
    x+=2;
  }
  return 2*fnum;
}

*/

double mlog (double base, double num) {
  double log10 (double num);
  /* Using our logarithmic rule: (x is the base, y in the num)
              log(y)
     log(x,y)=------
              log(x)
  */
  return (log10(num)/log10(base));
}

/* creates a random number in interval [from;to] */
int 
number (int from, int to)
{
  /* error checking in case people call number() incorrectly */
  if (from > to)
    {
      int tmp = from;
      from = to;
      to = tmp;
    }

  return ((circle_random () % (to - from + 1)) + from);
}


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

  if (size <= 0 || number <= 0)
    return 0;
  while (number-- > 0)
    sum += ((circle_random() % size) + 1);

  return sum;
}


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


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



/* Create a duplicate of a string */
char *
str_dup (const char *source)
{
  char *new;
  if (!source) return NULL;
  CREATE (new, char, strlen (source) + 1);
  return (strcpy (new, source));
}



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

  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);
}


/* strn_cmp: a case-insensitive version of strncmp */
/* 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)
{
  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);
}


/* log a death trap hit */
void 
log_death_trap (struct char_data *ch)
{
  char buf[150];
  extern struct room_data *world;

  sprintf (buf, "%s hit death trap #%d (%s)", GET_NAME (ch),
	   (int) world[ch->in_room].number, world[ch->in_room].name);
  mudlog (buf, BRF, LVL_IMMORT, TRUE);

// this was annoying, removed 8/23/98 --Mulder
//  sprintf (buf, "&m[&YINFO&m]&n %s was killed by a death trap.\r\n",
//          GET_NAME (ch));
//          send_to_all (buf);
}


/* writes a string to the log */
void 
log (char *str)
{
  time_t ct;
  char *tmstr;

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

/* the "touch" command, essentially. */
int 
touch (char *path)
{
  FILE *fl;

  if (!(fl = fopen (path, "a")))
    {
      perror (path);
      return -1;
    }
  else
    {
      fclose (fl);
      return 0;
    }
}


/*
 * mudlog -- log mud messages to a file & to online imm's syslogs
 * based on syslog by Fen Jul 3, 1992
 */
void 
mudlog (char *str, char type, int level, byte file)
{
  char buf[MAX_STRING_LENGTH];
  extern struct descriptor_data *descriptor_list;
  struct descriptor_data *i;
  char *tmp, tp;
  time_t ct;
  int j;

  ct = time (0);
  tmp = asctime (localtime (&ct));

  if (file)
    {
      fprintf (logfile, "%-15.15s :: %s\n", tmp + 4, str);
      fflush (logfile);
    }
  if (level < 0)
    return;

  // Strip off \r\n characters off the end of the string. Mudlog doesn't look right... -Storm
  tmp=str_dup(str);
  for (j=strlen(tmp)-1; tmp[j]=='\r' || tmp[j]=='\n'; j--)
    tmp[j]='\0';
  sprintf (buf, "[ %s ]\r\n", tmp);
  free(tmp);

  for (i = descriptor_list; i; i = i->next)
    if (!i->connected && !PLR_FLAGGED (i->character, PLR_WRITING))
      {
	tp = ((PRF_FLAGGED (i->character, PRF_LOG1) ? 1 : 0) +
	      (PRF_FLAGGED (i->character, PRF_LOG2) ? 2 : 0) +
	      (PRF_FLAGGED (i->character, PRF_LOG3) ? 4 : 0));
  
	if ((GET_LEVEL (i->character) >= level) && (tp >= type || (tp == 3 && strncmp(str, "Auto zone reset:", 16)) /* syslog perfect logs everything cept resets */))
	  {
	    send_to_char (CCGRN (i->character, C_NRM), i->character);
	    send_to_char (buf, i->character);
	    send_to_char (CCNRM (i->character, C_NRM), i->character);
	  }
      }
}



void sprintbit(long bitvector, const char *names[], char *result)
{
  long nr;

  *result = '\0';

  if (bitvector < 0) {
    strcpy(result, "<INVALID BITVECTOR>");
    return;
  }
  for (nr = 0; bitvector; bitvector >>= 1) {
    if (IS_SET(bitvector, 1)) {
      if (*names[nr] != '\n') {
        strcat(result, names[nr]);
        strcat(result, " ");
      } else
        strcat(result, "UNDEFINED ");
    }
    if (*names[nr] != '\n')
      nr++;
  }
    
  if (!*result)
    strcpy(result, "NOBITS ");
}
void sprinttype(int type, const char *names[], char *result)
{
  int nr = 0;
     
  while (type && *names[nr] != '\n') {
    type--;
    nr++;
  } 
  
  if (*names[nr] != '\n')
    strcpy(result, names[nr]);
  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;
  struct time_info_data now;

  secs = (long) (t2 - t1);

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

  now.day = (secs / SECS_PER_MUD_DAY) % 35;	/* 0..34 days  */
  secs -= SECS_PER_MUD_DAY * now.day;

  now.month = (secs / SECS_PER_MUD_MONTH) % 17;		/* 0..16 months */
  secs -= SECS_PER_MUD_MONTH * now.month;

  now.year = (secs / SECS_PER_MUD_YEAR);	/* 0..XX? years */

  return now;
}



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;
}


/* Check if making CH follow VICTIM will create an illegal */
/* Follow "Loop/circle"                                    */
bool 
circle_follow (struct char_data * ch, struct char_data * victim)
{
  struct char_data *k;

  for (k = victim; k; k = k->master)
    {
      if (k == ch)
	return TRUE;
    }

  return FALSE;
}



/* Called when stop following persons, or stopping charm */
/* This will NOT do if a character quits/dies!!          */
void 
stop_follower (struct char_data *ch)
{
  struct follow_type *j, *k;

  assert (ch->master);

  if (IS_AFFECTED (ch, AFF_CHARM))
    {
      act ("You realize that $N is a jerk!", FALSE, ch, 0, ch->master, TO_CHAR);
      act ("$n realizes that $N is a jerk!", FALSE, ch, 0, ch->master, TO_NOTVICT);
      act ("$n hates your guts!", FALSE, ch, 0, ch->master, TO_VICT);
      if (affected_by_spell (ch, SPELL_CHARM))
	affect_from_char (ch, SPELL_CHARM);
    }
  else
    {
      act ("You stop following $N.", FALSE, ch, 0, ch->master, TO_CHAR);
      act ("$n stops following $N.", TRUE, ch, 0, ch->master, TO_NOTVICT);
      act ("$n stops following you.", TRUE, ch, 0, ch->master, TO_VICT);
    }

  if (ch->master->followers->follower == ch)
    {				/* Head of follower-list? */
      k = ch->master->followers;
      ch->master->followers = k->next;
      free (k);
    }
  else
    {				/* locate follower who is not head of list */
      for (k = ch->master->followers; k->next->follower != ch; k = k->next);

      j = k->next;
      k->next = j->next;
      free (j);
    }

  ch->master = NULL;
  REMOVE_BIT (AFF_FLAGS (ch), AFF_CHARM | AFF_GROUP);
}



/* Called when a character that follows/is followed dies */
void 
die_follower (struct char_data *ch)
{
  struct follow_type *j, *k;

  if (ch->master)
    stop_follower (ch);

  for (k = ch->followers; k; k = j)
    {
      j = k->next;
      stop_follower (k->follower);
    }
}



/* Do NOT call this before having checked if a circle of followers */
/* will arise. CH will follow leader                               */
void 
add_follower (struct char_data *ch, struct char_data *leader)
{
  struct follow_type *k;

  assert (!ch->master);

  ch->master = leader;

  CREATE (k, struct follow_type, 1);

  k->follower = ch;
  k->next = leader->followers;
  leader->followers = k;

  act ("You now follow $N.", FALSE, ch, 0, leader, TO_CHAR);
  if (CAN_SEE (leader, ch))
    act ("$n starts following you.", TRUE, ch, 0, leader, TO_VICT);
  act ("$n starts to follow $N.", TRUE, ch, 0, leader, TO_NOTVICT);
}

/*
 * get_line reads the next non-blank line off of the input stream.
 * The newline character is removed from the input.  Lines which begin
 * with '*' are considered to be comments.
 *
 * Returns the number of lines advanced in the file.
 */
int 
get_line (FILE * fl, char *buf)
{
  char temp[256];
  int lines = 0;

  do
    {
      lines++;
      fgets (temp, 256, fl);
      if (*temp)
	temp[strlen (temp) - 1] = '\0';
    }
  while (!feof (fl) && (*temp == '*' || !*temp));

  if (feof (fl))
    return 0;
  else
    {
      strcpy (buf, temp);
      return lines;
    }
}


int 
get_filename (char *orig_name, char *filename, int mode)
{
  char *prefix, *middle, *suffix, *ptr, name[64];

  switch (mode)
    {
    case CRASH_FILE:
      prefix = "plrobjs";
      suffix = "objs";
      break;
    case ETEXT_FILE:
      prefix = "plrtext";
      suffix = "text";
      break;
    case ALIAS_FILE:
      prefix = "plralias";
      suffix = "alias"; 
      break;
    case EDATA_FILE:
      prefix = "plredata";
      suffix = "data";
      break;
    default:
      return 0;
      break;
    }

  if (!*orig_name)
    return 0;

  strcpy (name, orig_name);
  for (ptr = name; *ptr; ptr++)
    *ptr = LOWER (*ptr);

  switch (LOWER (*name))
    {
    case 'a':
    case 'b':
    case 'c':
    case 'd':
    case 'e':
      middle = "A-E";
      break;
    case 'f':
    case 'g':
    case 'h':
    case 'i':
    case 'j':
      middle = "F-J";
      break;
    case 'k':
    case 'l':
    case 'm':
    case 'n':
    case 'o':
      middle = "K-O";
      break;
    case 'p':
    case 'q':
    case 'r':
    case 's':
    case 't':
      middle = "P-T";
      break;
    case 'u':
    case 'v':
    case 'w':
    case 'x':
    case 'y':
    case 'z':
      middle = "U-Z";
      break;
    default:
      middle = "ZZZ";
      break;
    }

  sprintf (filename, "%s/%s/%s.%s", prefix, middle, name, suffix);
  return 1;
}


int 
num_pc_in_room (struct room_data *room)
{
  int i = 0;
  struct char_data *ch;

  for (ch = room->people; ch != NULL; ch = ch->next_in_room)
    if (!IS_NPC (ch))
      i++;

  return i;
}


/* string manipulation fucntion originally by Darren Wilson */
/* (wilson@shark.cc.cc.ca.us) improved and bug fixed by Chris (zero@cnw.com) */
/* completely re-written again by M. Scott 10/15/96 (scottm@workcommn.net), */
/* substitute appearances of 'pattern' with 'replacement' in string */
/* and return the # of replacements */
int 
replace_str (char **string, char *pattern, char *replacement, int rep_all,
	     int max_size)
{
  char *replace_buffer = NULL;
  char *flow, *jetsam, temp;
  int len, i;

  if ((strlen (*string) - strlen (pattern)) + strlen (replacement) > max_size)
    return -1;

  CREATE (replace_buffer, char, max_size);
  i = 0;
  jetsam = *string;
  flow = *string;
  *replace_buffer = '\0';
  if (rep_all)
    {
      while ((flow = (char *) strstr (flow, pattern)) != NULL)
	{
	  i++;
	  temp = *flow;
	  *flow = '\0';
	  if ((strlen (replace_buffer) + strlen (jetsam) + strlen (replacement)) > max_size)
	    {
	      i = -1;
	      break;
	    }
	  strcat (replace_buffer, jetsam);
	  strcat (replace_buffer, replacement);
	  *flow = temp;
	  flow += strlen (pattern);
	  jetsam = flow;
	}
      strcat (replace_buffer, jetsam);
    }
  else
    {
      if ((flow = (char *) strstr (*string, pattern)) != NULL)
	{
	  i++;
	  flow += strlen (pattern);
	  len = ((char *) flow - (char *) *string) - strlen (pattern);

	  strncpy (replace_buffer, *string, len);
	  strcat (replace_buffer, replacement);
	  strcat (replace_buffer, flow);
	}
    }
  if (i == 0)
    return 0;
  if (i > 0)
    {
      RECREATE (*string, char, strlen (replace_buffer) + 3);
      strcpy (*string, replace_buffer);
    }
  free (replace_buffer);
  return i;
}


/* re-formats message type formatted char * */
/* (for strings edited with d->str) (mostly olc and mail)     */
void 
format_text (char **ptr_string, int mode, struct descriptor_data *d, int maxlen)
{
  int total_chars, cap_next = TRUE, cap_next_next = FALSE;
  char *flow, *start = NULL, temp;
  /* warning: do not edit messages with max_str's of over this value */
  char formated[MAX_STRING_LENGTH];

  flow = *ptr_string;
  if (!flow)
    return;

  if (IS_SET (mode, FORMAT_INDENT))
    {
      strcpy (formated, "   ");
      total_chars = 3;
    }
  else
    {
      *formated = '\0';
      total_chars = 0;
    }

  while (*flow != '\0')
    {
      while ((*flow == '\n') ||
	     (*flow == '\r') ||
	     (*flow == '\f') ||
	     (*flow == '\t') ||
	     (*flow == '\v') ||
	     (*flow == ' '))
	flow++;

      if (*flow != '\0')
	{

	  start = flow++;
	  while ((*flow != '\0') &&
		 (*flow != '\n') &&
		 (*flow != '\r') &&
		 (*flow != '\f') &&
		 (*flow != '\t') &&
		 (*flow != '\v') &&
		 (*flow != ' ') &&
		 (*flow != '.') &&
		 (*flow != '?') &&
		 (*flow != '!'))
	    flow++;

	  if (cap_next_next)
	    {
	      cap_next_next = FALSE;
	      cap_next = TRUE;
	    }

	  /* this is so that if we stopped on a sentance .. we move off the sentance delim. */
	  while ((*flow == '.') || (*flow == '!') || (*flow == '?'))
	    {
	      cap_next_next = TRUE;
	      flow++;
	    }

	  temp = *flow;
	  *flow = '\0';

	  if ((total_chars + strlen (start) + 1) > 79)
	    {
	      strcat (formated, "\r\n");
	      total_chars = 0;
	    }

	  if (!cap_next)
	    {
	      if (total_chars > 0)
		{
		  strcat (formated, " ");
		  total_chars++;
		}
	    }
	  else
	    {
	      cap_next = FALSE;
	      *start = UPPER (*start);
	    }

	  total_chars += strlen (start);
	  strcat (formated, start);

	  *flow = temp;
	}

      if (cap_next_next)
	{
	  if ((total_chars + 3) > 79)
	    {
	      strcat (formated, "\r\n");
	      total_chars = 0;
	    }
	  else
	    {
	      strcat (formated, "  ");
	      total_chars += 2;
	    }
	}
    }
  strcat (formated, "\r\n");

  if (strlen (formated) > maxlen)
    formated[maxlen] = '\0';
  RECREATE (*ptr_string, char, MIN (maxlen, strlen (formated) + 3));
  strcpy (*ptr_string, formated);
}
int charge_less_rent(struct char_data *ch)
{
int lessrent;

lessrent = GET_LEVEL(ch) * 500;

if (GET_LEVEL(ch) < LVL_IMMORT)
  return lessrent;
else
  return 100000000;
}

/*quicksort: sort v[left] to v[right] into INCREASING order. */
/* Implemented by Thargor, based on Kernighan & Ritchie's "The C Language",
   considered by all the C bible. 
   This version has been modified to custom fit the static data structure
   used (struct who_list).
   NOTE: This is a recursive function. Do not edit unless you understand
   recursive functions.
   */
void quicksort(void *v[], int left, int right, 
	   int (*comp)(int, int))
{
  int i, last;
  void swap(void *v[], int, int);

  if (left >= right)  /* Do nothing if array contains fewer than 2 elements */
    return; 

  swap(v, left, (left+right)/2);
  last = left;

  for (i = left+1; i <= right; i++)
    /* if ((*comp)(v[i], v[left]) < 0) */
    if ((*comp)((((struct who_list *) v)+i)->level,
		(((struct who_list *) v)+left)->level) < 0)
      swap(v, ++last, i);
  swap(v, left, last);

  quicksort (v, left, last-1, comp);
  quicksort (v, last+1, right, comp);
} /* end quicksort */

void swap(void *v[], int i, int j)
{
  struct who_list temp;

  if (i == j)
    return;

  bzero(temp.desc, SMALL_BUFSIZE);
  strcpy(temp.desc, (((struct who_list *) v)+i)->desc);
  temp.level =  (((struct who_list *) v)+i)->level;

  bzero((((struct who_list *) v)+i)->desc, SMALL_BUFSIZE);
  strcpy((((struct who_list *) v)+i)->desc, 
	 (((struct who_list *) v)+j)->desc);
  (((struct who_list *) v)+i)->level = (((struct who_list *) v)+j)->level;

  bzero((((struct who_list *) v)+j)->desc, SMALL_BUFSIZE);
  strcpy((((struct who_list *) v)+j)->desc, temp.desc);
  (((struct who_list *) v)+j)->level = temp.level;

/*
  temp = v[i];
  v[i] = v[j];
  v[j] = temp;
  */
}


char* numdisplay(int val)
{
  /* Important note:
   * Since a static char is used, do not call this function more than once
   * per (s)printf. Instead break up your (s)printfs for each call to this
   * function.
   */
  static char dispstr[80];
  char temp1[80], temp2[80];
  int i, j, k;

  bzero(temp1, 80);
  bzero(temp2, 80);
  bzero(dispstr, 80);

  sprintf(temp1, "%d", val);
  j = 0; k = 0;
  for (i = (strlen(temp1)-1); i >= 0; i--){
    temp2[j++] = temp1[i];
    if (++k >= 3){
      k = 0;
      if (i > 0 && temp1[(i-1)] != '-')
	temp2[j++] = ',';
    }
  }
  k = 0;
  for (i = (j-1); i >=0 ; i--)
    dispstr[k++] = temp2[i];

  return dispstr;
}

/* Arena mod - Thargor */
/* Remove who from the linked list of observers of an arena combatant */
void deobserve(struct char_data *who)
{
  struct char_data *curr, *prev, *next, *obswho;

  obswho = OBSERVING(who);
  if (obswho == NULL || GET_ARENASTAT(who) != ARENA_OBSERVER)
    return;

  curr = OBSERVING(who);
  prev = curr;
  while (!(curr == NULL || curr == who)){
    next = OBSERVE_BY(curr);
    if (curr != who){
      prev = curr;
      curr = next;
    }
  } 
  if (curr == who){
    next = OBSERVE_BY(curr);
    OBSERVE_BY(prev) = next;
    OBSERVE_BY(curr) = NULL;
  }
  OBSERVING(who) = NULL;
}

/* Arena mod - Thargor */
/* link who to the linked list of observers of an arena combatant 'to'*/
void linkobserve(struct char_data *who, struct char_data *to)
{
  struct char_data *curr;

  curr = to;
  while (OBSERVE_BY(curr))
    curr = OBSERVE_BY(curr);

  OBSERVING(who) = to;
  OBSERVE_BY(curr) = who;
  OBSERVE_BY(who) = NULL;
  
}

/* Arena mod - Thargor */
/* Clear off all observers of a player (who) who's left the arena */
void clearobservers(struct char_data *who)
{
  struct char_data *tmp, *clear;
 
  if (GET_ARENASTAT(who) == ARENA_NOT || GET_ARENASTAT(who) == ARENA_OBSERVER)
    return;

  tmp = who;
  while (tmp != NULL){
    clear = tmp;
    tmp = OBSERVE_BY(clear);
    OBSERVING(clear) = NULL;
    OBSERVE_BY(clear) = NULL;
  }

}
int exp_to_level(arg)
{
  double modifier;
  if (arg < 1 || arg > LVL_IMPL) return 0;
  if (arg < 10)
    modifier = mlog(3,arg);
  else if (arg < 20)
    modifier = mlog(2.9,arg);
  else if (arg < 30)
    modifier = mlog(2.8,arg);
  else if (arg < 40)
    modifier = mlog(2.7,arg);
  else if (arg < 50)
    modifier = mlog(2.6,arg);
  else if (arg < 60)
    modifier = mlog(2.5,arg);
  else if (arg < 70)
    modifier = mlog(2.4,arg);
  else if (arg < 80)
    modifier = mlog(2.3,arg);
  else if (arg < 90)
    modifier = mlog(2.2,arg);
  else if (arg < 96)
    modifier = mlog(2.05,arg);
  else
    modifier = mlog(2,arg);

  if (arg == 1)
    return 3000;
  else
    return 4000 * (arg * modifier)+exp_to_level(arg-1); // was gonna do +exp_to_level(arg-1) but that makes it REAL cpu intense

/*
  if (arg < 10)
    modifier = 1;
  else if (arg < 20)
    modifier = 5;
  else if (arg < 30)
    modifier = 10;
  else if (arg < 40)
    modifier = 20;  
  else if (arg < 50)
    modifier = 30;
  else if (arg < 60)
    modifier = 40;
  else if (arg < 70)
    modifier = 50;
  else if (arg < 80)
    modifier = 60;  
  else if (arg < 90)
    modifier = 80;
  else
    modifier = 250;

 exp = arg * modifier * 4000;
 return exp;
*/
}
/* strips \r's from line */
char *stripcr(char *dest, const char *src) {
  int i, length;
  char *temp;

  if (!dest || !src) return NULL;
  temp = &dest[0];
  length = strlen(src);
  for (i = 0; *src && (i < length); i++, src++)
    if (*src != '\r') *(temp++) = *src;
      *temp = '\0';
  return dest;
}
/* Will return the number of items in the container. */
int count_contents(struct obj_data *container)
{
  int count = 0;
  struct obj_data *obj;

  if (container->contains)
    for (obj = container->contains; obj; obj = obj->next_content, count++)
      if (GET_OBJ_TYPE(obj) == ITEM_CONTAINER && obj->contains)
        count += count_contents(obj);

  return(count);
}

/* Will return the number of items that the character owns. */
int item_count(struct char_data *ch)
{
  int i, count = 0;
  struct obj_data *obj;

  for (i = 0; i < NUM_WEARS; i++) {
    if (GET_EQ(ch, i)) {
      count++;
      if (GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_CONTAINER &&
          GET_EQ(ch, i)->contains)
        count += count_contents(GET_EQ(ch, i));
    }
  }

  if (ch->carrying)
    for (obj = ch->carrying; obj; obj = obj->next_content, count++)
      if (GET_OBJ_TYPE(obj) == ITEM_CONTAINER && obj->contains)
        count += count_contents(obj);

  return(count);
}

void search_replace(char *string, const char *find, const char *replace)
{
        char final[MAX_INPUT_LENGTH], temp[2];
        size_t start, end, i;

        while (strstr(string, find) != NULL) {

                final[0] = '\0';
                start = strstr(string, find) - string;
                end = start + strlen(find);

                temp[1] = '\0';

                strncat(final, string, start);
                
                strcat(final, replace);

                for (i = end; string[i] != '\0'; i++) {
                        temp[0] = string[i];
                        strcat(final, temp);
                }

                sprintf(string, final);

        }
        return;
}

/* OLD Square Root Function
   Heh, I handcoded this when I couldn't get the system SQRT function
   working -- this works fine on a relatively fast system (300MHz+ I
   would guess), but on slower ones it's a turtle when called many
   times.

   I found out that you need to link libm.a (-lm) to the object files
   for math.h's sqrt function to work.
   -Storm

  double sqrt ( double num ) {
    register double i, ci;

    if (!num) return 0;
    i=num/2;
    if (i==1) i+=0.1;
    ci=i;

    while (1) {
      i=num/i;
      i=(ci+i)/2;
      ci=i;
      if (i*i==num) return i;
    }
  }
*/

sh_int a2i(char *vnum)
{
  int i, k, l, n=1;
  sh_int num=0, j;
  l=strlen(vnum);
  i=0;
  if (vnum[0]=='-') {
    n=-1;
    i=1;
  }

  for (; i<strlen(vnum); i++) {
    if ('0'==vnum[i]) j=0;
    else if ('1'==vnum[i]) j=1;
    else if ('2'==vnum[i]) j=2;
    else if ('3'==vnum[i]) j=3;
    else if ('4'==vnum[i]) j=4;
    else if ('5'==vnum[i]) j=5;
    else if ('6'==vnum[i]) j=6;
    else if ('7'==vnum[i]) j=7;
    else if ('8'==vnum[i]) j=8;
    else if ('9'==vnum[i]) j=9;
    else continue;
    for (k=1; k<l; k++)
      j*=10;
    num+=j;
    l--;
  }
  return num*n;
}