/* recycle.c */ #include "config.h" /* * This file is part of TeenyMUD II. * Copyright(C) 1993, 1994, 1995 by Jason Downs. * All rights reserved. * * TeenyMUD II is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * TeenyMUD II is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file 'COPYING'); if not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * */ #include <stdio.h> #include <sys/types.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif /* HAVE_UNISTD_H */ #include "conf.h" #include "teeny.h" #include "commands.h" #include "externs.h" #ifndef F_OK #define F_OK 0 #endif /* object recycling system */ static int recycle_clean _ANSI_ARGS_((int, int, int, int *)); VOID do_recycle(player, cause, switches, argone) int player, cause, switches; char *argone; { int obj, ret; char buff[BUFFSIZ]; if((argone == (char *)NULL) || (argone[0] == '\0')) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "Recycle what?", NOT_QUIET); return; } obj = resolve_object(player, cause, argone, (!(switches & CMD_QUIET) ? RSLV_EXITS|RSLV_NOISY : RSLV_EXITS)); if(obj == -1) return; if(!isDESTROY_OK(obj)) { if(!(switches & RECYCLE_OVERRIDE)) { int plown, objown; char fbuf[152]; if((get_int_elt(player, OWNER, &plown) == -1) || (get_int_elt(obj, OWNER, &objown) == -1)) { notify_bad(player); return; } if(objown != plown) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "You can't recycle that!", NOT_QUIET); return; } /* Very rudimentary protection. */ snprintf(fbuf, sizeof(fbuf), "%s#%d", mudconf.files_path, obj); if(access(fbuf, F_OK) == 0) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "You can't recycle that!", NOT_QUIET); return; } } else { if(isEXIT(obj)) { int loc; if(get_int_elt(obj, LOC, &loc) == -1) { notify_bad(player); return; } if(!controls(player, cause, obj) && !controls(player, cause, loc)) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "You can't recycle that!", NOT_QUIET); return; } } else { if(!controls(player, cause, obj)) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "You can't recycle that!", NOT_QUIET); return; } } } } if((obj == mudconf.starting_loc) || (obj == mudconf.root_location)) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "You may not recycle that.", NOT_QUIET); return; } if(isPLAYER(obj)) { if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "You may not recycle players.", NOT_QUIET); return; } ret = recycle_obj(player, cause, obj); switch(ret) { case -1: notify_bad(player); break; case 0: if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "Nothing to recycle?!", NOT_QUIET); break; case 1: if(!(switches & CMD_QUIET)) notify_player(player, cause, player, "Thank you for recycling.", NOT_QUIET); break; default: if(!(switches & CMD_QUIET)) { snprintf(buff, sizeof(buff), "Thank you for recycling %d objects.", ret); notify_player(player, cause, player, buff, NOT_QUIET); } } } int recycle_owned(player, cause, object) int player, cause, object; { register int index, ret; int owner, total = 0; for(index = 0; index < mudstat.total_objects; index++) { if(!exists_object(index) || (index == object)) continue; if(get_int_elt(index, OWNER, &owner) == -1) { logfile(LOG_ERROR, "recycle_owned: bad owner reference on object #%d\n", index); return(-1); } if(owner == object) { ret = recycle_obj(player, cause, index); if(ret == -1) return(-1); total += ret; } } return(total); } int recycle_obj(player, cause, object) int player, cause, object; { int loc, owner; int total = 0; /* some sanity checking. */ if(!exists_object(object) || (get_int_elt(object, LOC, &loc) == -1) || (get_int_elt(object, OWNER, &owner) == -1)) { logfile(LOG_ERROR, "recycle_obj: bad reference to object #%d\n", object); return(-1); } switch(Typeof(object)) { case TYP_PLAYER: notify_player(object, cause, object, "You feel the universe collapsing around you...", 0); if(isALIVE(object)) tcp_logoff(object); ptable_delete(object); case TYP_THING: move_player_leave(object, cause, loc, 0, "You've been recycled!"); if(recycle_clean(player, cause, object, &total) == -1) return(-1); if(isTHING(object)) reward_money(owner, mudconf.thing_cost); destroy_obj(object); total++; break; case TYP_EXIT: list_drop(object, loc, EXITS); reward_money(owner, mudconf.exit_cost); destroy_obj(object); total++; break; case TYP_ROOM: notify_contents(object, cause, object, "The room shakes and begins to crumble...", 0); list_drop(object, loc, ROOMS); if(recycle_clean(player, cause, object, &total) == -1) return(-1); reward_money(owner, mudconf.room_cost); destroy_obj(object); total++; } return(total); } static int recycle_clean(player, cause, object, total) int player, cause, object, *total; { register int index; int home, *dests, parent, list, next; static char err[] = "recycle_clean: bad element reference on object #%d\n"; /* fix references to recycled objects */ for(index = 0; index < mudstat.total_objects; index++) { if(!exists_object(index)) continue; if(!isEXIT(index)) { if(get_int_elt(index, HOME, &home) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } switch(Typeof(index)) { case TYP_PLAYER: if(home == object) { if(set_int_elt(index, HOME, mudconf.starting_loc) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } break; case TYP_THING: if(home == object) { int owner, ownhome; if(get_int_elt(index, OWNER, &owner) == -1) { logfile(LOG_ERROR, err, index); return(-1); } if(get_int_elt(owner, HOME, &ownhome) == -1) { logfile(LOG_ERROR, err, owner); return(-1); } if(ownhome != object) { if(set_int_elt(index, HOME, ownhome) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } else { if(set_int_elt(index, HOME, mudconf.starting_loc) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } } break; case TYP_ROOM: /* really drop-to */ if(home == object) { if(set_int_elt(index, DROPTO, -1) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } break; case TYP_EXIT: if(get_array_elt(index, DESTS, &dests) == -1) { logfile(LOG_ERROR, err, index); return(-1); } if(dests != (int *)NULL) { register int d, t, change = 0; int new[MAXLINKS + 1]; for(d = 1; d <= dests[0]; d++) { if(dests[d] == object) change++; } if(change) { t = 0; for(d = 1; d <= dests[0]; d++) { if(dests[d] != object) new[++t] = dests[d]; } if(t) { new[0] = t; if(set_array_elt(index, DESTS, new) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } else { if(set_array_elt(index, DESTS, (int *)NULL) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } } } break; } if(get_int_elt(index, PARENT, &parent) == -1) { logfile(LOG_ERROR, err, index); return(-1); } if(parent == object) { if(set_int_elt(index, PARENT, -1) == -1) { logfile(LOG_ERROR, err, index); return(-1); } } } /* clean out lists and such */ if(get_int_elt(object, CONTENTS, &list) == -1) { logfile(LOG_ERROR, err, object); return(-1); } while(list != -1) { if(get_int_elt(list, NEXT, &next) == -1) { logfile(LOG_ERROR, err, list); return(-1); } notify_player(list, cause, list, "You feel a wrenching sensation...", 0); send_home(list, cause, object); list = next; } if(get_int_elt(object, EXITS, &list) == -1) { logfile(LOG_ERROR, err, object); return(-1); } while(list != -1) { if(get_int_elt(list, NEXT, &next) == -1) { logfile(LOG_ERROR, err, list); return(-1); } (*total) += recycle_obj(player, cause, list); list = next; } if(isROOM(object)) { if(get_int_elt(object, ROOMS, &list) == -1) { logfile(LOG_ERROR, err, object); return(-1); } while(list != -1) { if(get_int_elt(list, NEXT, &next) == -1) { logfile(LOG_ERROR, err, list); return(-1); } list_add(list, mudconf.root_location, ROOMS); if(set_int_elt(list, LOC, mudconf.root_location) == -1) { logfile(LOG_ERROR, err, list); return(-1); } list = next; } } return(0); }