/* 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: */