cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
#include <stdlib.h>
#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 "climate.h"
#include "parse.h"
#include "mobile.h"
#include "objsys.h"
#include "zones.h"
#include "exitnames.h"
#include "bprintf.h"
#include "mobile.h"
#include "fight.h"
#include "uaf.h"
#include "log.h"
#include "mudmacros.h"
#include "mobiles.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, 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 flags) {
  int i, ct, mob;

  for (i = 0, ct = 0, mob = lfirst_mob(loc) ; ct < lnumchars(loc) ; 
    mob = lmob_nr(++ct, loc)) {
    if (flags & COUNT_PLAYERS) {
      if (mob < max_players || ststflg(mob, SFL_OCCUPIED))
        i++;
    }
    if (flags & COUNT_MOBILES) {
      if (mob >= max_players && !ststflg(mob, SFL_OCCUPIED))
        i++;
    }
  }
  return(i);
}

void gotocom (Boolean tiptoe) {
  char xx[SETIN_MAX + 200];
  int a, 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 (chkroom (a, mynum) || 
      (ltstflg(a, LFL_NOGOTO) && plev (mynum) < LVL_GOD)) {
    bprintf ("A magical force prevents you from entering that room.\n");
    return;
  }
  if (plev (mynum) < LVL_GOD) {
    if (ltstflg (a, LFL_PRIVATE)) {
      pc = count_players (a, COUNT_PLAYERS);
      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 (SETIN_SETMOUT, xx, cur_player->setmout, 
              pname (mynum), NULL, NULL));
  else
    send_msg (ploc (mynum), 0, max (pvis (mynum), LVL_GOD), LVL_MAX, mynum, 
              NOBODY, "%s\n", build_setin (SETIN_SETMOUT, xx,
              cur_player->setmout, pname (mynum), NULL, NULL));

  setploc (mynum, a);
  trapch (a);

  if (!tiptoe) {
    check_follow ();
    send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
      "%s\n", build_setin (SETIN_SETMIN, xx, cur_player->setmin, pname(mynum), 
      NULL, NULL));
  }
  else
    send_msg (ploc (mynum), 0, max (pvis (mynum), LVL_GOD), LVL_MAX, mynum, 
      NOBODY, "%s\n", build_setin (SETIN_SETMIN, xx, cur_player->setmin,
      pname (mynum), NULL, NULL));
}


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

void exitcom (Boolean use_args) {
  int a, v, newch;
  int drnum, droff;
  int b = 0;
  char st[64];

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

  if( use_args ) {
    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;
    }
  }
  else
    room = ploc(mynum);
  gotroom = exists (room);

  if (!gotroom && !(gotexit = ((exit = tlookup (wordbuf, Exits)) != -1))) {
    bprintf ("Non-existant room or exit.\n");
    return;
  }
  if ((!gotexit && brkword () == -1) || !use_args ) {
    if (r_isdark (room, mynum)) {
      bprintf ("It is dark.....\n");
      return;
    }
    if(ststflg(mynum, SFL_BLIND) && plev(mynum) < LVL_WIZARD) {
      bprintf("You are blind.\n");
      return;
    }
    bprintf ("&+CObvious exits are:\n");
 
    for (a = 0; a < 6; a++) {
      newch = getexit (room, a);
      if (newch >= DOOR && newch < EDOOR) {
	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 ("  &+y%-5s &+Y: &+G%s\n", Exits[a], sdesc (newch));
      else {
	v = findzone (newch, st);
	if (ltstflg (newch, LFL_MAZE) && (plev (mynum) < LVL_ARCHWIZARD))
	  bprintf ("  &+y%-5s &+Y: &+G%-45s &+Y: [Maze]\n",
		   Exits[a], sdesc (newch));
	else
	  bprintf ("  &+y%-5s &+Y: &+G%-45s &+Y: &+c%s%d %s\n",
		   Exits[a], sdesc (newch), st, v,
		   (ltstflg( newch, LFL_DEATH ) ) ? "&+r<&+LD&+r>&N" : "" );

      }
      b = 1;
    }
    if (b == 0)
      bprintf ("&+RNone....\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 || !use_args) {
    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 (!ltstflg (room, 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;
    }
  }

  for (i = 0; i < max_players; ++i) {
    if (ststflg (i, SFL_LIT))
      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) {
  int ct, mob;

  setploc (mynum, loc);
  lookin (loc, 0);
  if (ltstflg (loc, LFL_DEATH)) {
    if (plev (mynum) < LVL_WIZARD) {
      quit_msg("You seem to have died...", "Deathroom");
      quit_player(False);
      return False;
    }
  }

  if (pfighting (mynum) != -1 && ploc (mynum) != ploc (pfighting (mynum)))
    setpfighting (mynum, -1);

  for (ct = 0; ct < lnumchars (loc); ct++) {
    mob = lmob_nr(ct,loc);
    if (pangry(mob) == mynum && pstr(mob) >= 0 && mob >= max_players) {
      bprintf("%s says, &+W\"&+YSo we meet again..&+W\"\n", pname(mob));
      hit_player(mob, mynum, pwpn(mob));
    }
  }
  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)) {
      if (plev(mynum) >= LVL_DEMI)
        bprintf("&+M%s &+B[&+C%s@%s&+B] &+Y[&+WAltitude: &+B%d&+Y]&N\n",
              showname(loc), room_data[convroom(loc)].r_name, 
              zname(loc2zone(ploc(mynum))), laltitude(loc));
      else
        bprintf("&+M%s &+Y[&+WAltitude: &+B%d&+Y]&N\n", 
                showname(loc), laltitude(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 ("&+g%s\n", sdesc (loc));
  }

  if (ltstflg (loc, LFL_DEATH) && plev (mynum) >= LVL_WIZARD)
    bprintf ("&+r[DEATH] ");
  if (plev (mynum) >= LVL_WIZARD && ltstflg (loc, LFL_PRIVATE))
    bprintf ("&+W[PRIVATE] ");
  if (plev (mynum) >= LVL_WIZARD && ltstflg (loc, LFL_PARTY))
    bprintf ("&+M[PARTY] ");

#include "lookin.h"

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

    show_weather();
    list_objects ();
    list_people ();

    if (ststflg (mynum, SFL_AUTOEXIT)) {
      bprintf ("\n");
      exitcom (False);
    }
  }
  bprintf ("\n");

  if (mynum < max_players && pfollow(mynum) != -1)
    bprintf(cur_player->cprompt);
}

char *showname (int loc)
{
  int k;
  char n[64];
  static char b[66];

  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 = fmbn (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);
  laltitude(loc) = laltitude_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;
}

Boolean
chkroom (int a, int plr)
{

  if (ltstflg (a, LFL_WIZARD) && plev (plr) < LVL_WIZARD)
    return True;

  if (ltstflg (a, LFL_AWIZ) && plev (plr) < LVL_ARCHWIZARD)
    return True;

  if (ltstflg (a, LFL_SHALAFI) && plev (plr) < LVL_SHALAFI)
    return True;

  if (ltstflg (a, LFL_GOD) && plev (plr) < LVL_GOD)
    return True;

  if (ltstflg (a, LFL_NOINVIS) && pvis (plr) != 0)
    return True;

  if (ltstflg (a, LFL_OWNER) && !EQ (pname (plr), lowner (a)))
    return True;

  return False;
}

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

  if (ltstflg (loc, LFL_DARK))
    return LFL_DARK;

  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;

  if (ltstflg (loc, LFL_HOT))
    return LFL_HOT;

  if (ltstflg (loc, LFL_COLD))
    return LFL_COLD;

  if (ltstflg (loc, LFL_T_REAL))
    return LFL_T_REAL;

  return LFL_T_ORDINARY;
}