#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"
/* 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 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 + 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)) {
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, 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, NULL));
} else {
send_msg (ploc (mynum), 0, max (pvis (mynum), LVL_GOD), LVL_MAX, mynum, NOBODY,
"%s\n", build_setin (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 (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 (xx, cur_player->setmin, pname (mynum), NULL, 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 = 0;
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);
if (ltstflg (newch, LFL_MAZE) && (plev (mynum) < LVL_ARCHWIZARD))
bprintf ("%5s : %-45s : [Maze]\n",
Exits[a], sdesc (newch));
else
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 (!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)
{
setploc (mynum, loc);
lookin (loc, 0);
if (ltstflg (loc, LFL_DEATH)) {
if (plev (mynum) < LVL_WIZARD) {
crapup ("\t\tYou seem to have died...\n", 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));
}
#if (OFL_MAX == 96)
list_objects (OFL_NOGET);
show_weather ();
list_objects (OFL_MAX);
list_people ();
#else
list_objects (1 << OFL_NOGET, True);
show_weather ();
list_objects (1 << OFL_NOGET, False);
list_people ();
#endif
if (ststflg (mynum, SFL_AUTOEXIT)) {
bprintf ("\n");
exitcom ();
}
}
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;
}
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_AVATAR) && plev (plr) < LVL_AVATAR)
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_NOGOTO) && plev (plr) < LVL_GOD)
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;
mudlog ("ERROR: Light LFlag Missing From %s", showname (loc));
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;
}