/*
Copyright (C)1991, Marcus J. Ranum. All rights reserved.
*/
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include "mud.h"
#include "sbuf.h"
#include "vars.h"
#include "look.h"
static void say_other ();
static void say_name ();
static int known (char *att);
/*
this is to enable/disable TinyMUD-style object IDs after looked at stuff
which means you do a lock evaluation every time you look at something. UGH!
*/
#ifdef LOOK_OBJECT_IDS
#define DISPLAY_NAME(who,ob,showoid) say_name(who,ob,showoid)
#else
#define DISPLAY_NAME(who,ob,junk) say(who,ut_name(ob),"\n",(char *)0)
#endif
#define ISDARK(obj) (ut_flagged((obj),var_isdark))
/*
* Setup macro for whether a player is a valid
* player or not, given who is calling and the
* look flags. If ignoring unconnected players,
* the check ensures that the player isn't the
* current player, that the player isn't DARK,
* and that either unconnected players are
* to be shown or the player is connected.
* Note that the DARK check uses the macro defined
* above.
*
* If ignoring unconnected players, the check
* just ensures that the player isn't DARK, using
* the ISDARK macro.
*/
#ifdef CONNONLY
#define VALID_PLAYER(who,ply,flg) \
(strcmp((who),(ply)) && \
(!ISDARK((ply))) && \
(((flg) & LOOK_UNCONN) || playerconn((ply))))
#else
#define VALID_PLAYER(who,ply,flg) \
(strcmp((who),(ply)) && \
(!ISDARK((ply))))
#endif
/* look at something */
void lookat (char *who, char *thing, int flg)
{
char nxtu[MAXOID];
char *dp;
/* flagged to print the thing's name */
if (flg & LOOK_NAME) {
DISPLAY_NAME (who, thing, (ut_flagged (who, var_wiz)
|| ut_isobjown (who, thing)
|| !bool_locked (who, thing, (char *) 0, var_link, 1)));
}
dp = ut_getatt (thing, 0, typ_str, var_desc, (char *) 0);
if (dp == (char *) 0) {
say (who, "You see nothing special.\n", (char *) 0);
} else {
say (who, dp, "\n", (char *) 0);
}
#ifdef TINYHACK
/* This revolting little bit of cat vomit is for compatibility with */
/* converted Tiny* style databases. The code that is commented out */
/* would be the "right thing" to do if you were really going to do */
/* this. The working stuff is the minimum that needs to be done. */
if (ut_flagged (thing, var_isroom)) {
int ac = 0;
char *av[2];
av[0] = av[1] = (char *) 0;
if (bool_locked (who, thing, thing, var_lock, 0)) {
(void) activate (ACTIV_PONLY, who, thing, thing, var_fail, ac, av);
(void) activate (ACTIV_ECAST, who, thing, thing, var_ofail, ac, av);
} else {
(void) activate (ACTIV_PONLY, who, thing, thing, var_succ, ac, av);
(void) activate (ACTIV_ECAST, who, thing, thing, var_osucc, ac, av);
}
}
#endif
/* Don't show any lists if this thing is dark */
if (ISDARK (thing))
return;
/* players? */
dp = ut_getatt (thing, 0, typ_list, var_ply, (char *) 0);
if ((flg & LOOK_PLAY) && dp != (char *) 0) {
int numdisp = 0;
char *savelst = dp;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (VALID_PLAYER (who, nxtu, flg))
numdisp++;
if (numdisp > 0) {
say (who, "Players:\n", (char *) 0);
dp = savelst;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (VALID_PLAYER (who, nxtu, flg))
DISPLAY_NAME (who, nxtu, 0);
}
}
#ifdef COMBAT
dp = ut_getatt (thing, 0, typ_obj, var_weapon, (char *) 0);
if (dp != (char *) 0 && !ISDARK (dp))
say (who, "Wielding: ", ut_name (dp), "\n", (char *) 0);
#endif
/* carrying or contents? */
dp = ut_getatt (thing, 0, typ_list, var_cont, (char *) 0);
if ((flg & (LOOK_CARRY | LOOK_CONT)) && dp != (char *) 0) {
int numdisp = 0;
char *savelst = dp;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (!ISDARK (nxtu))
numdisp++;
if (numdisp > 0) {
if (flg & LOOK_CARRY)
say (who, "Carrying:\n", (char *) 0);
else
say (who, "Contents:\n", (char *) 0);
dp = savelst;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (!ISDARK (nxtu))
DISPLAY_NAME (who, nxtu, 0);
}
}
/* wearing */
dp = ut_getatt (thing, 0, typ_list, var_wearing, (char *) 0);
if ((flg & LOOK_CARRY) && dp != (char *) 0) {
int numdisp = 0;
char *savelst = dp;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (!ISDARK (nxtu))
numdisp++;
if (numdisp > 0) {
say (who, "Wearing:\n", (char *) 0);
dp = savelst;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (!ISDARK (nxtu))
DISPLAY_NAME (who, nxtu, 0);
}
}
#ifdef LIST_EXITS
/* Listing of non dark exits added by Ed Hand 6/27/91 */
dp = ut_getatt (thing, 0, typ_list, var_xit, (char *) 0);
if ((flg & LOOK_NAME) && dp != (char *) 0) {
int numdisp = 0;
char *savelst = dp;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (!ISDARK (nxtu))
numdisp++;
if (numdisp > 0) {
say (who, "Obvious Exits:\n", (char *) 0);
dp = savelst;
while ((dp = lstnext (dp, nxtu, sizeof (nxtu))) != (char *) 0)
if (!ISDARK (nxtu))
DISPLAY_NAME (who, nxtu, 0);
}
}
#endif /* LIST_EXITS */
/* using? */
dp = ut_getatt (thing, 0, typ_obj, var_using, (char *) 0);
if ((flg & LOOK_USING) && dp != (char *) 0 && !ISDARK (dp))
(void) say_attribute (who, thing, var_using, (char *) 0, 0);
}
static void say_name (char *who, char *ob, int showoid)
{
if (showoid)
say (who, ut_name (ob), "(", ob, ")\n", (char *) 0);
else
say (who, ut_name (ob), "\n", (char *) 0);
}
/*
ob - name or OID of the object
att -the attribute to look for
title - optional title, overrides default
showoid - show object ids?
*/
int say_attribute (char *who, char *ob, char *att, char *title, int showoid)
{
char tbuf[MAXOID]; /* buffer for the title */
Obj *op; /* pointer to the object */
char *atp; /* pointer to the attribute */
char *atd;
if ((op = cache_get (ob)) == (Obj *) 0)
return (1);
if ((atp = objattr (op, att, (int *) 0)) == (char *) 0)
return (1);
atd = attdata (atp);
/* possibly generate a title */
if (title == (char *) 0) {
fndvnam (att, tbuf, sizeof (tbuf));
title = tbuf;
}
/* here we have to use the stretchy-buffer version of listnext */
if (attistype (atp, typ_list)) { /* a list? */
Sbuf sb;
if (atd == (char *) 0 || *atd == '\0')
return (1);
say (who, title, ":\n", (char *) 0);
sbuf_initstatic (&sb);
while ((atd = lstnextsbuf (atd, &sb)) != (char *) 0)
say_name (who, sbuf_buf (&sb), showoid);
sbuf_freestatic (&sb);
} else if (attistype (atp, typ_obj)) { /* an object? */
if (atd == (char *) 0 || *atd == '\0')
return (1);
say (who, title, ": ", (char *) 0);
say_name (who, atd, showoid);
} else if (attistype (atp, typ_flag)) { /* a flag? */
say (who, title, " ", (char *) 0);
} else if (attistype (atp, typ_cmd)) { /* a command? */
if (atd == (char *) 0 || *atd == '\0')
return (1);
say (who, title, "(macro): ", atd, "\n", (char *) 0);
} else if (attistype (atp, typ_u)) { /* U-code? */
if (atd == (char *) 0 || *atd == '\0')
return (1);
say (who, title, "(U-code): ", atd, "\n", (char *) 0);
} else {
if (atd == (char *) 0 || *atd == '\0')
return (1);
say (who, title, ": ", atd, "\n", (char *) 0);
}
return (0);
}
static void say_other (char *who, char *ob)
{
char aname[MAXOID];
Obj *op; /* pointer to the object */
int a;
if ((op = cache_get (ob)) == (Obj *) 0)
return;
for (a = 0; a < (int) op->ocnt; a++) {
if (attname (op->oap[a], aname) == 0 && !known (aname)) /* an unknown! */
(void) say_attribute (who, ob, aname, aname, 1);
}
}
/* attributes in the order you want to to see them */
static char *flgs[] = {
var_isroom, var_isplay, var_wiz, var_isdark,
var_islocal,
#ifdef COMBAT
var_isdead, var_isweapon, var_isarmor,
#endif
0
};
static char *atts[] = {
var_nam, var_desc, var_text, var_owner,
var_ply, var_cont, var_using, var_xit,
var_lock, var_link, var_succ, var_osucc,
var_fail, var_ofail, var_drop, var_odrop,
var_loc, var_dest, var_home, var_dropto,
var_newsart, var_subive, var_objive, var_posive,
#ifdef COMBAT
var_weapon,
#endif
var_pass, 0
};
static int known (char *att)
{
char **ap;
for (ap = flgs; *ap != (char *) 0; ++ap)
if (strcmp (att, *ap) == 0)
return (2);
for (ap = atts; *ap != (char *) 0; ++ap)
if (strcmp (att, *ap) == 0)
return (1);
return (0);
}
int do_examine (char *who, char *aswho, char *ob)
{
char **ap;
if (ut_flagged (ob, var_isplay)) {
say (who, "A player", (char *) 0);
} else if (ut_flagged (ob, var_isroom)) {
say (who, "A room", (char *) 0);
} else
if (lstlook (ut_getatt (ob, 0, typ_list, var_loc, var_xit, (char *) 0),
ob)) {
say (who, "An exit", (char *) 0);
} else {
say (who, "An object", (char *) 0);
}
say (who, " named: ", (char *) 0);
say_name (who, ob, 1);
if (!ut_flagged (aswho, var_wiz) && !ut_isobjown (aswho, ob)) {
char *here, *there;
here = ut_loc (aswho);
there = ut_loc (ob);
if (!strcmp (here, there) || !strcmp (here, ob) || !strcmp (there, aswho)) {
(void) say_attribute (who, ob, var_desc, (char *) 0, 0);
(void) say_attribute (who, ob, var_owner, (char *) 0, 1);
}
return (0);
}
say (who, "Flags: ", (char *) 0);
for (ap = flgs; *ap != (char *) 0; ++ap)
(void) say_attribute (who, ob, *ap, (char *) 0, 0);
say (who, "\n", (char *) 0);
for (ap = atts + 1; *ap != (char *) 0; ++ap)
(void) say_attribute (who, ob, *ap, (char *) 0, 1);
say_other (who, ob);
return (0);
}