/
umud/DOC/
umud/DOC/examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
/*
	Copyright (C)1991, Marcus J. Ranum. All rights reserved.
*/

#ifndef	lint
static	char	RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/do_look.c,v 1.6 91/10/22 11:29:24 mjr Exp $";
#endif

#include <ctype.h>

/* configure all options BEFORE including system stuff. */
#include	"config.h"


#include	"mud.h"
#include	"vars.h"
#include	"look.h"

static void	say_other();
static void	say_name();


/*
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(who,thing,flg)
char	*who;
char	*thing;
int	flg;
{
	char	nxtu[MAXOID];
	char	*dp;
	char	*linkok;
	
	/* 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)) != (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)) != (char *)0)
				if(VALID_PLAYER(who,nxtu,flg))
					DISPLAY_NAME(who,nxtu,0);
		}
	}

	/* 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)) != (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)) != (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)) != (char *)0)
			if(!ISDARK(nxtu))
				numdisp++;
		
		if(numdisp > 0) {
			say(who,"Obvious Exits:\n",(char *)0);
			dp = savelst;
			while((dp = lstnext(dp,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))
		say_attribute(who,thing,var_using,(char *)0,0);
}



static	void
say_name(who,ob,showoid)
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);
}


say_attribute(who,ob,att,title,showoid)
char	*who;
char	*ob;			/* name or OID of the object */
char	*att;			/* the attribute to look for */
char	*title;			/* optional title, overrides default */
int	showoid;		/* show object ids? */
{
	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);
		title = tbuf;
	}

	if(attistype(atp,typ_list)) {		/* a list? */
		char	nxtu[MAXOID];

		if(atd == (char *)0 || *atd == '\0')
			return(1);
		say(who,title,":\n",(char *)0);

		while((atd = lstnext(atd,nxtu)) != (char *)0) {
			say_name(who,nxtu,showoid);
		}
	}
	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(atd == (char *)0 || *atd == '\0')
			return(1);
		say(who,title,": ",atd,"\n",(char *)0);
	}
	return(0);
}




static	void
say_other(who,ob)
char	*who;
char	*ob;
{
	char	aname[MAXOID];
	Obj	*op;		/* pointer to the object */
	int	a;
	static int known();

	if((op = cache_get(ob)) == (Obj *)0)
		return;

	for(a = 0; a < op->ocnt; a++) {
		if(attname(op->oap[a],aname) == 0
			&& !known(aname))	/* an unknown! */
			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,
	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,
	var_pass,	0
};



static int
known(att)
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);
}



do_examine(who,aswho,ob)
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)){
			say_attribute(who,ob,var_desc,(char *)0,0);
			say_attribute(who,ob,var_owner,(char *)0,1);
		}
		return(0);
	}

	say(who,"Flags: ",(char *)0);
	for (ap = flgs; *ap != (char *)0; ++ap)
		say_attribute(who,ob,*ap,(char *)0,0);
	say(who,"\n",(char *)0);

	for (ap = atts + 1; *ap != (char *)0; ++ap)
		say_attribute(who,ob,*ap,(char *)0,1);

	say_other(who,ob);
	return(0);
}