mux/src/move.cpp

Go to the documentation of this file.
00001 // move.cpp -- Routines for moving about.
00002 //
00003 // $Id: move.cpp,v 1.8 2007/04/14 04:57:05 sdennis Exp $
00004 //
00005 
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010 
00011 #include "attrs.h"
00012 #include "command.h"
00013 #include "interface.h"
00014 #include "powers.h"
00015 #ifdef REALITY_LVLS
00016 #include "levels.h"
00017 #endif /* REALITY_LVLS */
00018 
00019 /* ---------------------------------------------------------------------------
00020  * process_leave_loc: Generate messages and actions resulting from leaving a
00021  * place.
00022  */
00023 
00024 static void process_leave_loc(dbref thing, dbref dest, dbref cause, bool canhear, int hush)
00025 {
00026     dbref loc = Location(thing);
00027     if ((loc == NOTHING) || (loc == dest))
00028     {
00029         return;
00030     }
00031 
00032     if (dest == HOME)
00033     {
00034         dest = Home(thing);
00035     }
00036 
00037     if (Html(thing))
00038     {
00039         notify_html(thing, "<xch_page clear=links>");
00040     }
00041 
00042     // Run the LEAVE attributes in the current room if we meet any of
00043     // following criteria:
00044     //
00045     //   - The current room has wizard privs.
00046     //   - Neither the current room nor the moving object are dark.
00047     //   - The moving object can hear and does not hav wizard privs.
00048     //
00049     // EXCEPT if we were called with the HUSH_LEAVE key.
00050     //
00051 
00052 #ifdef REALITY_LVLS
00053     bool quiet = (  (hush & HUSH_LEAVE) || !IsReal(loc, thing)
00054 #else
00055     bool quiet = (  (hush & HUSH_LEAVE)
00056 #endif /* REALITY_LVLS */
00057                  || (  !Wizard(loc)
00058                     && (  Dark(thing)
00059                        || Dark(loc))
00060                     && (  !canhear
00061                        || (  Wizard(thing)
00062                           && Dark(thing)))));
00063 
00064     int oattr = quiet ? 0 : A_OLEAVE;
00065     int aattr = quiet ? 0 : A_ALEAVE;
00066     int pattr = (!mudconf.terse_movemsg && Terse(thing)) ? 0 : A_LEAVE;
00067     did_it(thing, loc, pattr, NULL, oattr, NULL, aattr,
00068            (char **)NULL, 0);
00069 
00070     // Do OXENTER for receiving room
00071     //
00072     if ((dest != NOTHING) && !quiet)
00073     {
00074         did_it(thing, dest, 0, NULL, A_OXENTER, NULL, 0, (char **)NULL, 0);
00075     }
00076 
00077     // Display the 'has left' message if we meet any of the following
00078     // criteria:
00079     //
00080     //   - Neither the current room nor the moving object are dark.
00081     //   - The object can hear and is not a dark wizard.
00082     //
00083     if (  !quiet
00084        && !Blind(thing)
00085        && !Blind(loc))
00086     {
00087         if (  (  !Dark(thing)
00088               && !Dark(loc))
00089            || (  canhear
00090               && !(Wizard(thing) && Dark(thing))))
00091         {
00092 #ifdef REALITY_LVLS
00093             notify_except2_rlevel(loc, thing, thing, cause,
00094 #else
00095             notify_except2(loc, thing, thing, cause,
00096 #endif /* REALITY_LVLS */
00097                        tprintf("%s has left.", Name(thing)));
00098         }
00099     }
00100 }
00101 
00102 /*---------------------------------------------------------------------------
00103  * process_enter_loc: Generate messages and actions resulting from entering
00104  * a place.
00105  */
00106 
00107 static void process_enter_loc(dbref thing, dbref src, dbref cause, bool canhear, int hush)
00108 {
00109     dbref loc = Location(thing);
00110     if (  loc == NOTHING
00111        || loc == src)
00112     {
00113         return;
00114     }
00115 
00116     show_vrml_url(thing, loc);
00117 
00118     // Run the ENTER attributes in the current room if we meet any of following
00119     // criteria:
00120     //
00121     //  - The current room has wizard privs.
00122     //  - Neither the current room nor the moving object are dark.
00123     //  - The moving object can hear and does not have wizard privs.
00124     //
00125     // EXCEPT if we were called with the HUSH_ENTER key.
00126     //
00127 #ifdef REALITY_LVLS
00128     bool quiet = (  (hush & HUSH_ENTER) || !IsReal(loc, thing)
00129 #else
00130     bool quiet = (  (hush & HUSH_ENTER)
00131 #endif /* REALITY_LVLS */
00132                  || (  !Wizard(loc)
00133                     && (  Dark(thing)
00134                        || Dark(loc))
00135                     && (  !canhear
00136                        || (  Wizard(thing)
00137                           && Dark(thing)))));
00138 
00139     int oattr = quiet ? 0 : A_OENTER;
00140     int aattr = quiet ? 0 : A_AENTER;
00141     int pattr = (!mudconf.terse_movemsg && Terse(thing)) ? 0 : A_ENTER;
00142 
00143     did_it(thing, loc, pattr, NULL, oattr, NULL, aattr,
00144            (char **)NULL, 0);
00145 
00146     // Do OXLEAVE for sending room.
00147     //
00148     if (  src != NOTHING
00149        && !quiet)
00150     {
00151         did_it(thing, src, 0, NULL, A_OXLEAVE, NULL, 0, (char **)NULL, 0);
00152     }
00153 
00154     // Display the 'has arrived' message if we meet all of the following
00155     // criteria:
00156     //
00157     //  - The moving object can hear.
00158     //  - The object is not a dark wizard.
00159     //
00160     if (  !quiet
00161        && canhear
00162        && !Blind(thing)
00163        && !Blind(loc)
00164        && !(Dark(thing) && Wizard(thing)))
00165     {
00166 #ifdef REALITY_LVLS
00167         notify_except2_rlevel(loc, thing, thing, cause,
00168 #else
00169         notify_except2(loc, thing, thing, cause,
00170 #endif /* REALITY_LVLS */
00171                    tprintf("%s has arrived.", Name(thing)));
00172     }
00173 }
00174 
00175 /* ---------------------------------------------------------------------------
00176  * move_object: Physically move an object from one place to another.
00177  * Does not generate any messages or actions.
00178  */
00179 
00180 void move_object(dbref thing, dbref dest)
00181 {
00182     dbref src = Location(thing);
00183 
00184     // Remove from the source location
00185     //
00186     if (src != NOTHING)
00187     {
00188         s_Contents(src, remove_first(Contents(src), thing));
00189     }
00190 
00191     // Special check for HOME
00192     //
00193     if (dest == HOME)
00194     {
00195         dest = Home(thing);
00196     }
00197 
00198     // Add to destination location
00199     //
00200     if (dest != NOTHING)
00201     {
00202         s_Contents(dest, insert_first(Contents(dest), thing));
00203     }
00204     else
00205     {
00206         s_Next(thing, NOTHING);
00207     }
00208     s_Location(thing, dest);
00209 
00210     // Look around and do the penny check
00211     //
00212     look_in(thing, dest, (LK_SHOWEXIT | LK_OBEYTERSE));
00213     if (  isPlayer(thing)
00214        && mudconf.payfind > 0
00215        && Pennies(thing) < mudconf.paylimit
00216        && !Controls(thing, dest)
00217        && RandomINT32(0, mudconf.payfind-1) == 0)
00218     {
00219         giveto(thing, 1);
00220         notify(thing, tprintf("You found a %s!", mudconf.one_coin));
00221     }
00222 }
00223 
00224 // move_the_exit: Move an exit silently from its location to its destination
00225 //
00226 static void move_the_exit(dbref thing, dbref dest)
00227 {
00228     dbref exitloc = Exits(thing);
00229     s_Exits(exitloc, remove_first(Exits(exitloc), thing));
00230     s_Exits(dest, insert_first(Exits(dest), thing));
00231     s_Exits(thing, dest);
00232 }
00233 
00234 /* ---------------------------------------------------------------------------
00235  * send_dropto, process_sticky_dropto, process_dropped_dropto,
00236  * process_sacrifice_dropto: Check for and process droptos.
00237  */
00238 
00239 // send_dropto: Send an object through the dropto of a room
00240 //
00241 static void send_dropto(dbref thing, dbref player)
00242 {
00243     if (!Sticky(thing))
00244     {
00245         move_via_generic(thing, Dropto(Location(thing)), player, 0);
00246     }
00247     else
00248     {
00249         move_via_generic(thing, HOME, player, 0);
00250     }
00251     divest_object(thing);
00252 }
00253 
00254 // process_sticky_dropto: Call when an object leaves the room to see if
00255 // we should empty the room
00256 //
00257 static void process_sticky_dropto(dbref loc, dbref player)
00258 {
00259     dbref dropto, thing, next;
00260 
00261     // Do nothing if checking anything but a sticky room
00262     //
00263     if (!Good_obj(loc) || !Has_dropto(loc) || !Sticky(loc))
00264         return;
00265 
00266     // Make sure dropto loc is valid
00267     //
00268     dropto = Dropto(loc);
00269     if ((dropto == NOTHING) || (dropto == loc))
00270         return;
00271 
00272     // Make sure no players hanging out
00273     //
00274     DOLIST(thing, Contents(loc))
00275     {
00276         if ((Connected(Owner(thing)) && Hearer(thing)))
00277             return;
00278     }
00279 
00280     // Send everything through the dropto
00281     //
00282     s_Contents(loc, reverse_list(Contents(loc)));
00283     SAFE_DOLIST(thing, next, Contents(loc))
00284     {
00285         send_dropto(thing, player);
00286     }
00287 }
00288 
00289 // process_dropped_dropto: Check what to do when someone drops an object.
00290 //
00291 static void process_dropped_dropto(dbref thing, dbref player)
00292 {
00293     // If STICKY, send home
00294     //
00295     if (Sticky(thing))
00296     {
00297         move_via_generic(thing, HOME, player, 0);
00298         divest_object(thing);
00299         return;
00300     }
00301 
00302     // Process the dropto if location is a room and is not STICKY
00303     //
00304     dbref loc = Location(thing);
00305     if (Has_dropto(loc) && (Dropto(loc) != NOTHING) && !Sticky(loc))
00306         send_dropto(thing, player);
00307 }
00308 
00309 /* ---------------------------------------------------------------------------
00310  * move_via_generic: Generic move routine, generates standard messages and
00311  * actions.
00312  */
00313 
00314 void move_via_generic(dbref thing, dbref dest, dbref cause, int hush)
00315 {
00316     if (dest == HOME)
00317     {
00318         dest = Home(thing);
00319     }
00320 
00321     dbref src = Location(thing);
00322     bool canhear = Hearer(thing);
00323     process_leave_loc(thing, dest, cause, canhear, hush);
00324     move_object(thing, dest);
00325     did_it(thing, thing, A_MOVE, NULL, A_OMOVE, NULL, A_AMOVE,
00326            (char **)NULL, 0);
00327     process_enter_loc(thing, src, cause, canhear, hush);
00328 }
00329 
00330 /* ---------------------------------------------------------------------------
00331  * move_via_exit: Exit move routine, generic + exit messages + dropto check.
00332  */
00333 
00334 static void move_via_exit(dbref thing, dbref dest, dbref cause, dbref exit, int hush)
00335 {
00336     if (dest == HOME)
00337     {
00338         dest = Home(thing);
00339     }
00340     dbref src = Location(thing);
00341     bool canhear = Hearer(thing);
00342     bool quiet = (  (Wizard(thing) && Dark(thing)) // Dark wizards don't trigger OSUCC/ASUCC
00343                  || (hush & HUSH_EXIT));
00344 
00345     int oattr = quiet ? 0 : A_OSUCC;
00346     int aattr = quiet ? 0 : A_ASUCC;
00347     int pattr = (!mudconf.terse_movemsg && Terse(thing)) ? 0 : A_SUCC;
00348     did_it(thing, exit, pattr, NULL, oattr, NULL, aattr,
00349            (char **)NULL, 0);
00350     process_leave_loc(thing, dest, cause, canhear, hush);
00351     move_object(thing, dest);
00352 
00353     // Dark wizards don't trigger ODROP/ADROP
00354     //
00355     oattr = quiet ? 0 : A_ODROP;
00356     aattr = quiet ? 0 : A_ADROP;
00357     pattr = (!mudconf.terse_movemsg && Terse(thing)) ? 0 : A_DROP;
00358     did_it(thing, exit, pattr, NULL, oattr, NULL, aattr,
00359            (char **)NULL, 0);
00360 
00361     did_it(thing, thing, A_MOVE, NULL, A_OMOVE, NULL, A_AMOVE,
00362            (char **)NULL, 0);
00363     process_enter_loc(thing, src, cause, canhear, hush);
00364     process_sticky_dropto(src, thing);
00365 }
00366 
00367 /* ---------------------------------------------------------------------------
00368  * move_via_teleport: Teleport move routine, generic + teleport messages +
00369  * divestiture + dropto check.
00370  */
00371 
00372 bool move_via_teleport(dbref thing, dbref dest, dbref cause, int hush)
00373 {
00374     dbref curr;
00375     int count;
00376     char *failmsg;
00377 
00378     dbref src = Location(thing);
00379     if ((dest != HOME) && Good_obj(src))
00380     {
00381         curr = src;
00382         for (count = mudconf.ntfy_nest_lim; count > 0; count--)
00383         {
00384             if (!could_doit(thing, curr, A_LTELOUT))
00385             {
00386                 if ((thing == cause) || (cause == NOTHING))
00387                 {
00388                     failmsg = "You can't teleport out!";
00389                 }
00390                 else
00391                 {
00392                     failmsg = "You can't be teleported out!";
00393                     notify_quiet(cause, "You can't teleport that out!");
00394                 }
00395                 did_it(thing, src,
00396                        A_TOFAIL, failmsg, A_OTOFAIL, NULL,
00397                        A_ATOFAIL, (char **)NULL, 0);
00398                 return false;
00399             }
00400             if (isRoom(curr))
00401             {
00402                 break;
00403             }
00404             curr = Location(curr);
00405         }
00406     }
00407 
00408     if (isExit(thing))
00409     {
00410         move_the_exit(thing, dest);
00411         return true;
00412     }
00413     if (dest == HOME)
00414     {
00415         dest = Home(thing);
00416     }
00417     bool canhear = Hearer(thing);
00418     if (!(hush & HUSH_LEAVE))
00419     {
00420         did_it(thing, thing, 0, NULL, A_OXTPORT, NULL, 0,
00421             (char **)NULL, 0);
00422     }
00423     process_leave_loc(thing, dest, NOTHING, canhear, hush);
00424 
00425     move_object(thing, dest);
00426 
00427     if (!(hush & HUSH_ENTER))
00428     {
00429         did_it(thing, thing, A_TPORT, NULL, A_OTPORT, NULL, A_ATPORT,
00430             (char **)NULL, 0);
00431     }
00432     did_it(thing, thing, A_MOVE, NULL, A_OMOVE, NULL, A_AMOVE,
00433         (char **)NULL, 0);
00434     process_enter_loc(thing, src, NOTHING, canhear, hush);
00435     divest_object(thing);
00436     process_sticky_dropto(src, thing);
00437     return true;
00438 }
00439 
00440 /* ---------------------------------------------------------------------------
00441  * move_exit: Try to move a player through an exit.
00442  */
00443 
00444 static dbref get_exit_dest(dbref executor, dbref exit)
00445 {
00446     dbref aowner;
00447     int   aflags;
00448     char *atr_gotten = atr_pget(exit, A_EXITVARDEST, &aowner, &aflags);
00449 
00450     char *result = alloc_lbuf("get_exit_dest");
00451     char *ref = result;
00452     char *str = atr_gotten;
00453     mux_exec(result, &ref, exit, executor, executor, EV_TOP | EV_FCHECK | EV_EVAL,
00454                 &str, (char **)NULL, 0);
00455     free_lbuf(atr_gotten);
00456     *ref = '\0';
00457 
00458     dbref dest = NOTHING;
00459     if (*result == NUMBER_TOKEN)
00460     {
00461         dest = mux_atol(result + 1);
00462     }
00463 
00464     free_lbuf(result);
00465     return dest;
00466 }
00467 
00468 void move_exit(dbref player, dbref exit, bool divest, const char *failmsg, int hush)
00469 {
00470     int oattr, aattr;
00471     bool bDoit = false;
00472 
00473     dbref loc = Location(exit);
00474     if (atr_get_raw(exit, A_EXITVARDEST) != NULL)
00475     {
00476         loc = get_exit_dest(player, exit);
00477     }
00478 
00479     if (loc == HOME)
00480     {
00481         loc = Home(player);
00482     }
00483 
00484 #ifdef WOD_REALMS
00485     if (Good_obj(loc) && (REALM_DO_HIDDEN_FROM_YOU != DoThingToThingVisibility(player, exit, ACTION_IS_MOVING)))
00486     {
00487         if (isShroud(player))
00488         {
00489             bDoit = true;
00490             int iShroudWarded = get_atr("SHROUD_WARDED");
00491             if (iShroudWarded > 0)
00492             {
00493                 int owner, flags;
00494                 char *buff = atr_pget(exit, iShroudWarded, &owner, &flags);
00495                 if (buff)
00496                 {
00497                     if (*buff)
00498                     {
00499                         bDoit = false;
00500                     }
00501                     free_lbuf(buff);
00502                 }
00503             }
00504         }
00505 
00506         if (!bDoit && isUmbra(player))
00507         {
00508             bDoit = true;
00509             int iUmbraWarded = get_atr("UMBRA_WARDED");
00510             if (iUmbraWarded > 0)
00511             {
00512                 int owner, flags;
00513                 char *buff = atr_pget(exit, iUmbraWarded, &owner, &flags);
00514                 if (buff)
00515                 {
00516                     if (*buff)
00517                     {
00518                         bDoit = false;
00519                     }
00520                     free_lbuf(buff);
00521                 }
00522             }
00523         }
00524 
00525         if (!bDoit && could_doit(player, exit, A_LOCK))
00526         {
00527             bDoit = true;
00528         }
00529     }
00530 #else
00531     if (Good_obj(loc) && could_doit(player, exit, A_LOCK))
00532     {
00533         bDoit = true;
00534     }
00535 #endif
00536     if (bDoit)
00537     {
00538         switch (Typeof(loc))
00539         {
00540         case TYPE_ROOM:
00541             move_via_exit(player, loc, NOTHING, exit, hush);
00542             if (divest)
00543                 divest_object(player);
00544             break;
00545         case TYPE_PLAYER:
00546         case TYPE_THING:
00547             if (Going(loc))
00548             {
00549                 notify(player, "You can't go that way.");
00550                 return;
00551             }
00552             move_via_exit(player, loc, NOTHING, exit, hush);
00553             divest_object(player);
00554             break;
00555         case TYPE_EXIT:
00556             notify(player, "You can't go that way.");
00557             return;
00558         }
00559     }
00560     else
00561     {
00562         if ((Wizard(player) && Dark(player)) || (hush & HUSH_EXIT))
00563         {
00564             oattr = 0;
00565             aattr = 0;
00566         }
00567         else
00568         {
00569             oattr = A_OFAIL;
00570             aattr = A_AFAIL;
00571         }
00572         did_it(player, exit, A_FAIL, failmsg, oattr, NULL, aattr, (char **)NULL, 0);
00573     }
00574 }
00575 
00576 /* ---------------------------------------------------------------------------
00577  * do_move: Move from one place to another via exits or 'home'.
00578  */
00579 
00580 void do_move(dbref executor, dbref caller, dbref enactor, int key, char *direction)
00581 {
00582     UNUSED_PARAMETER(caller);
00583     UNUSED_PARAMETER(enactor);
00584 
00585     dbref exit, loc;
00586     int i, quiet;
00587 
00588     if (!string_compare(direction, "home"))
00589     {
00590         // Go home w/o stuff.
00591         //
00592         if (  (  Fixed(executor)
00593               || Fixed(Owner(executor)))
00594            && !(WizRoy(executor)))
00595         {
00596             notify(executor, mudconf.fixed_home_msg);
00597             return;
00598         }
00599 
00600         if (  (loc = Location(executor)) != NOTHING
00601            && !Dark(executor)
00602            && !Dark(loc))
00603         {
00604             // Tell all
00605             //
00606             notify_except(loc, executor, executor, tprintf("%s goes home.", Name(executor)), 0);
00607         }
00608         // Give the player the messages
00609         //
00610         for (i = 0; i < 3; i++)
00611             notify(executor, "There's no place like home...");
00612         move_via_generic(executor, HOME, NOTHING, 0);
00613         divest_object(executor);
00614         process_sticky_dropto(loc, executor);
00615         return;
00616     }
00617     // Find the exit.
00618     //
00619     init_match_check_keys(executor, direction, TYPE_EXIT);
00620     match_exit();
00621     exit = match_result();
00622     switch (exit)
00623     {
00624     case NOTHING:       // Try to force the object
00625         notify(executor, "You can't go that way.");
00626         break;
00627     case AMBIGUOUS:
00628         notify(executor, "I don't know which way you mean!");
00629         break;
00630     default:
00631         quiet = 0;
00632         if ((key & MOVE_QUIET) && Controls(executor, exit))
00633             quiet = HUSH_EXIT;
00634         move_exit(executor, exit, false, "You can't go that way.", quiet);
00635     }
00636 }
00637 
00638 /* ---------------------------------------------------------------------------
00639  * do_get: Get an object.
00640  */
00641 
00642 void do_get(dbref executor, dbref caller, dbref enactor, int key, char *what)
00643 {
00644     UNUSED_PARAMETER(caller);
00645     UNUSED_PARAMETER(enactor);
00646 
00647     dbref playerloc;
00648     if (  !Has_location(executor)
00649        || !Good_obj(playerloc = Location(executor)))
00650     {
00651         return;
00652     }
00653 
00654     // You can only pick up things in rooms and ENTER_OK objects/players.
00655     //
00656     if (  !isRoom(playerloc)
00657        && !Enter_ok(playerloc)
00658        && !Controls(executor, playerloc))
00659     {
00660         notify(executor, NOPERM_MESSAGE);
00661         return;
00662     }
00663 
00664     // Look for the thing locally.
00665     //
00666     init_match_check_keys(executor, what, TYPE_THING);
00667     match_neighbor();
00668     match_exit();
00669     if (Long_Fingers(executor))
00670     {
00671         match_absolute();
00672     }
00673     dbref thing = match_result();
00674 
00675     // Look for the thing in other people's inventories.
00676     //
00677     if (!Good_obj(thing))
00678     {
00679         thing = match_status(executor, match_possessed(executor, executor, what,
00680             thing, true));
00681 
00682         if (!Good_obj(thing))
00683         {
00684             return;
00685         }
00686     }
00687 
00688     // If we found it, check to see if we can get it.
00689     //
00690     dbref thingloc = Location(thing);
00691     if (Good_obj(thingloc))
00692     {
00693         if (!could_doit(executor, thingloc, A_LGET))
00694         {
00695             notify(executor, NOPERM_MESSAGE);
00696             return;
00697         }
00698     }
00699 
00700     // If we can get it, get it.
00701     //
00702     const char *failmsg;
00703     int oattr, aattr;
00704     bool quiet = false;
00705     switch (Typeof(thing))
00706     {
00707     case TYPE_PLAYER:
00708     case TYPE_THING:
00709 
00710         // You can't take what you already have.
00711         //
00712         if (thingloc == executor)
00713         {
00714             notify(executor, "You already have that!");
00715             break;
00716         }
00717         if (  (key & GET_QUIET)
00718            && Controls(executor, thing))
00719         {
00720             quiet = true;
00721         }
00722 
00723         if (thing == executor)
00724         {
00725             notify(executor, "You cannot get yourself!");
00726         }
00727         else if (could_doit(executor, thing, A_LOCK))
00728         {
00729             if (thingloc != playerloc)
00730             {
00731                 notify(thingloc, tprintf("%s was taken from you.",
00732                     Name(thing)));
00733             }
00734             move_via_generic(thing, executor, executor, 0);
00735             notify(thing, "Taken.");
00736             oattr = quiet ? 0 : A_OSUCC;
00737             aattr = quiet ? 0 : A_ASUCC;
00738             did_it(executor, thing, A_SUCC, "Taken.", oattr, NULL,
00739                    aattr, (char **)NULL, 0);
00740         }
00741         else
00742         {
00743             oattr = quiet ? 0 : A_OFAIL;
00744             aattr = quiet ? 0 : A_AFAIL;
00745             if (thingloc != playerloc)
00746             {
00747                 failmsg = "You can't take that from there.";
00748             }
00749             else
00750             {
00751                 failmsg = "You can't pick that up.";
00752             }
00753             did_it(executor, thing, A_FAIL, failmsg, oattr, NULL, aattr,
00754                 (char **)NULL, 0);
00755         }
00756         break;
00757 
00758     case TYPE_EXIT:
00759 
00760         // You can't take what you already have.
00761         //
00762         thingloc = Exits(thing);
00763         if (thingloc == executor)
00764         {
00765             notify(executor, "You already have that!");
00766             break;
00767         }
00768 
00769         // You must control either the exit or the location.
00770         //
00771         if (  !Controls(executor, thing)
00772            && !Controls(executor, playerloc))
00773         {
00774             notify(executor, NOPERM_MESSAGE);
00775             break;
00776         }
00777 
00778         // Do it.
00779         //
00780         s_Exits(thingloc, remove_first(Exits(thingloc), thing));
00781         s_Exits(executor, insert_first(Exits(executor), thing));
00782         s_Exits(thing, executor);
00783         if (!Quiet(executor))
00784         {
00785             notify(executor, "Exit taken.");
00786         }
00787         break;
00788 
00789     default:
00790 
00791         notify(executor, "You can't take that!");
00792         break;
00793     }
00794 }
00795 
00796 /* ---------------------------------------------------------------------------
00797  * do_drop: Drop an object.
00798  */
00799 
00800 void do_drop(dbref executor, dbref caller, dbref enactor, int key, char *name)
00801 {
00802     UNUSED_PARAMETER(caller);
00803     UNUSED_PARAMETER(enactor);
00804 
00805     dbref loc = Location(executor);
00806     if (!Good_obj(loc))
00807         return;
00808 
00809     dbref exitloc, thing;
00810     char *buf, *bp;
00811     int oattr, aattr;
00812     bool quiet;
00813 
00814     init_match(executor, name, TYPE_THING);
00815     match_possession();
00816     match_carried_exit();
00817 
00818     switch (thing = match_result())
00819     {
00820     case NOTHING:
00821         notify(executor, "You don't have that!");
00822         return;
00823     case AMBIGUOUS:
00824         notify(executor, "I don't know which you mean!");
00825         return;
00826     }
00827 
00828     switch (Typeof(thing))
00829     {
00830     case TYPE_THING:
00831     case TYPE_PLAYER:
00832 
00833         // You have to be carrying it.
00834         //
00835         if (  (  Location(thing) != executor
00836               && !Wizard(executor))
00837            || !could_doit(executor, thing, A_LDROP))
00838         {
00839             did_it(executor, thing, A_DFAIL, "You can't drop that.",
00840                    A_ODFAIL, NULL, A_ADFAIL, (char **)NULL, 0);
00841             return;
00842         }
00843 
00844         // Move it
00845         //
00846         move_via_generic(thing, Location(executor), executor, 0);
00847         notify(thing, "Dropped.");
00848         quiet = false;
00849         if ((key & DROP_QUIET) && Controls(executor, thing))
00850             quiet = true;
00851         bp = buf = alloc_lbuf("do_drop.did_it");
00852         safe_tprintf_str(buf, &bp, "dropped %s.", Name(thing));
00853         oattr = quiet ? 0 : A_ODROP;
00854         aattr = quiet ? 0 : A_ADROP;
00855         did_it(executor, thing, A_DROP, "Dropped.", oattr, buf,
00856                aattr, (char **)NULL, 0);
00857         free_lbuf(buf);
00858 
00859         // Process droptos
00860         //
00861         process_dropped_dropto(thing, executor);
00862 
00863         break;
00864     case TYPE_EXIT:
00865 
00866         // You have to be carrying it.
00867         //
00868         if ((Exits(thing) != executor) && !Wizard(executor))
00869         {
00870             notify(executor, "You can't drop that.");
00871             return;
00872         }
00873         if (!Controls(executor, loc))
00874         {
00875             notify(executor, NOPERM_MESSAGE);
00876             return;
00877         }
00878 
00879         // Do it
00880         //
00881         exitloc = Exits(thing);
00882         s_Exits(exitloc, remove_first(Exits(exitloc), thing));
00883         s_Exits(loc, insert_first(Exits(loc), thing));
00884         s_Exits(thing, loc);
00885 
00886         if (!Quiet(executor))
00887             notify(executor, "Exit dropped.");
00888         break;
00889     default:
00890         notify(executor, "You can't drop that.");
00891     }
00892 }
00893 
00894 /* ---------------------------------------------------------------------------
00895  * do_enter, do_leave: The enter and leave commands.
00896  */
00897 
00898 void do_enter_internal(dbref player, dbref thing, bool quiet)
00899 {
00900     int oattr, aattr;
00901 
00902     if (!Enter_ok(thing) && !Controls(player, thing))
00903     {
00904         oattr = quiet ? 0 : A_OEFAIL;
00905         aattr = quiet ? 0 : A_AEFAIL;
00906         did_it(player, thing, A_EFAIL, NOPERM_MESSAGE,
00907                oattr, NULL, aattr, (char **)NULL, 0);
00908     }
00909     else if (player == thing)
00910     {
00911         notify(player, "You can't enter yourself!");
00912     }
00913     else if (could_doit(player, thing, A_LENTER))
00914     {
00915         dbref loc = Location(player);
00916         oattr = quiet ? HUSH_ENTER : 0;
00917         move_via_generic(player, thing, NOTHING, oattr);
00918         divest_object(player);
00919         process_sticky_dropto(loc, player);
00920     }
00921     else
00922     {
00923         oattr = quiet ? 0 : A_OEFAIL;
00924         aattr = quiet ? 0 : A_AEFAIL;
00925         did_it(player, thing, A_EFAIL, "You can't enter that.",
00926                oattr, NULL, aattr, (char **)NULL, 0);
00927     }
00928 }
00929 
00930 void do_enter(dbref executor, dbref caller, dbref enactor, int key, char *what)
00931 {
00932     UNUSED_PARAMETER(caller);
00933     UNUSED_PARAMETER(enactor);
00934 
00935     init_match(executor, what, TYPE_THING);
00936     match_neighbor();
00937     if (Long_Fingers(executor))
00938         match_absolute();   // the wizard has long fingers
00939 
00940     dbref thing = noisy_match_result();
00941     bool bQuiet = false;
00942 
00943     if (thing == NOTHING)
00944         return;
00945 
00946     switch (Typeof(thing))
00947     {
00948     case TYPE_PLAYER:
00949     case TYPE_THING:
00950         if ((key & MOVE_QUIET) && Controls(executor, thing))
00951             bQuiet = true;
00952         do_enter_internal(executor, thing, bQuiet);
00953         break;
00954     default:
00955         notify(executor, NOPERM_MESSAGE);
00956     }
00957     return;
00958 }
00959 
00960 void do_leave(dbref executor, dbref caller, dbref enactor, int key)
00961 {
00962     UNUSED_PARAMETER(caller);
00963     UNUSED_PARAMETER(enactor);
00964 
00965     dbref loc = Location(executor);
00966     dbref newLoc = loc;
00967 
00968     if (  !Good_obj(loc)
00969        || Going(loc)
00970        || !Has_location(loc)
00971        || !Good_obj(newLoc = Location(loc))
00972        || Going(newLoc))
00973     {
00974         notify(executor, "You can't leave.");
00975         return;
00976     }
00977     int quiet = 0;
00978     if (  (key & MOVE_QUIET)
00979        && Controls(executor, loc))
00980     {
00981         quiet = HUSH_LEAVE;
00982     }
00983     if (could_doit(executor, loc, A_LLEAVE))
00984     {
00985         move_via_generic(executor, newLoc, NOTHING, quiet);
00986     }
00987     else
00988     {
00989         int oattr = quiet ? 0 : A_OLFAIL;
00990         int aattr = quiet ? 0 : A_ALFAIL;
00991         did_it(executor, loc, A_LFAIL, "You can't leave.",
00992                oattr, NULL, aattr, (char **)NULL, 0);
00993     }
00994 }

Generated on Mon May 28 04:40:10 2007 for MUX by  doxygen 1.4.7