/
dirt31/
dirt31/bin/
#include "kernel.h"
#include "locations.h"
#include "objects.h"
#include "pflags.h"
#include "oflags.h"
#include "lflags.h"
#include "cflags.h"
#include "sflags.h"
#include "sendsys.h"
#include "rooms.h"
#include "weather.h"
#include "parse.h"
#include "mobile.h"
#include "objsys.h"
#include "zones.h"
#include "exitnames.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;
}


/* 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, door, 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];
}


/* 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, i, pc;

  if (!ptstflg(mynum,PFL_GOTO)) {
    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 (plev(mynum) < LVL_GOD) {      /* a change from 4.98.3 -> 4.98.4 */
    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 a, v, newch;
  int drnum, droff;
  int b = 0;
  char st[64];

  int room, exit;
  Boolean gotroom = False, gotexit = False, gotarg;

  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;
	  }
	  bprintf("Obvious exits are:\n");
	  for (a = 0; a < 6; 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_WIZARD)
		    bprintf("%5s : %s\n", Exits[a], sdesc(newch));
		  else {
			  v = findzone(newch, st);
			  bprintf("%5s : %-45s : %s%d\n",
				  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;

    if ((xlflags(room) & LFL_L_MASK) != LFL_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_WIZARD;
}

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



void teletrap(int newch)
{
  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_WIZARD) {
      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)
{
  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_WIZARD) {
      bprintf("%s\n", showname(loc));
      if (roomdark(loc) && plev(mynum) >= LVL_WIZARD)
        bprintf("[DARK]\n");
    }
    if (isdark()) {
      bprintf("It's dark.  Be careful or you may be eaten by a Grue!\n");

      return;
    } else {
      bprintf("%s\n", sdesc(loc));
    }
  }

  if (ltstflg(loc, LFL_DEATH) && plev(mynum) >= LVL_WIZARD) {
    bprintf("[DEATH]\n");
  }
  if (plev(mynum) >= LVL_WIZARD && ltstflg(loc, LFL_PRIVATE))
    bprintf("[PRIVATE]\n");
  if (plev(mynum) >= LVL_WIZARD && ltstflg(loc, LFL_PARTY))
    bprintf("[PARTY]\n");
  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");
}

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