pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
#define ROOMS_C

#include "kernel.h"
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "exitnames.h"
#include "lflags.h"
#include "rooms.h"
#include "mobile.h"
#include "sendsys.h"
#include "sflags.h"
#include "pflags.h"
#include "cflags.h"
#include "oflags.h"
#include "calendar.h"
#include "objsys.h"
#include "zones.h"
#include "bprintf.h"
#include "parse.h"
#include "fight.h"
#include "uaf.h"
#include "special.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.
 * Used in things like moving mobiles and flee-code
 */
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++] = i;
  }
  return n_exits == 0 ? -1 : ex[MY_RANDOM () % n_exits];
}

void get_exit_locs_from(int loc, int *loctable, Boolean through_doors)
{   int i, newch,drnum,droff;
     
    for (i = 0; i < NEXITS; i++)
    {  newch = getexit (loc, i);
       if (newch >= DOOR && newch < EDOOR)
       {  /* look through special exits */
	      
	   drnum = newch - DOOR;
	   droff = olinked (drnum);	/*other side */
	   if (!state (drnum) || through_doors)
		newch = obj_loc (droff);
       }
       loctable[i] = newch;
    }
}

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.
 * Note: This differs from get_rand_exit_dir in that this already returns the
 * exit location, while get_rand_exit_dir return the direction.
 */
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+100];
  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 you are going??\n");
     erreval();
     return;
  }
  if (brkword () == -1)
  {  if (!exists (a = find_loc_by_id (phome (mynum))))
     {  bprintf("Goto where?\n");
        return;
     }
  }
  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 will be a good idea.\n");
     return;
  }  
  if (!checklevel(mynum,a))
    return;

  if (!has_access_to(mynum,a,-1))
  {   bprintf("You can't transport to unknown grounds.\n");
      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 (rom_fun(a) != NULL)
  {   param_s.plx = mynum;
      param_s.loc = a;
      param_s.ret = 1;
      rom_fun(a)(E_ONENTRY);
      if (param_s.ret != 1)
        return;
  }
 
  if (!tiptoe)
     send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
		"%s\n", build_setin (mynum,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 (mynum,xx, cur_player->setmin, pname (mynum), NULL));
}


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

/* The EXITS command
 */
A_COMMAND(exitcom)
{  show_exits(True);
}

void show_exits(Boolean check_line)
{ int a, v, newch;
/*  int drnum, droff;*/
  int b = 0;
  char st[120];
  int  e[NEXITS];
  Boolean shortexits;
  int room, exit = 0;
  Boolean gotroom = False, gotexit = False, gotarg;
 
  if (!check_line)
  {  gotarg = False;
     room = ploc(mynum);
  }
  else 
  {
     room = !(gotarg = (brkword () != -1)) ? ploc (mynum) : find_loc_by_name (wordbuf);
  }

  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 (!gotexit && brkword () == -1)
  {  if (r_isdark (room, mynum))
     {  bprintf ("It is dark.....\n");
        return;
     }
     shortexits = ststflg(mynum,SFL_SHORTEXIT);

     get_exit_locs_from(room,e,False);

     b = 0;
     bprintf ("&+wObvious exits are: &*");

     for (a = 0; a < NEXITS; a++)
     {  if (e[a] >= 0)
           continue;
        
        if (shortexits)
              bprintf("&+w%s   ",Exits[a]);
        else if (plev (mynum) < LVL_APPREN || 
	        (ltstflg(ploc(mynum), LFL_MAZE) &&
	         plev(mynum) < LVL_ARCHWIZARD))
	        bprintf ("\n&+w[&+w%-9.9s&+w] &+w: &+w%s", Exits[a], sdesc (e[a]));
        else
        {  v = findzone (e[a], st);
	      bprintf ("\n&+w[&+w%-9.9s&+w] &+w%-50s : %s%d",
	               Exits[a], sdesc (e[a]), st, v);
        }
        b = 1;
     }
     if (b == 0) 
     {  if (!shortexits)
                 bprintf("\n");
          bprintf ("None....");
     }
     bprintf("\n");
     return;
  }
  if (!gotroom)
    room = ploc (mynum);
 
  if (ltstflg(room,LFL_JAIL) && plev(mynum) < LVL_ARCHWIZARD)
  {  bprintf ("If only that was true...\n");
     return;
  }
 
  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;

  /* 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 (check_light(room) == LFL_LIGHT)
/*
  if (lmaskflg(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_MAGICLIT)) &&
	  !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_MAGICLIT)) &&
	   !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 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));
  stp = 0;
  strbuf[stp] = '\0'; 
  trapch (newch);
}


Boolean trapch (int loc)
{ stp = 0;
  strbuf[stp] = '\0' ;     /* Exits bug fix */
  setploc (mynum, loc);
  lookin (loc, 0);

  if (ltstflg (loc, LFL_DEATH))
  {  if (plev (mynum) < LVL_APPREN)
     {  send_msg(DEST_ALL,MODE_QUIET|MODE_BRACKET,Max(pvis(mynum),LVL_APPREN),LVL_MAX,
                 mynum,NOBODY,"%s has found a death room",
                 pname(mynum)); 
        up_pdied(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)
{ int dark = isdark();

  if (ststflg (mynum, SFL_BLIND))
    bprintf ("You're blind, you can't see a thing!\n");
  else
  {  if (ptstflg (mynum, PFL_GOTO) || plev (mynum) >= LVL_APPREN)
     {  bprintf ("Location: %s - %s", showname (loc),
		 ststflg(mynum,SFL_BRIEF) ? "\n" : "");
	if (roomdark (loc) && plev (mynum) >= LVL_APPREN)
	    bprintf ("(Dark)");
     }
     if (dark)
     {  bprintf ("It's dark.  Be careful or you may be eaten by a Grue!\n");
        return;
     }
     else
     {  if (!ststflg (mynum, SFL_BRIEF) && plev (mynum) >= LVL_APPREN)
	    bprintf ("%s - %s\n%s\n",
		     real_light_state (loc),
		     real_temp_state (loc),
		     sdesc(loc));
        else
           bprintf("%s\n",sdesc(loc));
     }
  }
  
  
  if (ltstflg (loc, LFL_DEATH) && plev (mynum) >= LVL_APPREN)
      bprintf ("(DEATH) ");
  
  if (plev (mynum) >= LVL_APPREN && ltstflg (loc, LFL_PRIVATE))
    bprintf ("(PRIVATE) ");
  if (plev (mynum) >= LVL_APPREN && ltstflg (loc, LFL_PARTY))
    bprintf ("(PARTY) ");

  if (!dark && !ststflg (mynum, SFL_BLIND))
  {  if ((showfl & SHOW_LONG) != 0 || ststflg (mynum, SFL_BRIEF) == 0)
        bprintf ("\n%s", ldesc (loc));

     list_objects(OFL_NOGET,True);
     show_weather ();
     list_objects (MAX_OFLAG,True);
     list_people ();
  }
  bprintf ("\n");
  if (ststflg(mynum, SFL_AUTOEXIT))
  {  show_exits(False);
     bprintf("\n");
  }
}

char *showname (int loc)
{ static char a[255];
  
  return xshowname (a, loc);
}

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

char *buildname (char *b, int loc)
{ int k;
  char n[255];
  
  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);
  */
  xlflags(loc).b1 = xlflags_reset(loc).b1;
  xlflags(loc).b2 = xlflags_reset(loc).b2;
  xlflags(loc).b3 = xlflags_reset(loc).b3;

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


int check_light(int loc)
{   if (ltstflg(loc,LFL_LIGHT))
       return LFL_LIGHT;
    else if (ltstflg(loc,LFL_DARK))
       return LFL_DARK;
    else if (ltstflg(loc,LFL_L_REAL))
       return LFL_L_REAL;

    return LFL_LIGHT;
}

int check_temp(int loc)
{  if (ltstflg(loc,LFL_T_ORDINARY))
      return LFL_T_ORDINARY;
   else if (ltstflg(loc,LFL_HOT))
      return LFL_HOT;
   else if (ltstflg(loc,LFL_COLD))
      return LFL_COLD;
   else if (ltstflg(loc,LFL_T_REAL))
      return LFL_T_REAL;

   return LFL_T_ORDINARY;
}