#include "copyright.h" #include "os.h" #include "db.h" #include "config.h" #include "interface.h" #include "match.h" #include "externs.h" void moveto (dbref what, dbref where) { dbref loc; /* remove what from old loc */ if ((loc = 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 */ break; } /* now put what in where */ PUSH (what, db[where].contents); db[what].location = where; } static void send_contents (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 (Typeof (first) != TYPE_THING) { moveto (first, loc); } else { moveto (first, (db[first].flags & STICKY) ? HOME : dest); } first = rest; } db[loc].contents = reverse (db[loc].contents); } void maybe_dropto (dbref loc, dbref dropto) { dbref thing; if (loc == dropto) return; /* bizarre special case */ /* check for players */ DOLIST (thing, db[loc].contents) { if (Typeof (thing) == TYPE_PLAYER) return; } /* no players, send everything to the dropto */ send_contents (loc, dropto); } void enter_room (dbref player, dbref loc) { dbref old; dbref dropto; char buf[BUFFER_LEN]; /* check for room == HOME */ if (loc == HOME) loc = db[player].exits; /* home */ /* get old location */ old = db[player].location; /* check for self-loop */ /* self-loops don't do move or other player notification */ /* but you still get autolook and penny check */ if (loc != old) { #ifdef TIMESTAMPS db[loc].usecnt++; db[loc].lastused = time (0); #endif /* TIMESTAMPS */ if (old != NOTHING) { /* notify others unless DARK */ if (!Dark (old) && !Dark (player)) { sprintf (buf, "%s has left.", db[player].name); notify_except (db[old].contents, player, buf); } } /* go there */ moveto (player, loc); /* if old location has STICKY dropto, send stuff through it */ if (old != NOTHING && (dropto = db[old].location) != NOTHING && (db[old].flags & STICKY)) { maybe_dropto (old, dropto); } /* tell other folks in new location if not DARK */ if (!Dark (loc) && !Dark (player)) { sprintf (buf, "%s has arrived.", db[player].name); notify_except (db[loc].contents, player, buf); } } /* autolook */ look_room (player, loc); /* check for pennies */ if (!controls (player, loc) && db[player].pennies <= MAX_PENNIES && OS_RAND () % PENNY_RATE == 0) { notify (player, "You found a penny!"); db[player].pennies++; } } void send_home (dbref thing) { switch (Typeof (thing)) { case TYPE_PLAYER: /* send his possessions home first! */ /* that way he sees them when he arrives */ send_contents (thing, HOME); enter_room (thing, db[thing].exits); /* home */ break; case TYPE_THING: moveto (thing, db[thing].exits); /* home */ break; default: /* no effect */ break; } } int can_move (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 (dbref player, const char *direction) { dbref exit; dbref loc; char buf[BUFFER_LEN]; if (!string_compare (direction, "home")) { /* send him home */ /* but steal all his possessions */ if ((loc = db[player].location) != NOTHING) { /* tell everybody else */ sprintf (buf, "%s goes home.", db[player].name); notify_except (db[loc].contents, player, buf); } /* 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..."); notify (player, "You wake up back home, without your possessions."); send_home (player); } else { /* find the exit */ init_match_check_keys (player, direction, TYPE_EXIT); match_exit (); switch (exit = match_result ()) { case NOTHING: 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 */ #ifdef TIMESTAMPS db[exit].usecnt++; db[exit].lastused = time (0); #endif /* TIMESTAMPS */ /* check to see if we got through */ if (can_doit (player, exit, "You can't go that way.")) { enter_room (player, db[exit].location); } break; } } } void do_get (dbref player, const char *what) { dbref loc; dbref thing; 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_THING: #ifdef TIMESTAMPS db[thing].usecnt++; db[thing].lastused = time (0); #endif /* TIMESTAMPS */ if (can_doit (player, thing, "You can't pick that up.")) { moveto (thing, player); notify (player, "Taken."); } break; case TYPE_EXIT: if (!controls (player, thing)) { notify (player, "You can't pick that up."); } else if (db[thing].location != NOTHING) { notify (player, "You can't pick up a linked exit."); #ifdef RESTRICTED_BUILDING } else if (!Builder (player)) { notify (player, "Only authorized builders may pick up exits."); #endif /* RESTRICTED_BUILDING */ } else { /* take it out of location */ if ((loc = getloc (player)) == NOTHING) return; if (!member (thing, db[loc].exits)) { notify (player, "You can't pick up an exit from another room."); return; } db[loc].exits = remove_first (db[loc].exits, thing); PUSH (thing, db[player].contents); db[thing].location = player; notify (player, "Exit taken."); } break; default: notify (player, "You can't take that!"); break; } } } void do_drop (dbref player, const char *name) { dbref loc; dbref thing; char buf[BUFFER_LEN]; int reward; 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!"); break; case AMBIGUOUS: notify (player, "I don't know which you mean!"); break; default: if (db[thing].location != player && !(Typeof (thing) == TYPE_EXIT) && db[thing].location == NOTHING) { /* Should not ever happen. */ notify (player, "You can't drop that."); } else if (Typeof (thing) == TYPE_EXIT) { /* special behavior for exits */ if (!controls (player, loc)) { notify (player, "You can't put an exit down here."); return; } /* else we can put it down */ moveto (thing, NOTHING); /* take it out of the pack */ PUSH (thing, db[loc].exits); notify (player, "Exit dropped."); } else if (db[loc].flags & TEMPLE) { /* sacrifice time */ send_home (thing); sprintf (buf, "%s is consumed in a burst of flame!", db[thing].name); notify (player, buf); #ifndef TINKER sprintf (buf, "%s sacrifices %s.", db[player].name, db[thing].name); #else /* TINKER */ sprintf (buf, "%s donates %s.", db[player].name, db[thing].name); #endif /* TINKER */ notify_except (db[loc].contents, player, buf); /* check for reward */ if (!controls (player, thing)) { reward = db[thing].pennies; if (reward < 1 || db[player].pennies > MAX_PENNIES) { reward = 1; } else if (reward > MAX_OBJECT_ENDOWMENT) { reward = MAX_OBJECT_ENDOWMENT; } db[player].pennies += reward; sprintf (buf, "You have received %d %s for your donation.", reward, reward == 1 ? "penny" : "pennies"); notify (player, buf); } } else if (db[thing].flags & STICKY) { send_home (thing); notify (player, "Dropped."); } else if (db[loc].location != NOTHING && !(db[loc].flags & STICKY)) { /* location has immediate dropto */ moveto (thing, db[loc].location); notify (player, "Dropped."); } else if ((db[thing].flags & DARK) && !can_link_to (player, Typeof (thing), loc)) { notify (player, "You cannot drop that DARK object here."); } else { moveto (thing, loc); notify (player, "Dropped."); sprintf (buf, "%s dropped %s.", db[player].name, db[thing].name); notify_except (db[loc].contents, player, buf); } break; } }