/* move.c */ #include "copyright.h" #include <ctype.h> #include "config.h" #include "db.h" #include "interface.h" #include "match.h" #include "externs.h" #include "globals.h" void enter_room(); void moveto(what, where) dbref what; dbref where; { enter_room(what, where); } void moveit(what, where) dbref what; dbref where; { dbref loc, old; /* remove what from old loc */ if ((loc = old = db[what].location) != NOTHING) { db[loc].contents = remove_first(db[loc].contents, what); } /* test for special cases */ switch (where) { case NOTHING: db[what].location = NOTHING; return; /* NOTHING doesn't have contents */ case HOME: where = db[what].exits; /* home */ safe_tel(what, where); return; /*NOTREACHED*/ break; } /* now put what in where */ PUSH(what, db[where].contents); db[what].location = where; if (Hearer(what) && (where != NOTHING) && !Dark(where) && (old != where)) { did_it(what, old, "LEAVE", NULL, "OLEAVE", "has left.", "ALEAVE", old); if(Typeof(where) != TYPE_ROOM) did_it(what, where, NULL, NULL, "OXENTER", NULL, NULL, old); if(Typeof(old) != TYPE_ROOM) did_it(what, old, NULL, NULL, "OXLEAVE", NULL, NULL, where); did_it(what, where, "ENTER", NULL, "OENTER", "has arrived.", "AENTER", where); did_it(what, what, "MOVE", NULL, "OMOVE", NULL, "AMOVE", where); } } #define Dropper(thing) (Hearer(thing) && \ (db[db[thing].owner].flags & PLAYER_CONNECT)) void send_contents(loc, dest) dbref loc; dbref dest; { dbref first; dbref rest; first = db[loc].contents; db[loc].contents = NOTHING; /* blast locations of everything in list */ DOLIST(rest, first) { db[rest].location = NOTHING; } while (first != NOTHING) { rest = db[first].next; if (Dropper(first)) { db[first].location = loc; PUSH(first, db[loc].contents); } else enter_room(first, (db[first].flags & STICKY) ? HOME : dest); first = rest; } db[loc].contents = reverse(db[loc].contents); } void maybe_dropto(loc, dropto) dbref loc; dbref dropto; { dbref thing; if (loc == dropto) return; /* bizarre special case */ if (Typeof(loc) != TYPE_ROOM) return; /* check for players */ DOLIST(thing, db[loc].contents) { if (Dropper(thing)) return; } /* no players, send everything to the dropto */ send_contents(loc, dropto); } void enter_room(player, loc) dbref player; dbref loc; { dbref old; dbref dropto; static int deep = 0; if (deep++ > 15) { deep--; return; } if(player < 0 || player >= db_top) { deep--; return; } #ifdef notdef if (loc == NOTHING) { /* death to -1 */ free_object(player); deep--; return; } #endif /* check for room == HOME */ if (loc == HOME) loc = db[player].exits; /* home */ if ((Typeof(player) != TYPE_PLAYER) && (Typeof(player) != TYPE_THING)) { fprintf(stderr, "ERROR: Non object moved!! %d\n", player); fflush(stderr); deep--; return; } if (Typeof(loc) == TYPE_EXIT) { fprintf(stderr, "ERROR: Attempt to move %d to exit %d\n", player, loc); deep--; return; } /* get old location */ old = db[player].location; /* go there */ moveit(player, loc); /* if old location has STICKY dropto, send stuff through it */ if ((loc != old) && Dropper(player) && (old != NOTHING) && (Typeof(old) == TYPE_ROOM) && ((dropto = db[old].location) != NOTHING) && (db[old].flags & STICKY)) maybe_dropto(old, dropto); /* autolook */ look_room(player, loc, 0); deep--; } /* teleports player to location while removing items they shouldnt take */ void safe_tel(player, dest) dbref player; dbref dest; { dbref first; dbref rest; if (dest == HOME) dest = db[player].exits; if (db[db[player].location].owner == db[dest].owner) { enter_room(player, dest); return; } first = db[player].contents; db[player].contents = NOTHING; /* blast locations of everything in list */ DOLIST(rest, first) { db[rest].location = NOTHING; } while (first != NOTHING) { rest = db[first].next; /* if thing is ok to take then move to player else send home */ /* thing is not okay to move if it's KEY, or it's STICKY and its */ /* home is not the player */ if (controls(player, first) || ((Typeof(first) == TYPE_THING && !(db[first].flags & THING_KEY)) && (!(db[first].flags & STICKY) || (db[first].exits == player)))) { PUSH(first, db[player].contents); db[first].location = player; } else enter_room(first, HOME); first = rest; } db[player].contents = reverse(db[player].contents); enter_room(player, dest); } int can_move(player, direction) dbref player; const char *direction; { if (!string_compare(direction, "home")) return 1; /* otherwise match on exits */ init_match(player, direction, TYPE_EXIT); match_exit(); return (last_match_result() != NOTHING); } void do_move(player, direction, type) dbref player; const char *direction; int type; /* type 0 is normal, type 1 is global */ { dbref exit; dbref loc; if (!string_compare(direction, "home")) { /* send him home */ /* but steal all his possessions */ if ((loc = db[player].location) != NOTHING && !Dark(player) && !Dark(loc)){ /* tell everybody else */ notify_except(db[loc].contents, player, tprintf("%s goes home.", db[player].name)); } /* give the player the messages */ notify(player, "There's no place like home..."); notify(player, "There's no place like home..."); notify(player, "There's no place like home..."); safe_tel(player, HOME); } else { /* find the exit */ #ifdef DO_GLOBALS if (type == 1) init_match_global_check_keys(player, direction, TYPE_EXIT); else #endif init_match_check_keys(player, direction, TYPE_EXIT); match_exit(); switch (exit = match_result()) { case NOTHING: /* try to force the object */ notify(player, "You can't go that way."); break; case AMBIGUOUS: notify(player, "I don't know which way you mean!"); break; default: /* we got one */ /* check to see if we got through */ if (could_doit(player, exit)) { did_it(player, exit, "SUCCESS", NULL, "OSUCCESS", NULL, "ASUCCESS", NOTHING); did_it(player, exit, "DROP", NULL, "ODROP", NULL, "ADROP", db[exit].location); switch (Typeof(db[exit].location)) { case TYPE_ROOM: enter_room(player, db[exit].location); break; case TYPE_PLAYER: case TYPE_THING: { if (db[db[exit].location].flags & GOING) { notify(player, "You can't go that way."); return; } if (db[db[exit].location].location == NOTHING) return; safe_tel(player, db[exit].location); } break; case TYPE_EXIT: notify(player, "This feature coming soon."); break; } } else did_it(player, exit, "FAILURE", "You can't go that way.", "OFAILURE", NULL, "AFAILURE", NOTHING); break; } } } void do_get(player, what) dbref player; const char *what; { dbref loc = db[player].location; dbref thing; if ((Typeof(loc) != TYPE_ROOM) && !(db[loc].flags & ENTER_OK) && !controls(player, loc)) { notify(player, "Permission denied."); return; } if(((thing = is_possess(player, what)) != NOTHING) && (thing != AMBIGUOUS)) { if(could_doit(player,thing) && (db[db[thing].location].flags & ENTER_OK)) { notify(db[thing].location, tprintf("%s was taken from you.",db[thing].name)); moveto(thing,player); notify(thing, "Taken."); did_it(player, thing, "SUCCESS", "Taken.", "OSUCCESS", NULL, "ASUCCESS", NOTHING); } else did_it(player, thing, "FAILURE", "You can't take that from there.", "OFAILURE", NULL, "AFAILURE", NOTHING); } else { init_match_check_keys(player, what, TYPE_THING); match_neighbor(); match_exit(); if (Wizard(player)) match_absolute(); /* the wizard has long fingers */ if ((thing = noisy_match_result()) != NOTHING) { if (db[thing].location == player) { notify(player, "You already have that!"); return; } switch (Typeof(thing)) { case TYPE_PLAYER: case TYPE_THING: if (thing == player) { notify(player, "You cannot get yourself!"); return; } if (could_doit(player, thing)) { moveto(thing, player); notify(thing, "Taken."); did_it(player, thing, "SUCCESS", "Taken.", "OSUCCESS", NULL, "ASUCCESS", NOTHING); } else did_it(player, thing, "FAILURE", "You can't pick that up.", "OFAILURE", NULL, "AFAILURE", NOTHING); break; case TYPE_EXIT: notify(player, "You can't pick up exits."); return; default: notify(player, "You can't take that!"); break; } } } } void do_drop(player, name) dbref player; const char *name; { dbref loc; dbref thing; int reward; char tbuf1[BUFFER_LEN]; if ((loc = getloc(player)) == NOTHING) return; init_match(player, name, TYPE_THING); match_possession(); switch (thing = match_result()) { case NOTHING: notify(player, "You don't have that!"); return; case AMBIGUOUS: notify(player, "I don't know which you mean!"); return; default: if (db[thing].location != player) { /* Shouldn't ever happen. */ notify(player, "You can't drop that."); } else if (Typeof(thing) == TYPE_EXIT) { notify(player, "Sorry you can't drop exits."); return; } else if (db[loc].flags & ROOM_TEMPLE) { /* sacrifice time */ if (Typeof(thing) == TYPE_PLAYER) { notify(player, "Hey! No blood sacrifices please!."); return; } if (db[thing].flags & THING_SAFE) { notify(player, "That object is marked SAFE and cannot be sacrificed."); return; } notify(thing, "You have been sacrificed."); moveto(thing, NOTHING); /* Patched to destroy sacrificed objects */ notify(player, tprintf("%s is consumed in a burst of flame!", db[thing].name)); #ifdef FULL_INVIS if(!Dark(player)) { notify_except(db[loc].contents, player, tprintf("%s sacrifices %s.", db[player].name, db[thing].name)); } else { notify_except(db[loc].contents, player, tprintf("Someone sacrifices %s.", db[thing].name)); } #else notify_except(db[loc].contents, player, tprintf("%s sacrifices %s.", db[player].name, db[thing].name)); #endif /* check for reward */ if (!controls(player, thing) || (Typeof(player) != TYPE_PLAYER)) { reward = Pennies(thing); if (reward < 1 || (Pennies(db[player].owner) > MAX_PENNIES)) { reward = 1; } else if (reward > MAX_OBJECT_ENDOWMENT) { reward = MAX_OBJECT_ENDOWMENT; } giveto(db[player].owner, reward); notify(player, tprintf("You have received %d %s for your sacrifice.", reward, reward == 1 ? MONEY : MONIES)); db[thing].flags |= THING_DEST_OK; do_destroy(player,tprintf("#%d",thing), 1); } } else if (db[thing].flags & STICKY) { notify(thing, "Dropped."); safe_tel(thing, HOME); } else if (db[loc].location != NOTHING && (Typeof(loc) == TYPE_ROOM) && !(db[loc].flags & STICKY)) { /* location has immediate dropto */ notify(thing, "Dropped."); moveto(thing, db[loc].location); } else { notify(thing, "Dropped."); moveto(thing, loc); } break; } sprintf(tbuf1, "dropped %s.", db[thing].name); did_it(player, thing, "DROP", "Dropped.", "ODROP", tbuf1, "ADROP", NOTHING); } void do_enter(player, what) dbref player; const char *what; { dbref thing; init_match_check_keys(player, what, TYPE_THING); match_neighbor(); match_exit(); match_absolute(); /* necessary for enter aliases to work */ if ((thing = noisy_match_result()) == NOTHING) { /* notify(player,"I don't see that here."); */ return; } switch (Typeof(thing)) { case TYPE_ROOM: case TYPE_EXIT: notify(player, "Permission denied."); break; default: /* the object must pass the lock. Also, the thing being entered */ /* has to be controlled, or must be enter_ok */ if (!(((db[thing].flags & ENTER_OK) || controls(player, thing)) && (eval_boolexp(player, db[thing].enterkey, thing, 0, ENTERLOCK)))) { did_it(player, thing, "EFAIL", "Permission denied.", "OEFAIL", NULL, "AEFAIL", NOTHING); return; } if(thing == player) { notify(player, "Sorry, you must remain beside yourself!"); return; } safe_tel(player, thing); break; } } void do_leave(player) dbref player; { if (Typeof(db[player].location) == TYPE_ROOM) { notify(player, "You can't leave"); return; } enter_room(player, db[db[player].location].location); } #ifdef DO_GLOBALS int global_exit (player, direction) dbref player; const char *direction; { init_match_global(player, direction, TYPE_EXIT); match_exit(); return (last_match_result() != NOTHING); } #endif