/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
#ifndef lint
static char RCSid[] = "$Header: /home/mjr/hacks/umud/CMD/RCS/destroy.c,v 1.2 91/10/22 11:28:47 mjr Exp $";
#endif
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include "mud.h"
#include "match.h"
#include "look.h"
#include "vars.h"
static int player_destroy();
static int exit_destroy();
static int room_destroy();
static int object_destroy();
/*
Object destruction.
*/
/* ARGSUSED */
cmd_destroy(ac,av,who,aswho)
int ac;
char *av[];
char *who;
char *aswho;
{
int wiz;
/* do help */
if(ac == 2 && !strcmp(av[1],"help")) {
say(who,av[0]," player player-obj\n",(char *)0);
say(who,av[0]," exit exit-obj\n",(char *)0);
say(who,av[0]," room room-obj\n",(char *)0);
say(who,av[0]," object obj\n",(char *)0);
return(0);
}
if( ac != 3 ) {
say(who,"I don't understand that use of \"",av[0],"\"!\n",
(char *)0);
return(1);
}
wiz = ut_flagged(aswho,var_wiz);
if(!strcmp(av[1],"player"))
return(player_destroy(who,aswho,av[2],wiz));
else if(!strcmp(av[1],"exit"))
return(exit_destroy(who,aswho,av[2],wiz));
else if(!strcmp(av[1],"room"))
return(room_destroy(who,aswho,av[2],wiz));
else if(!strcmp(av[1],"object"))
return(object_destroy(who,aswho,av[2],wiz));
say(who,"I don't understand what you want me to destroy!\n",(char *)0);
return(1);
}
/* destroy a player */
static player_destroy(who,aswho,ob,wiz)
char *who;
char *aswho;
char *ob;
int wiz;
{
char ply[MAXOID];
char *loc;
char *dp;
char nxtu[MAXOID];
/* start with some checks */
/* must be a wizard! */
if(!wiz) {
say(who,"Only wizards can destroy players\n",(char *)0);
return(1);
}
/* find the player; unique, exact match required. #num is OK. */
if(matchplayers(who,ob,ut_loc(who),MTCH_UNIQ|MTCH_NONLOC,ply))
return(1);
/* lets make sure its a player! */
if(!ut_flagged(ply,var_isplay)) {
say(who,ut_name(ply)," is not a player\n",(char *)0);
return(1);
}
/* can't destroy yourself */
if(!strcmp(ply,aswho))
/*
* gotos are only evil if used indiscriminately or
* if they branch backwards.
* Use for exception handling is kosher.
*/
goto fail;
/* ensure that the player is logged off */
say(ply,ut_name(who)," is destroying you. Goodbye!\n",
(char *)0);
/*
* note that "goodbye" must gracefully handle the
* player object not existing
*/
io_logoff(ply);
/* ok. fire away */
/* remove the player from the player list of its location */
loc = ut_loc(ply);
/* move the objects in the players contents list to their homes */
dp = ut_getatt(ply,0,typ_list,var_cont,(char *)0);
if(dp != (char *)0) {
while((dp = lstnext(dp,nxtu)) != (char *)0)
if(home_object(who,nxtu,(char *)0,ply)) {
goto fail;
}
}
/* send the "use" object home */
dp = ut_getatt(ply,0,typ_obj,var_using,(char *)0);
if(dp != (char *)0 && (dp = lstnext(dp,nxtu)) != (char *)0)
/* there is a "use" object */
if(home_object(who,nxtu,(char *)0,ply))
goto fail;
if(ut_listdel(who,loc,var_ply,ply)) {
plogf("destroy player %s: can't remove player from room %s\n",
ply,loc);
goto fail;
}
/* save the name! */
dp = ut_getatt(ply,0,typ_str,var_nam,(char *)0);
if(dp != (char *)0) {
strncpy(nxtu,dp,MAXOID);
nxtu[MAXOID-1] = '\0';
} else
strcpy(nxtu,"An unidentifiable player");
/* now delete the player (log and display error) */
switch( cache_del(ply,0) ) {
case 1:
/* DB couldn't delete the object */
plogf("destroy player %s: couldn't delete the player\n",ply);
goto fail;
case -1:
/* DB not initialized */
plogf("destroy player %s: no delete. db not initted\n",ply);
say(who,"couldn't delete player ",ply,"\n",(char *)0);
goto fail;
case 0:
/* either cache not initted, or object deleted ok */
break;
}
plogf("player %s destroyed by %s\n",ply,who);
/* send a message to all where they were */
ut_roombcast(loc,(char *)0,nxtu," disintegrates before you!\n",
(char *)0);
say(who,"You destroyed player ",ply,"\n",(char*)0);
return(0);
fail:
say(who,"Cannot destroy player ",ply,"\n",(char *)0);
return(1);
}
static char ply_mesg[] =
"You've been sent home as the room you were in was being destroyed\n";
/* utility routine to delete the exit */
static delete_xit(room,ex)
char *room;
char *ex;
{
switch( cache_del(ex,0) ) {
case 1:
/* DB couldn't delete the object */
plogf("destroy room %s: couldn't delete exit %s\n",room,ex);
return(1);
case 0:
/* no problem */
return(0);
default:
case -1:
/* DB not initialized */
plogf("destroy room %s: no delete. db not initted\n",room);
return(1);
}
}
/* destroy a room */
static room_destroy(who,aswho,name,wiz)
char *who;
char *aswho;
char *name;
int wiz;
{
char room[MAXOID];
char *dp;
char nxtu[MAXOID];
char *limbo;
/* start with some checks */
/* find the room; unique, exact match required. #num is OK.
* Actually, #num is the *only* way to refer to a room */
if(matchlocal(who,name,ut_loc(who),
MTCH_UNIQ|MTCH_MEOK|MTCH_NONLOC,room))
return(1);
/* check ownership */
if(!wiz && !ut_isobjown(aswho,room)) {
say(who,"You don't own ",name,"\n",(char *)0);
return(1);
}
/* ensure the object is a room */
if(!ut_flagged(room,var_isroom)) {
say(who,ut_name(room)," is not a room\n",(char *)0);
return(1);
}
limbo = ut_getatt(system_object,0,typ_obj,var_syslimbo,(char *)0);
if(limbo == (char *)0) {
plogf("destroy room %s: cannot find limbo!\n",room);
goto fail;
} else if(!strcmp(room,limbo)) {
say(who,"You can't destroy the system limbo!\n",(char *)0);
return(1);
}
/* send the players home */
dp = ut_getatt(room,0,typ_list,var_ply,(char *)0);
if(dp != (char *)0) {
/* there are players */
while((dp = lstnext(dp,nxtu)) != (char *)0){
if(home_object(who,nxtu,ply_mesg,room)) {
goto fail;
}
/* Do some messages, just for Moira */
if(!ut_flagged(nxtu,var_isdark))
ut_roombcast(ut_loc(nxtu),nxtu,ut_name(nxtu),
" has arrived.\n",(char *)0);
lookat(nxtu,ut_loc(nxtu),LOOK_NAME|LOOK_PLAY|LOOK_CONT);
}
}
/* send the contents home */
dp = ut_getatt(room,0,typ_list,var_cont,(char *)0);
if(dp != (char *)0) {
/* there are contents */
while((dp = lstnext(dp,nxtu)) != (char *)0)
if(home_object(who,nxtu,(char *)0,room)) {
goto fail;
}
}
/* destroy the exits */
dp = ut_getatt(room,0,typ_list,var_xit,(char *)0);
if(dp != (char *)0) {
/* there are exits */
while((dp = lstnext(dp,nxtu)) != (char *)0)
/* delete the exit (log error) */
if(delete_xit(room,nxtu)) {
goto fail;
} else
/* ignore any error */
(void)ut_listdel(who,room,var_xit,nxtu);
}
/* ignore error */
(void)ut_unset(who,room,var_xit);
/* otherwise, delete the room! */
switch( cache_del(room,0) ) {
case 1:
/* DB couldn't delete the object */
plogf("destroy room %s: couldn't delete the room\n",room);
goto fail;
case -1:
/* DB not initialized */
plogf("destroy room %s: no delete. db not initted\n",room);
goto fail;
case 0:
/* either cache not initted, or object deleted ok */
break;
}
say(who,"You destroyed room ",room,"\n",(char*)0);
return(0);
fail:
say(who,"Cannot destroy room ",room,"\n",(char*)0);
return(1);
}
/* destroy an exit */
static exit_destroy(who,aswho,name,wiz)
char *who;
char *aswho;
char *name;
int wiz;
{
char ex[MAXOID];
char *loc;
/* start with some checks */
/* find the exit; unique match required. #num is OK. */
if(matchexit(who,name,ut_loc(who),MTCH_UNIQ|MTCH_NONLOC,ex))
return(1);
/* check ownership */
if(!wiz && !ut_isobjown(aswho,ex)) {
say(who,"You don't own ",name,"\n",(char *)0);
return(1);
}
/* ensure the object is an exit */
if(ut_getatt(ex,1,typ_obj,var_dest,(char *)0) == (char *)0) {
say(who,ut_name(ex)," is not an exit\n",(char *)0);
return(1);
}
/* where is the exit? */
loc = ut_loc(ex);
if(ut_listdel(who,loc,var_xit,ex)) {
plogf("destroy exit %s: can't find in %s's xit list\n",
ex,loc);
goto fail;
}
/* now delete the exit (log and display error) */
switch( cache_del(ex,0) ) {
case 1:
/* DB couldn't delete the object */
plogf("destroy exit %s: couldn't delete the object\n",ex);
goto fail;
case -1:
/* DB not initialized */
plogf("destroy exit %s: no delete. db not initted\n",ex);
goto fail;
case 0:
/* either cache not initted, or object deleted ok */
break;
}
say(who,"You destroyed exit ",ex,"\n",(char *)0);
return(0);
fail:
say(who,"Cannot destroy exit ",ex,"\n",(char*)0);
return(1);
}
/* destroy a thing */
static object_destroy(who,aswho,name,wiz)
char *who;
char *aswho;
char *name;
int wiz;
{
char obj[MAXOID];
char *loc;
char *use;
/* start with some checks */
/* find the object; unique and exact match required. #num is OK. */
if(matchlocal(who,name,ut_loc(who),MTCH_UNIQ|MTCH_NONLOC,obj))
return(1);
/* check ownership */
if(!wiz && !ut_isobjown(aswho,obj)) {
say(who,"You don't own ",name,"\n",(char *)0);
return(1);
}
/* ensure the object is not a player,room or exit */
if(ut_flagged(obj,var_isplay) || ut_flagged(obj,var_isroom)
|| ut_getatt(obj,1,typ_obj,var_dest,(char *)0) != (char *)0) {
say(who,ut_name(obj)," is not an object\n",(char *)0);
return(1);
}
/* where is the thing? */
loc = ut_loc(obj);
if(ut_flagged(loc,var_isplay) &&
(use = ut_getatt(loc,0,typ_obj,var_using,(char *)0))!= (char *)0
&& !strcmp(use,obj)) {
/* if object is used by a player, unset the using attr */
if(ut_unset(who,loc,var_using))
goto fail;
} else if(ut_listdel(who,loc,var_cont,obj))
/* if object is carried by a player or in a room,
* remove from contents */
goto fail;
/*
* if objects can be inside objects, then you have to
* send the contents of this object home.
*
* Not currently implemented.
*/
/* now delete the thing (log and display error) */
switch( cache_del(obj,0) ) {
case 1:
/* DB couldn't delete the object */
plogf("destroy object %s: couldn't delete the object\n",obj);
goto fail;
case -1:
/* DB not initialized */
plogf("destroy object %s: no delete. db not initted\n",obj);
goto fail;
case 0:
/* either cache not initted, or object deleted ok */
break;
}
say(who,"You destroyed object ",obj,"\n",(char *)0);
return(0);
fail:
say(who,"Cannot destroy object ",obj,"\n",(char *)0);
return(1);
}
static int
home_object(who,what,msg,notthere)
char *who;
char *what;
char *msg;
char *notthere;
{
char hm[MAXOID];
char *where;
char *dstlist;
char *p;
if(!ut_home(what,hm))
return(1);
/* Use limbo if home == notthere */
if(!strcmp(hm,notthere)){
p = ut_getatt(system_object,0,typ_obj,var_syslimbo,(char *)0);
if(p == (char *)0)
return(1);
strcpy(hm,p);
}
/* Figure out where it is, and get it out of there */
if((where = ut_loc(what)) != (char *)0){
if(ut_flagged(what,var_isplay)){
/* It's a player */
dstlist = var_ply;
if(ut_listdel(what,where,var_ply,what))
return(1);
} else {
/* It must be an object */
dstlist = var_cont;
if(ut_getatt(where,0,typ_obj,var_using,(char *)0) == what){
/* Used object */
if(ut_unset(who,where,var_using))
return(1);
} else {
/* In contents list */
if(ut_listdel(what,where,var_cont,what))
return(1);
}
}
}
/* Put it where it's supposed to go */
/* ignore return values and hope. */
(void)ut_listadd(who,hm,dstlist,what);
(void)ut_set(who,what,typ_obj,var_loc,hm);
/* Tell the thing */
if(msg != (char *)0)
say(what,msg,(char *)0);
return(0);
}
/* Local Variables: */
/* c-indent-level: 8 */
/* c-continued-statement-offset: 8 */
/* End: */