/* TinyMUD-like teleportation. We hope. Permissions, somewhat complex, are handled by building up some bit vectors of things that are true about the present situation, and then using them to verify that the teleport is legal. */ /* configure all options BEFORE including system stuff. */ #include "config.h" #include "mud.h" #include "vars.h" #include "look.h" #include "match.h" /* Some flags that can be set in bit vectors. For checking perms */ #define TEL_WHAT_PLAY 0001 #define TEL_WHAT_OBJ 0002 #define TEL_WHAT_OWNED 0004 #define TEL_WHAT_LINKOK 0010 #define TEL_WHAT_ME 0020 #define TEL_TO_OWNED 0001 #define TEL_TO_LINKOK 0002 #define TEL_TO_ROOM 0004 #define TEL_TO_PLAY 0010 #define TEL_TO_HOME 0020 #define TEL_TO_ME 0040 #define TEL_TO_HERE 0100 #define TEL_TO_ACTOR 0200 #define TEL_FRM_OWNED 0001 #define TEL_FRM_HERE 0002 #define TEL_FRM_ME 0004 #define TEL_FRM_CONT 0010 #define TEL_FRM_PLY 0020 #define TEL_FRM_ROOM 0040 #define TEL_FRM_USED 0100 static int wiz; static int whatflg; static int fromflg; static int toflg; /* ARGSUSED */ cmd_telep(ac,av,who,aswho) int ac; char *av[]; char *who; char *aswho; { char what[MAXOID]; char *here; char *from; char *to; char *listvar; char hm[MAXOID]; wiz = ut_flagged(aswho,var_wiz); here = ut_loc(run_actor()); whatflg = fromflg = toflg = 0; /* Figure out what it is we're supposed to move */ if(matchlocal(who,av[1],here,MTCH_MEOK|MTCH_UNIQ|MTCH_QUIET,what) && matchlocal(who,av[1],here,MTCH_FRST|MTCH_QUIET,what) && matchlocal(who,av[1],here,MTCH_NONLOC,what)) { say(aswho,"I can't see any ",av[1]," here\n",(char *)0); return(0); } /* And where it's supposed to go */ if(!strcmp("home",av[2])) { if(!ut_home(what,hm)) { say(aswho,"I can't figure out how to home ",av[1],".\n",(char *)0); return(0); } to = hm; toflg |= TEL_TO_HOME; } else if(!strcmp("here",av[2])) to = here; else if(!strcmp("me",av[2])) to = aswho; else if(!strcmp("actor",av[2])) to = run_actor(); else to = av[2]; /* Figure out where and what it is */ from = ut_loc(what); if(!strcmp(here,from)) fromflg |= TEL_FRM_HERE; if(!strcmp(aswho,from)) fromflg |= TEL_FRM_ME; /* Figure out what sort of thing this is */ if(!strcmp(what,aswho)) whatflg |= TEL_WHAT_ME; if(ut_listchk(from,listvar = var_ply,what)) { whatflg |= TEL_WHAT_PLAY; fromflg |= TEL_FRM_PLY; } else if(ut_listchk(from,listvar = var_cont,what)) { whatflg |= TEL_WHAT_OBJ; fromflg |= TEL_FRM_CONT; } else { char *used = ut_getatt(from,0,typ_obj,var_using,(char *)0); if(used != (char *)0 && !strcmp(what,used)) { whatflg |= TEL_WHAT_OBJ; fromflg |= TEL_FRM_USED; } else { say(aswho,av[1]," must be an exit or something.\n",(char *)0); return(0); } } /* Other misc stuff about the thing to 'port */ if(ut_isobjown(aswho,what)) whatflg |= TEL_WHAT_OWNED; if(!bool_locked(aswho,what,here,var_link,1)) whatflg |= TEL_WHAT_LINKOK; /* Now gather up remaining fact(s) about where this is coming from */ if(ut_isobjown(aswho,from)) fromflg |= TEL_FRM_OWNED; if(ut_flagged(from,var_isroom)) fromflg |= TEL_FRM_ROOM; /* Finally gather data on where it's supposed to go */ if(ut_isobjown(aswho,to)) toflg |= TEL_TO_OWNED; if(!bool_locked(aswho,to,here,var_link,1)) toflg |= TEL_TO_LINKOK; if(ut_flagged(to,var_isroom)) toflg |= TEL_TO_ROOM; if(ut_flagged(to,var_isplay)) toflg |= TEL_TO_PLAY; if(!strcmp(aswho,to)) toflg |= TEL_TO_ME; if(!strcmp(here,to)) toflg |= TEL_TO_HERE; if(!strcmp(run_actor(),to)) toflg |= TEL_TO_ACTOR; /* OK. Now we know everything, right? (heh. we have a headache. -mjr) */ if(!telep_ok(aswho,to,from,what)) { say(aswho,"You can't do that!\n",(char *)0); return(0); } /* Get it out of here */ if(fromflg & TEL_FRM_USED) { if(ut_unset(aswho,from,var_using)) { say(aswho,"Teleport failed.\n",(char *)0); return(0); } } else { if(ut_listdel(aswho,from,listvar,what)) { say(aswho,"Teleport failed.\n",(char *)0); return(0); } } /* Droptos DO matter */ if(whatflg & TEL_WHAT_OBJ) { char work[MAXOID]; /* Work buffer demanded by ut_dropto() */ to = ut_dropto(what,to,work); } /* And in to there */ if(ut_listadd(aswho,to,listvar,what)) { say(aswho,"Teleport failed.\n",(char *)0); return(0); } /* and change its location */ if(ut_set(aswho,what,typ_obj,var_loc,to)) { say(aswho,"Teleport failed.\n",(char *)0); return(0); } /* In certain cases, deal with inventories. Send contents home, */ /* leave used object alone. (On all non-wiz 'ports of players. */ if(!wiz && (whatflg & TEL_WHAT_PLAY)) { char *list; char next[MAXOID]; char ohom[MAXOID]; list = ut_getatt(what,0,typ_list,var_cont,(char *)0); if(list != (char *)0) { while((list = lstnext(list,next)) != (char *)0) { if(!ut_home(next,ohom)) continue; /* Ignore return values. There's *nothing* we can do */ (void)ut_listdel(aswho,what,var_cont,next); (void)ut_listadd(aswho,ohom,var_cont,next); (void)ut_set(aswho,next,typ_obj,var_loc,ohom); } } list = ut_getatt(what,0,typ_obj,var_using,(char *)0); if(list != (char *)0 && ut_home(list,ohom) && strcmp(ohom,what)) { (void)ut_listadd(aswho,ohom,var_cont,list); (void)ut_set(aswho,list,typ_obj,var_loc,ohom); (void)ut_unset(aswho,what,var_using); } } /* And now tell everyone what they need to hear */ if((whatflg & TEL_WHAT_PLAY) && (!ut_flagged(what,var_isdark))){ ut_roombcast(from,what,ut_name(what)," has left.\n",(char *)0); ut_roombcast(to,what,ut_name(what)," has arrived.\n",(char *)0); say(what,"You feel a wrenching sensation....\n",(char *)0); lookat(what,to,LOOK_NAME|LOOK_PLAY|LOOK_CONT); } say(aswho,"Teleported.\n",(char *)0); return(0); } /* It is here that we code up the teleport rules */ telep_ok(who,to,from,what) char *who; char *to; char *from; char *what; { /* Wizards can send stuff anywhere thats reasonable */ if(wiz) { return(((whatflg & TEL_WHAT_PLAY) && (toflg & TEL_TO_ROOM)) || ((whatflg & TEL_WHAT_OBJ) && (toflg & (TEL_TO_ROOM|TEL_TO_PLAY)))); } /* Only another wiz can do this and we eliminated that possibility */ if(ut_flagged(what,var_wiz)) return(0); /* Find out about who is doing this, and check the rules */ if(ut_flagged(who,var_isplay)) { if(whatflg & TEL_WHAT_PLAY) { if(whatflg & (TEL_WHAT_ME|TEL_WHAT_OWNED|TEL_WHAT_LINKOK)) { return(((toflg & TEL_TO_ROOM) && (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) || (toflg & TEL_TO_HOME)); } return((fromflg & TEL_FRM_HERE) && (fromflg & TEL_FRM_OWNED) && (toflg & TEL_TO_HOME)); } if(whatflg & TEL_WHAT_OBJ) { if(whatflg & (TEL_WHAT_OWNED|TEL_WHAT_LINKOK)) { return((toflg & (TEL_TO_ME|TEL_TO_ACTOR)) || ((toflg & (TEL_TO_ROOM|TEL_TO_PLAY)) && (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) || (toflg & TEL_TO_HOME)); } if(((fromflg & TEL_FRM_ROOM) && (fromflg & TEL_FRM_OWNED)) || (fromflg & TEL_FRM_ME)) return(toflg & TEL_TO_HOME); } return(0); } if(ut_flagged(who,var_isroom)) { if((whatflg & TEL_WHAT_OBJ) && (whatflg & (TEL_WHAT_OWNED|TEL_WHAT_LINKOK))) { return((toflg & (TEL_TO_ME|TEL_TO_ACTOR)) || ((toflg & (TEL_TO_ROOM|TEL_TO_PLAY)) && (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) || (toflg & TEL_TO_HOME)); } if((whatflg & TEL_WHAT_PLAY) && (fromflg & TEL_FRM_ME)){ return((toflg & TEL_TO_HOME) || ((whatflg & (TEL_WHAT_OWNED|TEL_WHAT_LINKOK))&& (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) ); } return(0); } /* Must be an exit or a thing */ if(lstlook(ut_getatt(who,0,typ_list,var_loc,var_xit,(char *)0),who)) { if((whatflg & TEL_WHAT_OBJ) && (whatflg & (TEL_WHAT_OWNED|TEL_WHAT_LINKOK))) { return(((toflg & (TEL_TO_ROOM|TEL_TO_PLAY)) && (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) || (toflg & TEL_TO_HOME)); } return(0); } /* Must be a thing. We hope so, anyway. */ if((whatflg & TEL_WHAT_PLAY) && !strcmp(run_actor(),what)) { return(((toflg & TEL_TO_ROOM) && (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) || (toflg & TEL_TO_HOME)); } if((whatflg & TEL_WHAT_OBJ) && (whatflg & (TEL_WHAT_ME|TEL_WHAT_OWNED|TEL_WHAT_LINKOK))) { return((toflg & TEL_TO_ACTOR) || ((toflg & (TEL_TO_ROOM|TEL_TO_PLAY)) && (toflg & (TEL_TO_OWNED|TEL_TO_LINKOK))) || (toflg & TEL_TO_HOME)); } return(0); }