/* $Header: look.c,v 2.0 90/05/05 12:45:36 lachesis Exp $
* $Log: look.c,v $
* Revision 2.0 90/05/05 12:45:36 lachesis
* Incorporated ABODE and HAVEN flags (remembering to convert FireFoot's
* usage of those flags to ours).
* Added Examine of objects that don't belong to you, added GOD_PRIV.
*
* Revision 1.3 90/04/21 17:20:46 lachesis
* Added property lists.
*
* Revision 1.2 90/04/20 14:06:44 lachesis
* Added @odrop && @drop.
*
* Revision 1.1 90/04/14 14:56:46 lachesis
* Initial revision
*
*/
#include "copyright.h"
/* commands which look at things */
#include "db.h"
#include "config.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
char buf[BUFFER_LEN];
/* prints owner of something */
static void
print_owner(dbref player, dbref thing)
{
char buf[BUFFER_LEN];
switch(Typeof(thing))
{
case TYPE_ROOM:
sprintf(buf, "Owner: %s", db[db[thing].sp.room.owner].name);
break;
case TYPE_THING:
sprintf(buf, "Owner: %s", db[db[thing].sp.thing.owner].name);
break;
case TYPE_PLAYER:
sprintf(buf, "%s is a player", db[thing].name);
break;
case TYPE_EXIT:
sprintf(buf, "Owner: %s", db[db[thing].sp.exit.owner].name);
break;
#ifdef RECYCLE
case TYPE_GARBAGE:
sprintf(buf, "%s is garbage", db[thing].name);
break;
#endif
}
notify(player, buf);
}
static void look_contents(dbref player, dbref loc, const char *contents_name)
{
dbref thing;
dbref can_see_loc;
/* check to see if he can see the location */
can_see_loc = (!Dark(loc) || controls(player, loc));
/* check to see if there is anything there */
DOLIST(thing, db[loc].contents) {
if(can_see(player, thing, can_see_loc)) {
/* something exists! show him everything */
notify(player, contents_name);
DOLIST(thing, db[loc].contents) {
if(can_see(player, thing, can_see_loc)) {
notify(player, unparse_object(player, thing));
}
}
break; /* we're done */
}
}
}
static void look_simple(dbref player, dbref thing)
{
if(db[thing].description) {
notify(player, db[thing].description);
} else {
notify(player, "You see nothing special.");
}
}
void look_room(dbref player, dbref loc)
{
/* tell him the name, and the number if he can link to it */
notify(player, unparse_object(player, loc));
/* tell him the description */
if(db[loc].description) {
notify(player, db[loc].description);
}
/* tell him the appropriate messages if he has the key */
can_doit(player, loc, 0);
/* tell him the contents */
look_contents(player, loc, "Contents:");
}
void do_look_around(dbref player)
{
dbref loc;
if((loc = getloc(player)) == NOTHING) return;
look_room(player, loc);
}
void do_look_at(dbref player, const char *name)
{
dbref thing;
if(*name == '\0') {
if((thing = getloc(player)) != NOTHING) {
look_room(player, thing);
}
} else {
/* look at a thing here */
init_match(player, name, NOTYPE);
match_all_exits();
match_neighbor();
match_possession();
if(Wizard(player)) {
match_absolute();
match_player();
}
match_here();
match_me();
if((thing = noisy_match_result()) != NOTHING) {
switch(Typeof(thing)) {
case TYPE_ROOM:
look_room(player, thing);
break;
case TYPE_PLAYER:
look_simple(player, thing);
look_contents(player, thing, "Carrying:");
break;
default:
look_simple(player, thing);
break;
}
}
}
}
#ifdef VERBOSE_EXAMINE
static const char *flag_description(dbref thing)
{
static char buf[BUFFER_LEN];
strcpy(buf, "Type: ");
switch(Typeof(thing)) {
case TYPE_ROOM:
strcat(buf, "ROOM");
break;
case TYPE_EXIT:
strcat(buf, "EXIT/ACTION");
break;
case TYPE_THING:
strcat(buf, "THING");
break;
case TYPE_PLAYER:
strcat(buf, "PLAYER");
break;
#ifdef RECYCLE
case TYPE_GARBAGE:
strcat(buf, "GARBAGE");
break;
#endif
default:
strcat(buf, "***UNKNOWN TYPE***");
break;
}
if(db[thing].flags & ~TYPE_MASK) {
/* print flags */
strcat(buf, " Flags:");
if(db[thing].flags & WIZARD) strcat(buf, " WIZARD");
if(db[thing].flags & STICKY) strcat(buf, " STICKY");
if(db[thing].flags & DARK) strcat(buf, " DARK");
if(db[thing].flags & LINK_OK) strcat(buf, " LINK_OK");
if(db[thing].flags & TEMPLE) strcat(buf, " TEMPLE");
#ifdef RESTRICTED_BUILDING
if(db[thing].flags & BUILDER) strcat(buf, " BUILDER");
#endif /* RESTRICTED_BUILDING */
#ifdef PLAYER_CHOWN
if(db[thing].flags & CHOWN_OK) strcat(buf, " CHOWN_OK");
#endif /* PLAYER_CHOWN */
if(db[thing].flags & JUMP_OK) strcat(buf, " JUMP_OK");
#ifdef HAVEN
if (db[thing].flags & HAVEN) strcat(buf, " HAVEN");
#endif /* HAVEN */
#ifdef ABODE
if (db[thing].flags & ABODE) strcat(buf, " ABODE");
#endif /* ABODE */
}
return buf;
}
#endif /* VERBOSE_EXAMINE */
void do_examine(dbref player, const char *name)
{
dbref thing;
char buf[BUFFER_LEN];
dbref content;
dbref exit;
int i;
if(*name == '\0') {
if((thing = getloc(player)) == NOTHING) return;
} else {
/* look it up */
init_match(player, name, NOTYPE);
match_all_exits();
match_neighbor();
match_possession();
match_absolute();
/* only Wizards can examine other players */
if(Wizard(player)) match_player();
match_here();
match_me();
/* get result */
if((thing = noisy_match_result()) == NOTHING) return;
}
if(!can_link(player, thing)) {
print_owner(player, thing);
do_look_at(player, name);
return;
}
switch(Typeof(thing)) {
case TYPE_ROOM:
sprintf(buf, "%s Owner: %s",
unparse_object(player, thing),
db[db[thing].sp.room.owner].name);
break;
case TYPE_THING:
sprintf(buf, "%s Owner: %s Value: %d",
unparse_object(player, thing),
db[db[thing].sp.thing.owner].name,
db[thing].sp.thing.value);
break;
case TYPE_PLAYER:
sprintf(buf, "%s Cookies: %d ",
unparse_object(player, thing),
db[thing].sp.player.pennies);
break;
case TYPE_EXIT:
sprintf(buf, "%s Owner: %s",
unparse_object(player, thing),
db[db[thing].sp.exit.owner].name);
break;
#ifdef RECYCLE
case TYPE_GARBAGE:
strcpy(buf, unparse_object(player, thing));
break;
#endif
}
notify(player, buf);
#ifdef VERBOSE_EXAMINE
notify(player, flag_description(thing));
#endif /* VERBOSE_EXAMINE */
if(db[thing].description) notify(player, db[thing].description);
sprintf(buf, "Key: %s", unparse_boolexp(player, db[thing].key));
notify(player, buf);
if(db[thing].fail_message) {
sprintf(buf, "Fail: %s", db[thing].fail_message);
notify(player, buf);
}
if(db[thing].succ_message) {
sprintf(buf, "Success: %s", db[thing].succ_message);
notify(player, buf);
}
if (db[thing].drop_message)
{
sprintf(buf, "Drop: %s", db[thing].drop_message);
notify(player, buf);
}
if(db[thing].ofail) {
sprintf(buf, "Ofail: %s", db[thing].ofail);
notify(player, buf);
}
if(db[thing].osuccess) {
sprintf(buf, "Osuccess: %s", db[thing].osuccess);
notify(player, buf);
}
if (db[thing].odrop)
{
sprintf(buf, "Odrop: %s", db[thing].odrop);
notify(player, buf);
}
/* show him the properties */
if (db[thing].properties)
{
struct plist *p;
char buf[BUFFER_LEN];
notify(player, "Properties:");
for (p = db[thing].properties; p; p = p -> next)
{
strncpy(buf, p -> type, BUFFER_LEN - 1);
strncat(buf, ": ", BUFFER_LEN - 1);
strncat(buf, p -> class, BUFFER_LEN - 1);
notify(player, buf);
}
}
/* show him the contents */
if(db[thing].contents != NOTHING) {
if (Typeof(thing) == TYPE_PLAYER)
notify(player, "Carrying:");
else
notify(player, "Contents:");
DOLIST(content, db[thing].contents) {
notify(player, unparse_object(player, content));
}
}
switch(Typeof(thing)) {
case TYPE_ROOM:
/* tell him about exits */
if(db[thing].sp.room.exits != NOTHING) {
notify(player, "Exits:");
DOLIST(exit, db[thing].sp.room.exits) {
notify(player, unparse_object(player, exit));
}
} else {
notify(player, "No exits.");
}
/* print dropto if present */
if(db[thing].sp.room.dropto != NOTHING) {
sprintf(buf, "Dropped objects go to: %s",
unparse_object(player, db[thing].sp.room.dropto));
notify(player, buf);
}
break;
case TYPE_THING:
/* print home */
sprintf(buf, "Home: %s",
unparse_object(player, db[thing].sp.thing.home)); /* home */
notify(player, buf);
/* print location if player can link to it */
if(db[thing].location != NOTHING
&& (controls(player, db[thing].location)
|| can_link_to(player, db[thing].location))) {
sprintf(buf, "Location: %s",
unparse_object(player, db[thing].location));
notify(player, buf);
}
/* print thing's actions, if any */
if(db[thing].sp.thing.actions != NOTHING) {
notify(player, "Actions/exits:");
DOLIST(exit, db[thing].sp.thing.actions) {
notify(player, unparse_object(player, exit));
}
} else {
notify(player, "No actions attached.");
}
break;
case TYPE_PLAYER:
/* print home */
sprintf(buf, "Home: %s",
unparse_object(player, db[thing].sp.player.home)); /* home */
notify(player, buf);
/* print location if player can link to it */
if(db[thing].location != NOTHING
&& (controls(player, db[thing].location)
|| can_link_to(player, db[thing].location))) {
sprintf(buf, "Location: %s",
unparse_object(player, db[thing].location));
notify(player, buf);
}
/* print player's actions, if any */
if(db[thing].sp.player.actions != NOTHING) {
notify(player, "Actions/exits:");
DOLIST(exit, db[thing].sp.player.actions) {
notify(player, unparse_object(player, exit));
}
} else {
notify(player, "No actions attached.");
}
break;
case TYPE_EXIT:
if (db[thing].location != NOTHING) {
sprintf(buf, "Source: %s",
unparse_object(player, db[thing].location));
notify(player, buf);
}
/* print destinations */
if (db[thing].sp.exit.ndest == 0) break;
for (i = 0; i < db[thing].sp.exit.ndest; i++) {
switch( (db[thing].sp.exit.dest)[i]) {
case NOTHING:
break;
case HOME:
notify(player, "Destination: *HOME*");
break;
default:
sprintf(buf, "Destination: %s",
unparse_object(player, (db[thing].sp.exit.dest)[i]));
notify(player, buf);
break;
}
}
break;
default:
/* do nothing */
break;
}
}
void do_score(dbref player)
{
char buf[BUFFER_LEN];
sprintf(buf, "You have %d %s.",
db[player].sp.player.pennies,
db[player].sp.player.pennies == 1 ? "cookie" : "cookies");
notify(player, buf);
}
void do_inventory(dbref player)
{
dbref thing;
if((thing = db[player].contents) == NOTHING) {
notify(player, "You aren't carrying anything.");
} else {
notify(player, "You are carrying:");
DOLIST(thing, thing) {
notify(player, unparse_object(player, thing));
}
}
do_score(player);
}
void do_find(dbref player, const char *name)
{
dbref i;
if(!payfor(player, LOOKUP_COST)) {
notify(player, "You don't have enough cookies.");
} else {
for(i = 0; i < db_top; i++) {
if(Typeof(i) != TYPE_EXIT
&& controls(player, i)
&& (!*name || string_match(db[i].name, name))) {
notify(player, unparse_object(player, i));
}
}
notify(player, "***End of List***");
}
}