#include "copyright.h"
#include "config.h"
#include "version.h"
#include "mush.h"
/* commands which look at things */
#include <ctype.h>
#include "db.h"
#include "params.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#include "money.h"
#define EXEC_SIGNAL '@' /* Symbol which tells us what we're looking at
* is an execution order and not a message. */
static char buf[BUFFER_LEN];
/* prints owner of something */
static void print_owner(dbref player, dbref thing)
{
switch(Typeof(thing))
{
case TYPE_PLAYER:
sprintf(buf, "%s is a player.", unparse_name(thing));
break;
case TYPE_ROOM:
case TYPE_THING:
case TYPE_EXIT:
case TYPE_PROGRAM:
sprintf(buf, "Owner: %s", unparse_object_full(player, OWNER(thing)));
break;
case TYPE_GARBAGE:
sprintf(buf, "%s is garbage.", unparse_name(thing));
break;
}
notify(player, player, buf);
}
#undef PREP
void exec_or_notify(dbref player, dbref thing, char *message)
{
frame *fr;
char *p, *ptr;
char buff[BUFFER_LEN];
#ifdef COMPRESS
p = uncompress(message);
#else /* !COMPRESS */
p = message;
#endif /* COMPRESS */
if (*p == EXEC_SIGNAL)
{
#ifdef PREP
char *p2, *p3;
int i;
if (*(++p) == REGISTERED_TOKEN) {
strcpy(buf, p);
for (p2 = buf; *p && !isspace(*p); p++);
if (*p)
p++;
for (p3 = buf; *p3 && !isspace(*p3); p3++);
if (*p3)
*p3 = '\0';
if (*p2) {
i = (dbref) find_registered_obj(thing, p2);
} else {
i = 0;
}
} else {
long i;
i = atol(++p);
for (; *p && !isspace(*p); p++);
if (*p) p++;
}
#else
long i;
i = atol(++p);
for (; *p && !isspace(*p); p++);
if (*p) p++;
#endif
if (i < 0 || i >= db_top || (Typeof(i) != TYPE_PROGRAM))
{
if (*p) notify(player, player, p);
else notify(player, player, "You'll probably want to look again...");
}
else
{
char PREV_match_args[BUFSIZ];
strcpy(PREV_match_args, match_args);
strcpy(match_args, p);
fr = new_frame(player, i, thing, DBFETCH(player)->location, 1);
run_frame(fr, 1);
if (fr && (fr->status != STATUS_SLEEP)) free_frame(fr);
strcpy(match_args, PREV_match_args);
}
}
#ifdef MUSH
else {
ptr = exec(player, p, thing, 0);
if(ptr) {
strcpy(buff, ptr);
free(ptr);
}
notify(player, player, buff);
}
#else
else notify(player, player, p);
#endif
}
static void look_contents(dbref player, dbref loc, char *contents_name)
{
dbref thing;
dbref can_see_loc;
int titleflag = 0;
/* check to see if he can see the location */
can_see_loc = ((!Dark(loc) || controls(player, loc))
#ifdef SILENT_PLAYERS
&& (!(FLAGS(player) & STICKY))
#endif
);
/* check to see if there is anything there */
DOLIST(thing, DBFETCH(loc)->contents)
{
if((thing != player) && (Typeof(thing) != TYPE_ROOM) &&
(can_see(player, thing, can_see_loc)))
{
/* something exists! show him everything */
if (!titleflag)
{
titleflag = 1;
notify(player, player, contents_name);
}
notify(player, player, unparse_object(player, thing));
}
}
}
static void look_simple(dbref player, dbref thing)
{
#ifdef TIMESTAMPS
if(Typeof(thing) != TYPE_PLAYER)
DBFETCH(thing)->time_used = time((long *)NULL);
#endif
if(GET_DESC(thing))
exec_or_notify(player, thing, GET_DESC(thing));
else
notify(player, player, "You see nothing special.");
#ifdef MUSH
did_it(player, thing, NULL, NULL, NULL, NULL, "ADESCRIBE", NOTHING);
#endif
}
void look_room(dbref player, dbref loc)
{
char tbuf1[BUFFER_LEN];
char *ptr, *s;
if (can_move(player, "look"))
{
do_move(player, "", "", "look");
return;
}
#ifdef MUSH
if(Typeof(player) != TYPE_PLAYER) /* Hack, HACK, HACK */
speaker = player; /* Mush is a HACK! -- Howard */
#endif
/* tell him the name, and the number if he can link to it */
notify(player, player, unparse_object(player, loc));
#ifdef MUSH
if (Typeof(loc) != TYPE_ROOM)
{
if ((s = atr_get(loc, "IDESCRIBE"))) {
strcpy(tbuf1, s);
ptr = exec(loc, tbuf1, loc, 0);
strcpy(tbuf1, ptr);
exec_or_notify(player, loc, tbuf1);
free(ptr);
}
}
else
#endif
{
if(GET_DESC(loc)) /* tell him the description */
{
exec_or_notify(player, loc, GET_DESC(loc));
#ifdef TIMESTAMPS
DBFETCH(loc)->time_used = time(NULL);
#endif
}
}
#ifdef MUSH
did_it(player, loc, NULL, NULL, NULL, NULL, "ADESCRIBE", NOTHING);
#endif
/* 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(__DO_PROTO)
{
dbref thing;
match_data md;
if(*arg1 == '\0')
{
if((thing = getloc(player)) != NOTHING)
look_room(player, thing);
}
else
{
/* look at a thing here */
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
if(Wizard(player))
{
match_absolute(&md);
match_player(&md);
}
match_here(&md);
match_me(&md);
if((thing = noisy_match_result(&md)) != NOTHING)
{
switch(Typeof(thing))
{
case TYPE_ROOM:
if (getloc(player) != thing &&
!can_link_to(player, TYPE_ROOM, thing))
notify(player, player, "Permission denied.");
else look_room(player, thing);
break;
default:
look_simple(player, thing);
look_contents(player, thing, "Carrying:");
break;
}
}
}
}
char *flag_description(dbref thing)
{
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;
case TYPE_PROGRAM:
strcat(buf, "PROGRAM");
break;
case TYPE_GARBAGE:
strcat(buf, "GARBAGE");
break;
default:
strcat(buf, "***UNKNOWN TYPE***");
break;
}
if(FLAGS(thing) & ~TYPE_MASK)
{
/* print flags */
strcat(buf, " Flags:");
if(FLAGS(thing) & GOD) strcat(buf, " GOD");
if(FLAGS(thing) & WIZARD) strcat(buf, " WIZARD");
if(FLAGS(thing) & QUELL) strcat(buf, " QUELL");
if(FLAGS(thing) & STICKY) {
if(Typeof(thing) == TYPE_PROGRAM) strcat(buf, " SETUID");
else if(Typeof(thing) == TYPE_PLAYER) strcat(buf, " SILENT");
else strcat(buf, " STICKY");
}
if(FLAGS(thing) & SAFE) strcat(buf, " SAFE");
if(FLAGS(thing) & AUDIBLE) strcat(buf, " AUDIBLE");
if(FLAGS(thing) & DARK)
strcat(buf, (Typeof(thing) != TYPE_PROGRAM && !Puppet(thing))
? " DARK" : " DEBUGGING");
if(FLAGS(thing) & LINK_OK) strcat(buf, " LINK_OK");
if(FLAGS(thing) & MUCKER)
strcat (buf, ((FLAGS(thing) & WIZARD) && (Typeof(thing) == TYPE_PLAYER)) ?
" MONITOR" : " MUCKER");
if(FLAGS(thing) & BUILDER) strcat(buf, " BUILDER");
#ifdef PLAYER_CHOWN
if(FLAGS(thing) & CHOWN_OK) strcat(buf, " CHOWN_OK");
#endif /* PLAYER_CHOWN */
if(FLAGS(thing) & JUMP_OK) strcat(buf, " JUMP_OK");
#ifdef MUSH
if (FLAGS(thing) & HAVEN) {
if(Typeof(thing) == TYPE_EXIT) strcat(buf, " HEAR");
else if(Typeof(thing) == TYPE_THING) strcat(buf, " HALT");
else strcat(buf, " HAVEN");
}
#else
if (FLAGS(thing) & HAVEN) strcat(buf,
(Typeof(thing) == TYPE_EXIT) ? " HEAR" : " HAVEN");
#endif /* MUSH */
if (FLAGS(thing) & ABODE) {
if(Typeof(thing) == TYPE_EXIT) strcat(buf, " AUTOSTART");
else if(Typeof(thing) == TYPE_PLAYER) strcat(buf, " AUTHOR");
else strcat(buf, " ABODE");
}
if(FLAGS(thing) & ENTER_OK) strcat (buf, " ENTER_OK");
if(FLAGS(thing) & NOSPOOF) strcat (buf, " NOSPOOF");
#ifdef MUSH
if(FLAGS(thing) & PUPPET) strcat (buf, " PUPPET");
#endif
if(FLAGS(thing) & UNFIND) strcat (buf, " UNFINDABLE");
if(FLAGS(thing) & VISUAL) strcat (buf, " VISUAL");
if(FLAGS(thing) & VERBOSE) strcat (buf, " VERBOSE");
#ifdef MUSH
if(FLAGS(thing) & NOCOMMAND) strcat (buf, " NOCOMMAND");
#endif
if(FLAGS(thing) & INTERACTIVE) strcat (buf, " INTERACTIVE");
}
return buf;
}
void examine_object(dbref player, dbref thing)
{
int i;
if(Typeof(thing) == TYPE_GARBAGE)
{
notify(player, player, unparse_object(player, thing));
return;
}
if (!controls(player, thing) && !Visual(thing)) print_owner(player, thing);
else notify(player, player, unparse_object_full(player, thing));
if(!controls(player, thing) && !Visual(thing)) return;
sprintf(buf, " Location: %s",
unparse_object_full(player, DBFETCH(thing)->location));
notify(player, player, buf);
sprintf(buf, " Owner: %s", unparse_object_full(player, OWNER(thing)));
notify(player, player, buf);
sprintf(buf, " Money: %ld", DBFETCH(thing)->pennies);
notify(player, player, buf);
notify(player, player, flag_description(thing));
if(GET_DESC(thing))
{
sprintf(buf, " Description: %s", GET_DESC(thing));
notify(player, player, buf);
}
sprintf(buf, " Key: %s", unparse_boolexp(player, DBFETCH(thing)->key));
notify(player, player, buf);
if(GET_SUCC(thing))
{
sprintf(buf, " Success: %s", GET_SUCC(thing));
notify(player, player, buf);
}
if(GET_FAIL(thing))
{
sprintf(buf, " Fail: %s", GET_FAIL(thing));
notify(player, player, buf);
}
if (GET_DROP(thing))
{
sprintf(buf, " Drop: %s", GET_DROP(thing));
notify(player, player, buf);
}
if(GET_OSUCC(thing))
{
sprintf(buf, " Osuccess: %s", GET_OSUCC(thing));
notify(player, player, buf);
}
if(GET_OFAIL(thing))
{
sprintf(buf, " Ofail: %s", GET_OFAIL(thing));
notify(player, player, buf);
}
if (GET_ODROP(thing))
{
sprintf(buf, " Odrop: %s", GET_ODROP(thing));
notify(player, player, buf);
}
if (DBFETCH(thing)->link != NOTHING)
{
sprintf(buf, " Link: %s",
unparse_object_full(player, DBFETCH(thing)->link));
notify(player, player, buf);
}
switch(Typeof(thing))
{
case TYPE_EXIT:
/* print destinations */
if (DBFETCH(thing)->sp.exit.ndest > 0)
{
notify (player, player, "Destinations:");
for (i = 0; i < DBFETCH(thing)->sp.exit.ndest; i++)
{
notify(player, player, unparse_object_full(player,
(DBFETCH(thing)->sp.exit.dest)[i]));
}
}
break;
case TYPE_PROGRAM:
if (DBFETCH(thing)->sp.program.siz)
{
sprintf(buf, "Program compiled size: %d",
DBFETCH(thing)->sp.program.siz);
notify(player, player, buf);
}
else notify(player, player, "Program not compiled");
}
}
void examine_properties(dbref player, dbref thing, char *match, int titleflag)
{
if (!controls(player, thing) && !Visual(thing))
{
notify(player, player, "Permission denied.");
return;
}
if (DBFETCHPROP(thing) || titleflag)
{
notify(player, player, "Properties:");
notify_propdir(player, thing, match, access_rights(player, thing, NOTHING),
0);
}
}
void examine_contents(dbref player, dbref thing, char *match, int titleflag)
{
dbref content;
if (!controls(player, thing) && !Visual(thing))
{
notify(player, player, "Permission denied.");
return;
}
if((DBFETCH(thing)->contents != NOTHING) || titleflag)
{
notify(player, player, "Contents:");
DOLIST(content, DBFETCH(thing)->contents)
{
if (!match || !*match || string_match(NAME(content), match))
notify(player, player, unparse_object_full(player, content));
}
}
}
void examine_exits(dbref player, dbref thing, char *match, int titleflag)
{
dbref exit1;
if (!controls(player, thing) && !Visual(thing))
{
notify(player, player, "Permission denied.");
return;
}
if((DBFETCH(thing)->exits != NOTHING) || titleflag)
{
notify(player, player, "Exits:");
DOLIST(exit1, DBFETCH(thing)->exits)
{
if (!match || !*match || string_match(NAME(exit1), match))
notify(player, player, unparse_object_full(player, exit1));
}
}
}
void do_examine(__DO_PROTO)
{
dbref thing;
match_data md;
if(*arg1 == '\0')
{
if((thing = getloc(player)) == NOTHING) return;
}
else
{
/* look it up */
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
match_absolute(&md);
/* only Wizards can examine other players */
if(Wizard(player)) match_player(&md);
match_here(&md);
match_me(&md);
/* get result */
if((thing = noisy_match_result(&md)) == NOTHING) return;
}
examine_object(player, thing);
if (controls(player, thing) || Visual(thing))
{
examine_properties(player, thing, arg2, 0);
examine_contents(player, thing, arg2, 0);
examine_exits(player, thing, arg2, 0);
}
}
void do_at_examine(__DO_PROTO)
{
dbref thing;
match_data md;
if(*arg1 == '\0')
{
if((thing = getloc(player)) == NOTHING) return;
}
else
{
/* look it up */
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
match_absolute(&md);
/* only Wizards can examine other players */
if(Wizard(player)) match_player(&md);
match_here(&md);
match_me(&md);
/* get result */
if((thing = noisy_match_result(&md)) == NOTHING) return;
}
examine_object(player, thing);
}
void do_properties(__DO_PROTO)
{
dbref thing;
match_data md;
if(*arg1 == '\0')
{
if((thing = getloc(player)) == NOTHING) return;
}
else
{
/* look it up */
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
match_absolute(&md);
/* only Wizards can examine other players */
if(Wizard(player)) match_player(&md);
match_here(&md);
match_me(&md);
/* get result */
if((thing = noisy_match_result(&md)) == NOTHING) return;
}
examine_properties(player, thing, arg2, 1);
}
void do_contents(__DO_PROTO)
{
dbref thing;
match_data md;
if(*arg1 == '\0')
{
if((thing = getloc(player)) == NOTHING) return;
}
else
{
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
match_absolute(&md);
if(Wizard(player)) match_player(&md);
match_here(&md);
match_me(&md);
/* get result */
if((thing = noisy_match_result(&md)) == NOTHING) return;
}
examine_contents(player, thing, arg2, 1);
}
void do_exits(__DO_PROTO)
{
dbref thing;
match_data md;
if(*arg1 == '\0')
{
if((thing = getloc(player)) == NOTHING) return;
}
else
{
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
match_absolute(&md);
if(Wizard(player)) match_player(&md);
match_here(&md);
match_me(&md);
if((thing = noisy_match_result(&md)) == NOTHING) return;
}
examine_exits(player, thing, arg2, 1);
}
void do_score(__DO_PROTO)
{
sprintf(buf, "You have %d %s.", DBFETCH(player)->pennies,
DBFETCH(player)->pennies == 1 ? S_MONEY : PL_MONEY ); /* money.h */
notify(player, player, buf);
}
void do_inventory(__DO_PROTO)
{
dbref thing;
if((thing = DBFETCH(player)->contents) == NOTHING)
notify(player, player, "You aren't carrying anything.");
else
{
notify(player, player, "You are carrying:");
DOLIST(thing, thing)
{
notify(player, player, unparse_object(player, thing));
}
}
do_score(player, "", "", "");
}
void do_find(__DO_PROTO)
{
dbref i, current_flags;
current_flags = FLAGS(player);
FLAGS(player) &= (~STICKY);
if (FLAGS(player) & WIZARD)
{
for(i = 0; i < db_top; i++)
{
if ((Typeof(i) != TYPE_GARBAGE) &&
(!*arg1 || wild_match(arg1, NAME(i)) || string_match(NAME(i), arg1)))
notify(player, player, unparse_object_full(player, i));
}
}
else
{
for (i = player; i != NOTHING; i = DBFETCH(i)->nextowned)
{
if ((Typeof(i) != TYPE_GARBAGE) &&
(!*arg1 || wild_match(arg1, NAME(i)) || string_match(NAME(i), arg1)))
notify(player, player, unparse_object_full(player, i));
}
}
notify(player, player, "***End of List***");
FLAGS(player) = current_flags;
}
void do_owned(__DO_PROTO)
{
dbref obj, i;
match_data md;
if (strlen(arg1))
{
init_match(player, arg1, NOTYPE, &md);
match_all_exits(&md);
match_neighbor(&md);
match_possession(&md);
if(Wizard(player))
{
match_absolute(&md);
match_player(&md);
}
match_here(&md);
match_me(&md);
if(((obj = noisy_match_result(&md)) == AMBIGUOUS) || (obj == NOTHING))
return;
}
else obj = player;
if (!Wizard(player) && (player != OWNER(obj)))
{
notify (player, player, "Permission denied.");
return;
}
if (Typeof(obj) == TYPE_PLAYER)
{
for(i = obj; i != NOTHING; i = DBFETCH(i)->nextowned)
{
if ((Typeof(i) != TYPE_GARBAGE) &&
(!strlen(arg2) ||
string_match(DBFETCH(i)->name, arg2)))
notify(player, player, unparse_object_full(player, i));
}
notify(player, player, "***End of List***");
}
else notify(player, player, "Object not a player.");
}
void do_trace(__DO_PROTO)
{
dbref thing;
int i;
int depth;
match_data md;
depth = atoi(arg2);
init_match(player, arg1, NOTYPE, &md);
match_absolute(&md);
match_here(&md);
match_me(&md);
match_neighbor(&md);
match_possession(&md);
if ((thing = noisy_match_result(&md)) == NOTHING
|| thing == AMBIGUOUS) return;
for (i = 0; (!depth || i < depth) && thing != NOTHING; i++)
{
if (controls(player, thing) || can_link_to(player, NOTYPE, thing))
notify(player, player, unparse_object(player, thing));
else notify(player, player, "**Missing**");
thing = DBFETCH(thing)->location;
}
notify(player, player, "***End of List***");
}
void do_version(__DO_PROTO)
{
char buffer1[BUFFER_LEN];
sprintf(buffer1, "This DaemonMUCK is running version %s", VERSION);
notify(player, player, buffer1);
}