const char * unparse_object(dbref player, dbref loc) { static char buf[BUFFER_LEN]; if (player == NOTHING) goto islog; if (Typeof(player) != TYPE_PLAYER) player = OWNER(player); islog: switch (loc) { case NOTHING: return "*NOTHING*"; case AMBIGUOUS: return "*AMBIGUOUS*"; case HOME: return "*HOME*"; default: if (loc < 0 || loc >= db_top) return "*INVALID*"; if ((player == NOTHING) || (!(FLAGS(player) & STICKY) && (can_link_to(player, NOTYPE, loc) || ((Typeof(loc) != TYPE_PLAYER) && (controls_link(player, loc) || (FLAGS(loc) & CHOWN_OK)))))) { /* show everything */ snprintf(buf, sizeof(buf), "%.*s(#%d%s)", (BUFFER_LEN / 2), NAME(loc), loc, unparse_flags(loc)); return buf; } else { /* show only the name */ return NAME(loc); } } }
/* utility for open and link */ static dbref parse_linkable_room(dbref player, const char *room_name) { dbref room; /* parse room */ if (!strcasecmp(room_name, "here")) { room = IsExit(player) ? Source(player) : Location(player); } else if (!strcasecmp(room_name, "home")) { return HOME; /* HOME is always linkable */ } else { room = parse_objid(room_name); } /* check room */ if (!GoodObject(room)) { notify(player, T("That is not a valid object.")); return NOTHING; } else if (Going(room)) { notify(player, T("That room is being destroyed. Sorry.")); return NOTHING; } else if (!can_link_to(player, room)) { notify(player, T("You can't link to that.")); return NOTHING; } else { return room; } }
const char * unparse_object(dbref player, dbref loc) { char tbuf[BUFFER_LEN]; if (Typeof(player) != TYPE_PLAYER) player = OWNER(player); switch (loc) { case NOTHING: return "*NOTHING*"; case AMBIGUOUS: return "*AMBIGUOUS*"; case HOME: return "*HOME*"; case NIL: return "*NIL*"; default: if (loc < 0 || loc >= db_top) #ifdef SANITY { sprintf(upb, "*INVALID*(#%d)", loc); return upb; } #else return "*INVALID*"; #endif #ifndef SANITY if (!(FLAGS(player) & STICKY) && (TMage(player) || POWERS(player) & POW_SEE_ALL || can_link_to(player, NOTYPE, loc) || controls_link(player, loc) || ((Typeof(loc) != TYPE_PLAYER) && (FLAGS(loc) & CHOWN_OK)) )) { /* show everything */ #endif sprintf(upb, "%s(#%d%s)", NAME(loc), loc, unparse_flags(loc, tbuf)); return upb; #ifndef SANITY } else { /* show only the name */ return NAME(loc); } #endif } }
const char * unparse_object(dbref player, dbref loc) { static char buf[BUFFER_LEN]; if (Typeof(player) != TYPE_PLAYER) player = OWNER(player); switch (loc) { case NOTHING: return "*NOTHING*"; case AMBIGUOUS: return "*AMBIGUOUS*"; case HOME: return "*HOME*"; default: if (loc < 0 || loc > db_top) #ifdef SANITY { sprintf(buf, "*INVALID*(#%d)", loc); return buf; } #else return "*INVALID*"; #endif #ifndef SANITY if (!(FLAGS(player) & STICKY) && (can_link_to(player, NOTYPE, loc) || ((Typeof(loc) != TYPE_PLAYER) && (controls_link(player, loc) || (FLAGS(loc) & CHOWN_OK))) )) { /* show everything */ #endif sprintf(buf, "%s(#%d%s)", PNAME(loc), loc, unparse_flags(loc)); return buf; #ifndef SANITY } else { /* show only the name */ return PNAME(loc); } #endif } }
const char * ansi_unparse_object(dbref player, dbref loc) { char tbuf[BUFFER_LEN], tbuf2[BUFFER_LEN]; if (Typeof(player) != TYPE_PLAYER) player = OWNER(player); switch (loc) { case NOTHING: return SYSNORMAL "*NOTHING*"; case AMBIGUOUS: return SYSPURPLE "*AMBIGUOUS*"; case HOME: return SYSWHITE "*HOME*"; case NIL: return SYSCYAN "*NIL*"; default: if (loc < 0 || loc >= db_top) { sprintf(upb, SYSRED "*INVALID(#%d)*", loc); return upb; } #ifndef SANITY if (!(FLAGS(player) & STICKY) && (TMage(player) || POWERS(player) & POW_SEE_ALL || POWERS(player) & POW_SEARCH || can_link_to(player, NOTYPE, loc) || controls_link(player, loc) || ((Typeof(loc) != TYPE_PLAYER) && (FLAGS(loc) & CHOWN_OK)) )) { #endif /* show everything */ sprintf(upb, "%s" SYSYELLOW "(#%d%s)", ansiname(loc, tbuf), loc, unparse_flags(loc, tbuf2)); return upb; #ifndef SANITY } else { /* show only the name */ return ansiname(loc, upb); } #endif } }
static dbref parse_linkable_dest(int descr, dbref player, dbref exit, const char *dest_name) { dbref dobj; /* destination room/player/thing/link */ char buf[BUFFER_LEN]; struct match_data md; init_match(descr, player, dest_name, NOTYPE, &md); match_absolute(&md); match_everything(&md); match_home(&md); match_null(&md); if ((dobj = match_result(&md)) == NOTHING || dobj == AMBIGUOUS) { sprintf(buf, CINFO "I couldn't find '%s'.", dest_name); anotify_nolisten2(player, buf); return NOTHING; } if (!tp_teleport_to_player && Typeof(dobj) == TYPE_PLAYER) { sprintf(buf, CFAIL "You can't link to players. Destination %s ignored.", unparse_object(player, dobj)); anotify_nolisten2(player, buf); return NOTHING; } if (!can_link(player, exit)) { anotify_nolisten2(player, CFAIL "You can't link that."); return NOTHING; } if (!can_link_to(player, Typeof(exit), dobj)) { sprintf(buf, CFAIL "You can't link to %s.", unparse_object(player, dobj)); anotify_nolisten2(player, buf); return NOTHING; } else return dobj; }
const char * ansi_unparse_object(dbref player, dbref loc) { char tbuf[BUFFER_LEN], tbuf2[BUFFER_LEN]; if (Typeof(player) != TYPE_PLAYER) player = OWNER(player); switch (loc) { case NOTHING: return CGLOOM "*NOTHING*"; case AMBIGUOUS: return CPURPLE "*AMBIGUOUS*"; case HOME: return CWHITE "*HOME*"; default: if (!OkObj(loc)) return CRED "*INVALID*"; #ifndef SANITY if (!(FLAGS(player) & STICKY) && (TMage(player) || can_link_to(player, NOTYPE, loc) || controls_link(player, loc) || ((Typeof(loc) != TYPE_PLAYER) && (FLAGS(loc) & CHOWN_OK)) )) { #endif /* show everything */ sprintf(upb, "%s" CYELLOW "(#%d%s)", ansiname(loc, tbuf), loc, unparse_flags(loc, tbuf2)); return upb; #ifndef SANITY } else { /* show only the name */ return ansiname(loc, upb); } #endif } }
struct frame * interp(int descr, dbref player, dbref location, dbref program, dbref source, int nosleeps, int whichperms, int forced_pid) { struct frame *fr; int i; if (!MLevel(program) || !MLevel(OWNER(program)) || ((source != NOTHING) && !TrueWizard(OWNER(source)) && !can_link_to(OWNER(source), TYPE_EXIT, program))) { notify_nolisten(player, "Program call: Permission denied.", 1); return 0; } if (free_frames_list) { fr = free_frames_list; free_frames_list = fr->next; } else { fr = (struct frame *) malloc(sizeof(struct frame)); } fr->next = NULL; fr->pid = forced_pid ? forced_pid : top_pid++; fr->descr = descr; fr->multitask = nosleeps; fr->perms = whichperms; fr->already_created = 0; fr->been_background = (nosleeps == 2); fr->trig = source; fr->events = NULL; fr->timercount = 0; fr->started = time(NULL); fr->instcnt = 0; fr->skip_declare = 0; fr->wantsblanks = 0; fr->caller.top = 1; fr->caller.st[0] = source; fr->caller.st[1] = program; fr->system.top = 1; fr->system.st[0].progref = 0; fr->system.st[0].offset = 0; fr->waitees = NULL; fr->waiters = NULL; fr->fors.top = 0; fr->fors.st = NULL; fr->trys.top = 0; fr->trys.st = NULL; fr->errorstr = NULL; fr->errorinst = NULL; fr->errorprog = NOTHING; fr->errorline = 0; fr->rndbuf = NULL; fr->dlogids = NULL; fr->argument.top = 0; fr->pc = PROGRAM_START(program); fr->writeonly = ((source == -1) || (Typeof(source) == TYPE_ROOM) || ((Typeof(source) == TYPE_PLAYER) && (!online(source))) || (FLAGS(player) & READMODE)); fr->level = 0; fr->error.is_flags = 0; /* set basic local variables */ fr->svars = NULL; fr->lvars = NULL; for (i = 0; i < MAX_VAR; i++) { fr->variables[i].type = PROG_INTEGER; fr->variables[i].data.number = 0; } fr->brkpt.force_debugging = 0; fr->brkpt.debugging = 0; fr->brkpt.bypass = 0; fr->brkpt.isread = 0; fr->brkpt.showstack = 0; fr->brkpt.dosyspop = 0; fr->brkpt.lastline = 0; fr->brkpt.lastpc = 0; fr->brkpt.lastlisted = 0; fr->brkpt.lastcmd = NULL; fr->brkpt.breaknum = -1; fr->brkpt.lastproglisted = NOTHING; fr->brkpt.proglines = NULL; fr->brkpt.count = 1; fr->brkpt.temp[0] = 1; fr->brkpt.level[0] = -1; fr->brkpt.line[0] = -1; fr->brkpt.linecount[0] = -2; fr->brkpt.pc[0] = NULL; fr->brkpt.pccount[0] = -2; fr->brkpt.prog[0] = program; fr->proftime.tv_sec = 0; fr->proftime.tv_usec = 0; fr->totaltime.tv_sec = 0; fr->totaltime.tv_usec = 0; fr->variables[0].type = PROG_OBJECT; fr->variables[0].data.objref = player; fr->variables[1].type = PROG_OBJECT; fr->variables[1].data.objref = location; fr->variables[2].type = PROG_OBJECT; fr->variables[2].data.objref = source; fr->variables[3].type = PROG_STRING; fr->variables[3].data.string = (!*match_cmdname) ? 0 : alloc_prog_string(match_cmdname); if (PROGRAM_CODE(program)) { PROGRAM_INC_PROF_USES(program); } PROGRAM_INC_INSTANCES(program); push(fr->argument.st, &(fr->argument.top), PROG_STRING, *match_args ? MIPSCAST alloc_prog_string(match_args) : 0); return fr; }
/** Link an exit, room, player, or thing. * \verbatim * This is the top-level function for @link, which is used to link an * exit to a destination, set a player or thing's home, or set a * drop-to on a room. * * Linking an exit usually seizes ownership of the exit and costs 1 penny. * 1 penny is also transferred to the former owner. * \endverbatim * \param player the enactor. * \param name the name of the object to link. * \param room_name the name of the link destination. * \param preserve if 1, preserve ownership and zone data on exit relink. */ void do_link(dbref player, const char *name, const char *room_name, int preserve) { /* Use this to link to a room that you own. * It usually seizes ownership of the exit and costs 1 penny, * plus a penny transferred to the exit owner if they aren't you. * You must own the linked-to room AND specify it by room number. */ dbref thing; dbref room; if (!room_name || !*room_name) { do_unlink(player, name); return; } if (!IsRoom(player) && GoodObject(Location(player)) && IsExit(Location(player))) { notify(player, T("You somehow wound up in a exit. No biscuit.")); return; } if ((thing = noisy_match_result(player, name, TYPE_EXIT, MAT_EVERYTHING)) != NOTHING) { switch (Typeof(thing)) { case TYPE_EXIT: if ((room = check_var_link(room_name)) == NOTHING) room = parse_linkable_room(player, room_name); if (room == NOTHING) return; if (GoodObject(room) && !can_link_to(player, room)) { notify(player, T("Permission denied.")); break; } /* We may link an exit if it's unlinked and we pass the link-lock * or if we control it. */ if (!(controls(player, thing) || ((Location(thing) == NOTHING) && eval_lock(player, thing, Link_Lock)))) { notify(player, T("Permission denied.")); return; } if (preserve && !Wizard(player)) { notify(player, T("Permission denied.")); return; } /* handle costs */ if (Owner(thing) == Owner(player)) { if (!payfor(player, LINK_COST)) { notify_format(player, T("It costs %d %s to link this exit."), LINK_COST, ((LINK_COST == 1) ? MONEY : MONIES)); return; } } else { if (!payfor(player, LINK_COST + EXIT_COST)) { int a = LINK_COST + EXIT_COST; notify_format(player, T("It costs %d %s to link this exit."), a, ((a == 1) ? MONEY : MONIES)); return; } else if (!preserve) { /* pay the owner for his loss */ giveto(Owner(thing), EXIT_COST); chown_object(player, thing, player, 0); } } /* link has been validated and paid for; do it */ if (!preserve) { Owner(thing) = Owner(player); Zone(thing) = Zone(player); } Location(thing) = room; /* notify the player */ notify_format(player, T("Linked exit #%d to %s"), thing, unparse_object(player, room)); break; case TYPE_PLAYER: case TYPE_THING: if ((room = noisy_match_result(player, room_name, NOTYPE, MAT_EVERYTHING)) == NOTHING) { notify(player, T("No match.")); return; } if (IsExit(room)) { notify(player, T("That is an exit.")); return; } if (thing == room) { notify(player, T("You may not link something to itself.")); return; } /* abode */ if (!controls(player, room) && !Abode(room)) { notify(player, T("Permission denied.")); break; } if (!controls(player, thing)) { notify(player, T("Permission denied.")); } else if (room == HOME) { notify(player, T("Can't set home to home.")); } else { /* do the link */ Home(thing) = room; /* home */ if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player))) notify(player, T("Home set.")); } break; case TYPE_ROOM: if ((room = parse_linkable_room(player, room_name)) == NOTHING) return; if ((room != HOME) && (!IsRoom(room))) { notify(player, T("That is not a room!")); return; } if (!controls(player, thing)) { notify(player, T("Permission denied.")); } else { /* do the link, in location */ Location(thing) = room; /* dropto */ notify(player, T("Dropto set.")); } break; default: notify(player, T("Internal error: weird object type.")); do_log(LT_ERR, NOTHING, NOTHING, "Weird object! Type of #%d is %d", thing, Typeof(thing)); break; } } }
/* * do_dig * * Use this to create a room. */ void do_dig(int descr, dbref player, const char *name, const char *pname) { char *rname, *qname; dbref newparent; char rbuf[BUFFER_LEN]; char qbuf[BUFFER_LEN]; char buf[BUFFER_LEN]; dbref room; struct match_data md; dbref parent; if (!Builder(player) && !tp_all_can_build_rooms) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } if (!tp_building || tp_db_readonly) { anotify_nolisten2(player, CFAIL NOBUILD_MESG); return; } if (*name == '\0') { anotify_nolisten2(player, CINFO "You need name for the room."); return; } if (!ok_name(name)) { anotify_nolisten2(player, CINFO "That's a silly name for a room!"); return; } if (!payfor(player, tp_room_cost)) { anotify_fmt(player, CFAIL "You don't have enough %s to dig a room.", tp_pennies); return; } room = new_object(player); /* Initialize everything */ newparent = DBFETCH(DBFETCH(player)->location)->location; while ((OkObj(newparent)) && !(FLAGS(newparent) & ABODE) && !(FLAG2(newparent) & F2PARENT)) newparent = DBFETCH(newparent)->location; if (!OkObj(newparent)) { if (OkObj(tp_default_parent)) newparent = tp_default_parent; else newparent = GLOBAL_ENVIRONMENT; } NAME(room) = alloc_string(name); DBFETCH(room)->location = newparent; OWNER(room) = OWNER(player); DBFETCH(room)->exits = NOTHING; DBFETCH(room)->sp.room.dropto = NOTHING; FLAGS(room) = TYPE_ROOM | (FLAGS(player) & JUMP_OK); PUSH(room, DBFETCH(newparent)->contents); DBDIRTY(room); DBDIRTY(newparent); sprintf(buf, CSUCC "Room %s created.", unparse_object(player, room)); anotify_nolisten2(player, buf); strcpy(buf, pname); for (rname = buf; (*rname && (*rname != '=')); rname++) ; qname = rname; if (*rname) *(rname++) = '\0'; while ((qname > buf) && (isspace(*qname))) *(qname--) = '\0'; qname = buf; for (; *rname && isspace(*rname); rname++) ; rname = strcpy(rbuf, rname); qname = strcpy(qbuf, qname); if (*qname) { anotify_nolisten2(player, CNOTE "Trying to set parent..."); init_match(descr, player, qname, TYPE_ROOM, &md); match_absolute(&md); match_registered(&md); match_here(&md); if ((parent = noisy_match_result(&md)) == NOTHING || parent == AMBIGUOUS) { anotify_nolisten2(player, CINFO "Parent set to default."); } else { if ((!can_link_to(player, Typeof(room), parent) && !(FLAG2(parent) & F2PARENT)) || room == parent) { anotify_nolisten2(player, CFAIL "Permission denied. Parent set to default."); } else { moveto(room, parent); sprintf(buf, CSUCC "Parent set to %s.", unparse_object(player, parent)); anotify_nolisten2(player, buf); } } } if (*rname) { PData pdat; sprintf(buf, "_reg/%s", rname); pdat.flags = PROP_REFTYP; pdat.data.ref = room; set_property(player, buf, &pdat); sprintf(buf, CINFO "Room registered as $%s", rname); anotify_nolisten2(player, buf); } }
/* do_link * * Use this to link to a room that you own. It also sets home for * objects and things, and drop-to's for rooms. * It seizes ownership of an unlinked exit, and costs 1 penny * plus a penny transferred to the exit owner if they aren't you * * All destinations must either be owned by you, or be LINK_OK. */ void do_link(int descr, dbref player, const char *thing_name, const char *dest_name) { dbref good_dest[MAX_LINKS]; int ndest, i; struct match_data md; char buf[BUFFER_LEN]; dbref thing, dest; if (tp_db_readonly) { anotify_nolisten2(player, CFAIL DBRO_MESG); return; } if (Guest(player)) { anotify_fmt(player, CFAIL "%s", tp_noguest_mesg); return; } init_match(descr, player, thing_name, TYPE_EXIT, &md); match_all_exits(&md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); if (Mage(OWNER(player))) match_player(&md); if ((thing = noisy_match_result(&md)) == NOTHING) return; switch (Typeof(thing)) { case TYPE_EXIT: /* we're ok, check the usual stuff */ if (DBFETCH(thing)->sp.exit.ndest != 0) { if (controls(player, thing)) { if ((DBFETCH(thing)->sp.exit.dest)[0] != NIL) { anotify_nolisten2(player, CINFO "That exit is already linked."); return; } } else { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } } /* handle costs */ if (OWNER(thing) == OWNER(player)) { if (!payfor(player, tp_link_cost)) { anotify_fmt(player, CFAIL "It costs %d %s to link this exit.", tp_link_cost, (tp_link_cost == 1) ? tp_penny : tp_pennies); return; } } else { if (!payfor(player, tp_link_cost + tp_exit_cost)) { anotify_fmt(player, CFAIL "It costs %d %s to link this exit.", (tp_link_cost + tp_exit_cost), (tp_link_cost + tp_exit_cost == 1) ? tp_penny : tp_pennies); return; } else if (!Builder(player)) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } else { /* pay the owner for his loss */ dbref owner = OWNER(thing); DBFETCH(owner)->sp.player.pennies += tp_exit_cost; DBDIRTY(owner); } } /* link has been validated and paid for; do it */ OWNER(thing) = OWNER(player); if (! (ndest = link_exit(descr, player, thing, (char *) dest_name, good_dest))) { anotify_nolisten2(player, CFAIL "No destinations linked."); DBFETCH(player)->sp.player.pennies += tp_link_cost; /* Refund! */ DBDIRTY(player); break; } DBFETCH(thing)->sp.exit.ndest = ndest; if (DBFETCH(thing)->sp.exit.dest) free(DBFETCH(thing)->sp.exit.dest); DBFETCH(thing)->sp.exit.dest = (dbref *) malloc(sizeof(dbref) * ndest); for (i = 0; i < ndest; i++) (DBFETCH(thing)->sp.exit.dest)[i] = good_dest[i]; break; case TYPE_THING: case TYPE_PLAYER: init_match(descr, player, dest_name, TYPE_ROOM, &md); match_neighbor(&md); match_absolute(&md); match_registered(&md); match_me(&md); match_here(&md); match_null(&md); if (Typeof(thing) == TYPE_THING) match_possession(&md); if ((dest = noisy_match_result(&md)) == NOTHING) return; if (Typeof(thing) == TYPE_THING && dest == NIL) { anotify_fmt(player, CFAIL "%s", "You cannot HOME a THING to NIL."); return; } if (!controls(player, thing) || !can_link_to(player, Typeof(thing), dest)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } if (parent_loop_check(thing, dest)) { anotify_nolisten2(player, CFAIL "That would cause a parent paradox."); return; } /* do the link */ if (Typeof(thing) == TYPE_THING) { DBFETCH(thing)->sp.thing.home = dest; } else DBFETCH(thing)->sp.player.home = dest; sprintf(buf, CSUCC "%s's home set to %s.", NAME(thing), unparse_object(player, dest)); anotify_nolisten2(player, buf); break; case TYPE_ROOM: /* room dropto's */ init_match(descr, player, dest_name, TYPE_ROOM, &md); match_neighbor(&md); match_possession(&md); match_registered(&md); match_absolute(&md); match_home(&md); match_null(&md); if ((dest = noisy_match_result(&md)) == NOTHING) break; if (!controls(player, thing) || !can_link_to(player, Typeof(thing), dest) || (thing == dest)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); } else { DBFETCH(thing)->sp.room.dropto = dest; /* dropto */ sprintf(buf, CSUCC "%s's dropto set to %s.", NAME(thing), unparse_object(player, dest)); anotify_nolisten2(player, buf); } break; case TYPE_PROGRAM: anotify_nolisten2(player, CFAIL "You can't link programs to things!"); break; default: anotify_nolisten2(player, CFAIL "Weird object type."); log_status("*BUG: weird object: Typeof(%d) = %d\n", thing, Typeof(thing)); break; } DBDIRTY(thing); return; }
void do_teleport(int descr, dbref player, const char *arg1, const char *arg2) { dbref victim; dbref destination; const char *to; struct match_data md; /* get victim, destination */ if (*arg2 == '\0') { victim = player; to = arg1; } else { init_match(descr, player, arg1, NOTYPE, &md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); match_player(&md); if ((victim = noisy_match_result(&md)) == NOTHING) { return; } to = arg2; } #ifdef GOD_PRIV if(tp_strict_god_priv && !God(player) && God(OWNER(victim))) { notify(player, "God has already set that where He wants it to be."); return; } #endif /* get destination */ init_match(descr, player, to, TYPE_PLAYER, &md); match_possession(&md); match_me(&md); match_here(&md); match_home(&md); match_absolute(&md); match_registered(&md); if (Wizard(OWNER(player))) { match_neighbor(&md); match_player(&md); } switch (destination = match_result(&md)) { case NOTHING: notify(player, "Send it where?"); break; case AMBIGUOUS: notify(player, "I don't know which destination you mean!"); break; case HOME: switch (Typeof(victim)) { case TYPE_PLAYER: destination = PLAYER_HOME(victim); if (parent_loop_check(victim, destination)) destination = PLAYER_HOME(OWNER(victim)); break; case TYPE_THING: destination = THING_HOME(victim); if (parent_loop_check(victim, destination)) { destination = PLAYER_HOME(OWNER(victim)); if (parent_loop_check(victim, destination)) { destination = (dbref) 0; } } break; case TYPE_ROOM: destination = GLOBAL_ENVIRONMENT; break; case TYPE_PROGRAM: destination = OWNER(victim); break; default: destination = tp_player_start; /* caught in the next * switch anyway */ break; } default: switch (Typeof(victim)) { case TYPE_PLAYER: if (!controls(player, victim) || !controls(player, destination) || !controls(player, getloc(victim)) || (Typeof(destination) == TYPE_THING && !controls(player, getloc(destination)))) { notify(player, "Permission denied. (must control victim, dest, victim's loc, and dest's loc)"); break; } if (Typeof(destination) != TYPE_ROOM && Typeof(destination) != TYPE_THING) { notify(player, "Bad destination."); break; } if (!Wizard(victim) && (Typeof(destination) == TYPE_THING && !(FLAGS(destination) & VEHICLE))) { notify(player, "Destination object is not a vehicle."); break; } if (parent_loop_check(victim, destination)) { notify(player, "Objects can't contain themselves."); break; } notify(victim, "You feel a wrenching sensation..."); enter_room(descr, victim, destination, DBFETCH(victim)->location); notify(player, "Teleported."); break; case TYPE_THING: if (parent_loop_check(victim, destination)) { notify(player, "You can't make a container contain itself!"); break; } case TYPE_PROGRAM: if (Typeof(destination) != TYPE_ROOM && Typeof(destination) != TYPE_PLAYER && Typeof(destination) != TYPE_THING) { notify(player, "Bad destination."); break; } if (!((controls(player, destination) || can_link_to(player, NOTYPE, destination)) && (controls(player, victim) || controls(player, DBFETCH(victim)->location)))) { notify(player, "Permission denied. (must control dest and be able to link to it, or control dest's loc)"); break; } /* check for non-sticky dropto */ if (Typeof(destination) == TYPE_ROOM && DBFETCH(destination)->sp.room.dropto != NOTHING && !(FLAGS(destination) & STICKY)) destination = DBFETCH(destination)->sp.room.dropto; if (tp_thing_movement && (Typeof(victim) == TYPE_THING)) { enter_room(descr, victim, destination, DBFETCH(victim)->location); } else { moveto(victim, destination); } notify(player, "Teleported."); break; case TYPE_ROOM: if (Typeof(destination) != TYPE_ROOM) { notify(player, "Bad destination."); break; } if (!controls(player, victim) || !can_link_to(player, NOTYPE, destination) || victim == GLOBAL_ENVIRONMENT) { notify(player, "Permission denied. (Can't move #0, dest must be linkable, and must control victim)"); break; } if (parent_loop_check(victim, destination)) { notify(player, "Parent would create a loop."); break; } moveto(victim, destination); notify(player, "Parent set."); break; case TYPE_GARBAGE: notify(player, "That object is in a place where magic cannot reach it."); break; default: notify(player, "You can't teleport that."); break; } break; } return; }