dyrt/
dyrt/bin/
dyrt/data/MAIL/
dyrt/data/WIZ_ZONES/
dyrt/include/machine/
dyrt/src/misc/cpp/
#include "kernel.h"
#include "locations.h"
#include "objects.h"
#include "exitnames.h"
#include "stdinc.h"

/* A room's short description (title) */
char *sdesc (int room)
{
  return exists (room) ? lshort (room) : "Where no man has gone before";
}

/* A room's long description */
char *ldesc (int room)
{
  return exists (room) ? llong (room) : "";
}

int getexit (int room, int ex)
{
  return lexit (room, ex);
}

/* Set the <dir>-most exit in <room> to <dest>.
 * Return False if the new exit was a room which didn't exist.
 */
void setexit (int room, int dir, int dest)
{
  int i, n;
  
  if (exists (lexit (room, dir)))
    {
      
      for (i = n = 0; i < NEXITS && n <= 1; i++)
	if (lexit (room, i) == lexit (room, dir))
	  ++n;
      
      /* If we are removing the only exit to that room from this: */
      if (n == 1)
	{
	  remove_int (room, lexits_to_me (lexit (room, dir)));
	}
    }
  if (exists (dest))
    {
      add_int (room, lexits_to_me (dest));
    }
  lexit (room, dir) = dest;
  ltouched (room) = True;
}

/*
* return the room number an object is in
* even if it is carried by someone or in something
* [code by Twizzly, July 1995]
*/
int roomobjin(int o)
{
  int i;

  i = oloc(o);
  while( ocarrf(o) == IN_CONTAINER)  /* work our way out of the container */
    {
      o = i;
      i = oloc(o);
    }
  if( ocarrf(o) != IN_ROOM)
    {
      return(ploc(i));
    }
  return i;
}

/* Get a random exit direction from a location, or -1 if none exists. */
int get_rand_exit_dir (int room)
{
  int i, ex[NEXITS], newch, n_exits = 0;
  
  for (i = 0; i < NEXITS; i++)
    {
      if (!exists (lexit (room, i)) &&
	  (lexit (room, i) < DOOR || lexit (room, i) >= EDOOR))
	{
	  continue;
	}
      if (!exists (newch = lexit (room, i)))
	{
	  if (state (newch -= DOOR) > 0)
	    {
	      continue;
	    }
	  else
	    {
	      newch = obj_loc (olinked (newch));
	    }
	}
      /* ex[n_exits++] = newch;  */
      ex[n_exits++] = i;
    }
  return n_exits == 0 ? -1 : ex[my_random () % n_exits];
}

Boolean checklevel (int player, int room)
{
  if (ltstflg(room, LFL_WIZONLY) && (plev(player) < LVL_APPREN)) 
    {
      sendf(player, "I'm sorry, that room is reserved for Immortals.\n");
      return False;
    }
  if (ltstflg(room, LFL_AWIZONLY) && (plev(player) < LVL_ARCHWIZARD))
    {
      sendf(player, "I'm sorry, that room is reserved for Powers.\n");
      return False;
    }
  if (ltstflg(room, LFL_DGODONLY) && (plev(player) < LVL_DEMI))
    {
      sendf(player, "I'm sorry, that room is reserved for Dgod and up.\n");
      return False;
    }
  if (ltstflg(room, LFL_GODONLY) && (plev(player) < LVL_GOD))
    {
      sendf(player, "I'm sorry, that room is reserved for God and up.\n");
      return False;
    }
  return True;
}

/* Get a random exit (the room itself) from a location, or 0 if none exists. */
int get_rand_exit (int room)
{
  int newch;
  int i = get_rand_exit_dir (room);
  
  if (i == -1)
    {
      return 0;
    }
  newch = lexit (room, i);
  return !exists (newch) ? obj_loc (olinked (newch - DOOR)) : newch;
}

int count_players (int loc, int min_lvl, int max_lvl, int flags)
{
  /* Count number of players in a room */
  /* loc == 0 is legal and signify all rooms */
  
  int plx;
  int count = 0;
  int pla, plb;
  Boolean i;
  
  pla = ((flags & COUNT_PLAYERS) != 0) ? 0 : max_players;
  plb = ((flags & COUNT_MOBILES) != 0) ? numchars : max_players;
  i = ((flags & INVERT_LEVELS) != 0);
  
  for (plx = pla; plx < plb; plx++)
    {
      if ((loc == 0 || ploc (plx) == loc) && !EMPTY (pname (plx)))
	{
	  if (plx >= max_players ||
	      ((plev (plx) >= min_lvl && plev (plx) < max_lvl) != i))
	    {
	      ++count;
	    }
	}
    }
  return count;
}

void gotocom (Boolean tiptoe)
{
  char xx[SETIN_MAX];
  int a, pc;
  
  if (!ptstflg (mynum, PFL_GOTO))
    {
      erreval ();
      return;
    }
  if (ltstflg(ploc(mynum),LFL_JAIL) && (plev(mynum) < LVL_ARCHWIZARD)) 
    {
      bprintf ("Just where do you think yer goin...?\n");
      erreval ();
      return;
    }
  if (brkword () == -1)
    {
      if (!exists (a = find_loc_by_id (phome (mynum))))
	{
	  a = randperc () > 50 ? LOC_START_TEMPLE : LOC_START_CHURCH;
	}
    }
  else if ((a = findroomnum (wordbuf)) == 0)
    {
      bprintf ("Unknown Player, object or room\n");
      return;
    }
  if (ltstflg(a, LFL_JAIL) && (plev(mynum) < LVL_ARCHWIZARD)) 
    {
      bprintf ("I don't think that would be a good idea...\n");
      return;
    }
#ifdef LOCMIN_RHOME
  if ((a == LOC_RHOME_15) && (!EQ(pname(mynum), "Rex")))
    {
      bprintf("I'm sorry but you must be invited to this room.\n");
      return;
    }
#endif
  if (!checklevel(mynum,a))
    {
      return;
    }
  if (plev (mynum) < LVL_GOD)
    {
      if (ltstflg (a, LFL_PRIVATE))
	{
	  pc = count_players (a, LVL_MIN, LVL_MAX, COUNT_PLAYERS | COUNT_MOBILES);
	  if (pc > 1)
	    {
	      bprintf ("I'm sorry.  There's a private conference in that "
                       "location.\n");
	      return;
	    }
	}
    }
  if (!tiptoe)
    {
      send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY, "%s\n", 
                build_setin (xx, cur_player->setmout, pname (mynum), NULL));
    }
  setploc (mynum, a);
  trapch (a);
  if (!tiptoe)
    {
      send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY, "%s\n", 
                build_setin (xx, cur_player->setmin, pname (mynum), NULL));
    }
}

int exists (int room)
{
  return (room < 0 && convroom (room) < numloc);
}


/* The EXITS command */
void exitcom ( int check_args )
{
  int a, v, newch;
  int drnum, droff;
  int b = 0;
  char st[64];
  
  int room, exit;
  Boolean gotroom = False, gotexit = False, gotarg;
  
  if( check_args )
  {
    room = !(gotarg = brkword () != -1) ? ploc (mynum) : find_loc_by_name (wordbuf);
  }
  else
  {
    room = ploc( mynum );
    gotarg = False;
  }
  
  if (gotarg && !ptstflg (mynum, PFL_GOTO))
    {
      bprintf ("You aren't powerful enough to give arguments to EXITS.\n");
      return;
    }
  gotroom = exists (room);
  if (!gotroom && !(gotexit = ((exit = tlookup (wordbuf, Exits)) != -1)))
    {
      bprintf ("Non-existant room or exit.\n");
      return;
    }
  if (!check_args || ( !gotexit && brkword () == -1) )
    {
      if (r_isdark (room, mynum))
	{
	  bprintf ("It is dark.....\n");
	  return;
	}
      bprintf ("&+WObvious exits are:&*\n");
      for (a = 0; a < NEXITS; a++)
	{
	  newch = getexit (room, a);
	  if (newch >= DOOR && newch < EDOOR)
	    {
	      /* look through special exits */
	      drnum = newch - DOOR;
	      droff = olinked (drnum);	/*other side */
	      if (!state (drnum))
	        {
		  newch = obj_loc (droff);
		}
	    }
	  if (newch >= 0)
	    {
	      continue;
	    }
	  if (plev (mynum) < LVL_APPREN || (ltstflg(ploc(mynum), LFL_MAZE) &&
	      plev(mynum) < LVL_HIGHARCH))
 	    {
	      bprintf ("%9s : %s\n", Exits[a], sdesc (newch));
	    }
	  else
	    {
	      v = findzone (newch, st);
	      bprintf ("%d:%9s : %-45s : %s%d\n", a, Exits[a], sdesc (newch), st, v);
	    }
	  b = 1;
	}
      if (b == 0)
        {
	  bprintf ("None....\n");
	}
      return;
    }
  if (!gotroom)
    {
      room = ploc (mynum);
    }
  if (lpermanent (room) && !ptstflg (mynum, PFL_ROOM))
    {
      bprintf ("Your are only powerful enough to change exits on\n"
	       "non-permanent (wizard-created) rooms.\n");
      return;
    }
  if (!gotexit && (exit = tlookup (wordbuf, Exits)) == -1)
    {
      bprintf ("Illegal exit-name, use north, east, etc...\n");
      return;
    }
  if (brkword () == -1)
    {
      newch = 0;
    }
  else if (!exists (newch = find_loc_by_name (wordbuf)))
    {
      bprintf ("I don't know that destination.\n");
      return;
    }
  setexit (room, exit, newch);
  bprintf ("Exit %s from %s is now %s.\n", Exits[exit],
	   sdesc (room), (newch == 0) ? "removed" : sdesc (newch));
}

/* Is a room dark or not? It's dark if the Lflag DARK is set but
 * not if there is someone in the room carrying somthing lit.
 */
Boolean roomdark (int room)
{
  int i, j;

  /* ghosts can see in the dark */
  if (ststflg(mynum, SFL_GHOST))
    {
      return False;
    }
  /* if there is a lit wiz in the room, it is light */
  for (i=0; i< lnumchars(room); i++)
    if (ststflg( lmob_nr(i,room), SFL_GLOWING))
      {
        return False;
      }
    /* if LFL_LIGHT, it is never dark */
    if ((xlflags (room) & LFL_L_MASK) == LFL_LIGHT)
      {
        return False;
      }
    /* if REALTIME and not night, it is light */
    if (ltstflg (room, LFL_REALTIME) && !is_real_dark ())
      {
        return False;
      }
    for (i = 0; i < lnumobs (room); i++)
      {
        if (otstbit (lobj_nr (i, room), OFL_LIT) &&
  	   !otstbit (lobj_nr (i, room), OFL_DESTROYED))
 	  {
	    return False;
	  }
      }
    for (i = 0; i < lnumchars (room); i++)
      {
        for (j = 0; j < pnumobs (lmob_nr (i, room)); j++)
  	  {
	    if (otstbit (pobj_nr (j, lmob_nr (i, room)), OFL_LIT) &&
	        !otstbit (pobj_nr (j, lmob_nr (i, room)), OFL_DESTROYED))
	      {
	        return False;
 	      }
 	  }
      }
  return True;
}

/* Determine if a player can see in a room or not. Same as above with the
 * difference that if they are wiz, they will allways be able to see. */
Boolean r_isdark (int room, int plr)
{
  return roomdark (room) && plev (plr) < LVL_APPREN;
}

Boolean isdark ()
{
  return r_isdark (ploc (mynum), mynum);
}

void teletrap (int newch)
{
  if (ltstflg(ploc(mynum),LFL_JAIL) && (plev(mynum) < LVL_ARCHWIZARD)) 
    {
      bprintf ("For some reason, you are still in the jail\n");
      return;
    }
  send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
	    "%s has left.\n", pname (mynum));
  send_msg (newch, 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
	    "%s has arrived.\n", pname (mynum));
  trapch (newch);
}

Boolean trapch (int loc)
{
  setploc (mynum, loc);
  lookin (loc, 0);

  if (ltstflg (loc, LFL_DEATH))
    {
      if (plev (mynum) < LVL_APPREN)
	{
          if (ststflg(mynum, SFL_GHOST)) 
 	    {
              p_crapup (mynum, "\t\tYou fade to nothing, and vanish.", CRAP_SAVE);
              return False; 
            }
          send_msg(DEST_ALL, MODE_QUIET, LVL_APPREN, LVL_MAX, mynum, NOBODY,
	           "&+Y[%s has discovered a new deathroom.]\n", pname(mynum));
	  crapup ("\t\tYou seem to have died...", CRAP_SAVE);
	  return False;
	}
    }
  if (pfighting (mynum) >= 0 && ploc (mynum) != ploc (pfighting (mynum)))
    {
      setpfighting (mynum, -1);
    }
  return True;
}

void lookin (int loc, int showfl)
{
  char wbuff[200];
  char tbuff[50];

  if ((ptstflg (mynum, PFL_GOTO) || plev (mynum) >= LVL_APPREN))
    {
      sprintf (wbuff, "<%s>", showname (loc));
    }
  if ((!ststflg (mynum, SFL_BRIEF) && plev (mynum) >= LVL_APPREN))
    {
      /* show some of the usefull flags */
      if ((xlflags (loc) & LFL_L_MASK) == LFL_DARK)
	{
          if (roomdark (loc))
            {
              /* location is really dark */
              strcat (wbuff, " DARK ");
            }
          else
            {
              /* location is dark but there is light present */
              strcat (wbuff, " dark ");
 	    }
 	}
      if (ltstflg (loc, LFL_DEATH))
	{
          strcat (wbuff, " DEATH ");
	}
      if (ltstflg (loc, LFL_PRIVATE))
	{
          strcat (wbuff, " PRIVATE ");
	}
      if (ltstflg (loc, LFL_PARTY))
	{
          strcat (wbuff, " PARTY ");
	}
      if (ltstflg (loc, LFL_ON_WATER))
	{
          strcat (wbuff, " ON-WATER ");
	}
      if (ltstflg (loc, LFL_IN_WATER))
	{
          strcat (wbuff, " IN-WATER ");
	}
      /* display weather and temperature at the location */
      strcat (wbuff, " [");
      strcat (wbuff, real_light_state (loc));
      strcat (wbuff, "]");
      if (strncmp (real_temp_state (loc), "Very Hot", 8) == 0)
	{
          strcat (wbuff, " [");
	}
      if (strncmp (real_temp_state (loc), "Hot", 3) == 0)
	{
          strcat (wbuff, " [");
	}
      if (strncmp (real_temp_state (loc), "Warm", 4) == 0)
	{
          strcat (wbuff, " [");
	}
      if (strncmp (real_temp_state (loc), "Cool", 4) == 0)
	{
          strcat (wbuff, " [");
	}
      if (strncmp (real_temp_state (loc), "Cold", 4) == 0)
	{
          strcat (wbuff, " [");
	}
      if (strncmp (real_temp_state (loc), "Very Cold", 9) == 0)
	{
          strcat (wbuff, " [");
	}
      strcat (wbuff, real_temp_state (loc));
      strcat (wbuff, "]");
    }

  /* now print out the buffer that we have built up */
  if ((ptstflg (mynum, PFL_GOTO) || plev (mynum) >= LVL_APPREN))
    {
      strcat (wbuff, "\n");
      bprintf (wbuff);
    }

/* now print out what the mortals see */
  if (ststflg (mynum, SFL_BLIND))
    {
      bprintf ("You're blind, you can't see a thing!\n");
    }
  else
    {
      if (isdark ())
        {
          bprintf ("It's dark.  Be careful or you may be eaten by a Grue!\n");
          return;
        }
      else
        {
          bprintf ("%s\n", sdesc (loc));
        }
    }

  /* print out the description of the room as long as the player can see */
  if (!isdark () && !ststflg (mynum, SFL_BLIND))
    {
      if ((showfl & SHOW_LONG) != 0 || ststflg (mynum, SFL_BRIEF) == 0)
        {
          bprintf ("%s", ldesc (loc));
        }
      list_objects (1 << OFL_NOGET, True);
      show_weather ();
      list_objects (1 << OFL_NOGET, False);
      list_people ();
      bprintf ("\n");
      if (ststflg (mynum, SFL_AUTOEXIT))
 	{
          exitcom ( 0 );
	}
    }
  bprintf ("\n");
}

char *showname (int loc)
{
  static char a[64];

  return xshowname (a, loc);
}

char *xshowname (char *b, int loc)
{
  char v[64];
  
  sprintf (b, "%s", buildname (v, loc));
  return b;
}

char *buildname (char *b, int loc)
{
  int k;
  char n[64];
  
  k = findzone (loc, n);
  sprintf (b, "%s%d", n, k);
  return b;
}

/* Find Location By Name
 *
 * Name is either <zonename/abbrev><offsett>    (for instance "cat44")
 *             or <absolute room number>        (for instance "-233")
 *
 * Return location, or 0 on error, or 1 if correct zonename (only) was given.
 */
int find_loc_by_name (char *name)
{
  int y;
  char buff[MAX_COM_LEN], *b = buff;
  char *p = name;
  int n;
  
  while (isalpha (*p))
    *b++ = *p++;
  *b = '\0';
  n = atoi (p);
  if (*buff == '\0')
    {
      return exists (n) ? n : 0;
    }
  if ((y = get_zone_by_name (buff)) != -1)
    {
      return n == 0 ? 1 : getlocid (y, n);
    }
  else
    {
      return 0;
    }
}

/*
 * Basic function to find a room number from: 1) zonename<offset>,
 *                                        or  2) mobile/player
 *                                        or  3) object
 *                                        or  4) zonaname (no offset, assumes1)
 * Return room number, or 0 on error.
 */
int findroomnum (char *w)
{
  int loc, a;
  
  while (*w != 0 && *w != '-' && !isalnum (*w))
    ++w;
  if ((loc = find_loc_by_name (w)) < 0)
    {
      return loc;
    }
  else if ((a = fpbn (w)) != -1)
    {
      return ploc (a);
    }
  else if ((a = fobn (w)) != -1)
    {
      return obj_loc (a);
    }
  else if (loc == 1)
    {
      return getlocnum (w, 1);
    }
  else
    return 0;
}

/* Same as findroomnum(), but use brkword() and wordbuf. */
int getroomnum ()
{
  return (brkword () == -1) ? 0 : findroomnum (wordbuf);
}


/* Find location's in-game index from its ID.  Return 0 if not found. */
int find_loc_by_id (long int id)
{
  long int x;
  
  if (id < 0 && convroom (id) < num_const_locs)
    {
      return id;
    }
  return (x = lookup_entry (id, &id_table)) == NOT_IN_TABLE
          || !exists (x) ? 0 : x;
}

Boolean cango (int d)
{
  if (getexit (ploc (mynum), d) == 0)
    {
      return False;
    }
  if (getexit (ploc (mynum), d) < 0)
    {
      return True;
    }
  if (getexit (ploc (mynum), d) < DOOR)
    {
      return False;
    }
  if (state (getexit (ploc (mynum), d) - DOOR) == 0)
    {
      return True;
    }
  return False;
}

Boolean reset_location (int loc)
{
  Boolean missing_exit = False;
  
  xlflags (loc) = xlflags_reset (loc);
  if (ltouched (loc))
    {
      int i, x;
      for (i = 0; i < NEXITS; i++)
	{
	  missing_exit |= (x = lexit_reset (loc, i)) != 0 &&
	                  (x < DOOR || x > EX_MAX) &&
		          (x = find_loc_by_id (x)) == 0;
	  setexit (loc, i, x);
	}
      ltouched (loc) = False;
    }
  return !missing_exit;
}