/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ /* 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(char *who, char *aswho, char *ob, int wiz); static int delete_xit(char *room, char *ex); static int room_destroy(char *who, char *aswho, char *name, int wiz); static int exit_destroy(char *who, char *aswho, char *name, int wiz); static int object_destroy(char *who, char *aswho, char *name, int wiz); static int home_object(char *who, char *what, char *msg, char *notthere); /* Object destruction. */ /* ARGSUSED */ int cmd_destroy (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 (UERR_NONE); } if (ac != 3) { say (who, "I don't understand that use of \"", av[0], "\"!\n", (char *) 0); return (UERR_BADPARM); } 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 (UERR_BADPARM); } /* destroy a player */ static int player_destroy (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 (UERR_PERM); } /* find the player; unique, exact match required. #num is OK. */ if (matchplayers (who, ob, ut_loc (who), MTCH_UNIQ | MTCH_NONLOC, ply)) return (UERR_NOMATCH); /* 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 (UERR_BADOID); } /* 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, sizeof (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, sizeof (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); if (run_level () == 0) say (who, "You destroyed player ", ply, "\n", (char *) 0); return (UERR_NONE); fail: say (who, "Cannot destroy player ", ply, "\n", (char *) 0); return (UERR_FATAL); } 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 int delete_xit (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 (UERR_FATAL); case 0: /* no problem */ return (UERR_NONE); default: case -1: /* DB not initialized */ plogf ("destroy room %s: no delete. db not initted\n", room); return (UERR_FATAL); } } /* destroy a room */ static int room_destroy (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 (UERR_NOMATCH); /* check ownership */ if (!wiz && !ut_isobjown (aswho, room)) { say (who, "You don't own ", name, "\n", (char *) 0); return (UERR_PERM); } /* 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 (UERR_BADOID); } 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 (UERR_PERM); } /* 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, sizeof (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, sizeof (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, sizeof (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; } if (run_level () == 0) say (who, "You destroyed room ", room, "\n", (char *) 0); return (UERR_NONE); fail: say (who, "Cannot destroy room ", room, "\n", (char *) 0); return (UERR_FATAL); } /* destroy an exit */ static int exit_destroy (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 (UERR_NOMATCH); /* check ownership */ if (!wiz && !ut_isobjown (aswho, ex)) { say (who, "You don't own ", name, "\n", (char *) 0); return (UERR_PERM); } /* 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 (UERR_BADOID); } /* 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; } if (run_level () == 0) say (who, "You destroyed exit ", ex, "\n", (char *) 0); return (UERR_NONE); fail: say (who, "Cannot destroy exit ", ex, "\n", (char *) 0); return (UERR_FATAL); } /* destroy a thing */ static int object_destroy (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 (UERR_NOMATCH); /* check ownership */ if (!wiz && !ut_isobjown (aswho, obj)) { say (who, "You don't own ", name, "\n", (char *) 0); return (UERR_PERM); } /* 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 (UERR_BADOID); } /* 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; } if (run_level () == 0) say (who, "You destroyed object ", obj, "\n", (char *) 0); return (UERR_NONE); fail: say (who, "Cannot destroy object ", obj, "\n", (char *) 0); return (UERR_FATAL); } static int home_object (char *who, char *what, char *msg, char *notthere) { char hm[MAXOID]; char *where; char *dstlist = NULL; 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); }