/* move.c */ /* $Id: move.c,v 1.10 1993/09/18 19:04:11 nils Exp $ */ #include "copyright.h" #include "db.h" #include "config.h" #include "interface.h" #include "match.h" #include "externs.h" void moveto(what,where) dbref what; dbref where; { enter_room(what,where); } void moveit(what,where) dbref what; dbref where; { dbref loc,old; if(Typeof(what) == TYPE_EXIT && Typeof(where)==TYPE_PLAYER) { log_error("moving exit to player"); report(); return; } /* remove what from old loc */ if((loc = old = db[what].location) != NOTHING) { if (Typeof(what) == TYPE_EXIT) db[loc].exits = remove_first(db[loc].exits, what); else db[loc].contents = remove_first(db[loc].contents, what); if (Hearer(what) && (old != where)) did_it(what,loc,A_LEAVE,NULL,A_OLEAVE,Dark(old)?NULL:"has left.",A_ALEAVE); 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: if(Typeof(what) == TYPE_EXIT || Typeof(what) == TYPE_ROOM) return; where = db[what].link; /* home */ break; } /* now put what in where */ if (Typeof(what) == TYPE_EXIT) PUSH(what,db[where].exits); else PUSH(what, db[where].contents); db[what].location = where; if (Hearer(what) && (where!=NOTHING) && (old!=where)) did_it(what,where,A_ENTER,NULL,A_OENTER,Dark(where)?NULL:"has arrived.", A_AENTER); } extern void enter_room(); #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 zon; dbref dropto; int a1=0,a2=0,a3=0,a4=0,a5=0,a6=0; static int deep=0; if(Typeof(player) == TYPE_ROOM) { notify(player, "Sorry, rooms aren't allowed to move."); return; } if (deep++>15) { deep--; return; } if (Typeof(loc)==TYPE_EXIT) { log_error(tprintf("Attempt to move %d to exit %d",player,loc)); report(); deep--; return; } /* check for room == HOME */ if(loc == HOME) loc = db[player].link; /* 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) && (old != NOTHING) && hear) { * notify others unless DARK * if(!Dark(old) && !Dark(player)) { notify_in(old, player, tprintf("%s has left.", db[player].name)); } }*/ /* go there */ if (loc != old) did_it(player,player,A_MOVE,NULL,A_OMOVE,NULL,A_AMOVE); moveit(player, loc); if (loc != old) DOZONE(zon, player) did_it(player,zon,A_MOVE,NULL,A_OMOVE,NULL,A_AMOVE); /* if old location has STICKY dropto, send stuff through it */ if((a1=(loc!=old)) && (a2=Dropper(player)) && (a3=(old != NOTHING)) && (a4=(Typeof(old)==TYPE_ROOM)) && (a5=((dropto = db[old].location) != NOTHING)) && (a6=(db[old].flags & STICKY))) maybe_dropto(old, dropto); /* autolook */ look_room(player, loc); 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(Typeof(player)==TYPE_ROOM) return; if (dest==HOME) dest=db[player].link; 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 */ if (controls(player,first,POW_MODIFY) || (!(IS(first,TYPE_THING,THING_KEY)) && !(db[first].flags & STICKY))) { 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; char *direction; { if(Typeof(player)==TYPE_ROOM) { return 0; } 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) dbref player; char *direction; { dbref exit; dbref loc; dbref zresult; dbref old=db[player].location; if(Typeof(player)==TYPE_ROOM) { notify(player, "Sorry, rooms aren't allowed to move."); return; } if(!string_compare(direction, "home")) { /* send him home */ /* but steal all his possessions */ if (Typeof(player) == TYPE_ROOM || Typeof(player)==TYPE_EXIT) return; if (!check_zone(player, player, db[player].link, 2)) return; if(((loc = db[player].location) != NOTHING) && !IS(loc,TYPE_ROOM,ROOM_AUDITORIUM)) { /* tell everybody else */ notify_in(loc, 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 */ 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, A_LOCK)) { if ((zresult = check_zone(player, player, db[exit].link, 0))) { did_it(player,exit,A_SUCC,NULL,A_OSUCC,(db[exit].flags&DARK)?NULL:glurpdup(tprintf("goes through the exit marked %s.",main_exit_name(exit))),A_ASUCC); switch(Typeof(db[exit].link)) { case TYPE_ROOM: enter_room(player, db[exit].link); break; case TYPE_PLAYER: case TYPE_THING: if (db[db[exit].link].flags & GOING) { notify(player,"You can't go that way."); return; } if (db[db[exit].link].location==NOTHING) return; safe_tel(player,db[exit].link); break; case TYPE_EXIT: notify(player,"This feature coming soon."); break; } did_it(player,exit,A_DROP,NULL,A_ODROP,(db[exit].flags&DARK)?NULL:glurpdup(tprintf("arrives from %s.",db[old].name)),A_ADROP); if (zresult > (dbref) 1) /* we entered a new zone */ did_it(player,zresult,A_DROP,NULL,A_ODROP,NULL,A_ADROP); } } else did_it(player,exit,A_FAIL,"You can't go that way.", A_OFAIL,NULL,A_AFAIL); break; } } } void do_get(player,what) dbref player; char *what; { dbref thing; dbref loc=db[player].location; if(Typeof(player)==TYPE_EXIT) { notify(player,"You can't pick up things!"); return; } if ((Typeof(loc)!=TYPE_ROOM) && !(db[loc].flags & ENTER_OK) && !controls(player,loc,POW_TELEPORT)) { notify(player,"Permission denied."); return; } init_match_check_keys(player, what, TYPE_THING); match_neighbor(); match_exit(); if(power(player, POW_TELEPORT)) 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(could_doit(player, thing, A_LOCK)) { moveto(thing, player); notify(thing,tprintf("You have been picked up by %s.", unparse_object(thing,player))); did_it(player,thing,A_SUCC,"Taken.",A_OSUCC,NULL,A_ASUCC); } else did_it(player,thing,A_FAIL,"You can't pick that up.", A_OFAIL,NULL,A_AFAIL); 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; 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!"); 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) && (IS(thing,TYPE_THING,THING_SACROK))) { /* sacrifice time */ notify(thing,"You dissolve forever into the wispy aether of space and time."); db[thing].flags = TYPE_THING|GOING; enter_room(thing,NOTHING); notify_in(loc,NOTHING, tprintf("%s drops %s and it dissolves forever into the wispy aether of space and time.", db[player].name,db[thing].name)); /* check for reward */ if( db[player].owner != db[thing].owner) { reward = Pennies(thing); if(reward < 1 || (Pennies(db[player].owner) > MAX_PENNIES)) { reward = 1; } else if(reward > MAX_OBJECT_ENDOWMENT) { reward = MAX_OBJECT_ENDOWMENT; } if(payfor(db[thing].owner,reward)) { giveto(db[player].owner,reward); notify(player, tprintf("You have received %d %s.", reward, reward == 1 ? "credit" : "credits")); } } do_empty(thing); do_halt(thing,""); } else if(db[thing].flags & STICKY) { notify(thing,"Dropped."); safe_tel(thing,HOME); } else if(db[loc].link != NOTHING && (Typeof(loc)==TYPE_ROOM) && !(db[loc].flags & STICKY)) { /* location has immediate dropto */ notify(thing,"Dropped."); moveto(thing, db[loc].link); } else { notify(thing,"Dropped."); enter_room(thing, loc); /* sprintf(buf, "%s dropped %s.", db[player].name, db[thing].name); notify_in(loc, player, buf);*/ } break; } sprintf(buf,"dropped %s.",db[thing].name); did_it(player,thing,A_DROP,"Dropped.",A_ODROP,buf,A_ADROP); } void do_enter(player,what) dbref player; char *what; { dbref thing; init_match_check_keys(player, what, TYPE_THING); match_neighbor(); match_exit(); if(power(player, POW_TELEPORT)) match_absolute(); /* the wizard has long fingers */ 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: if (!(db[thing].flags & ENTER_OK) && !controls(player,thing,POW_TELEPORT)) { did_it(player, thing, A_EFAIL, "You can't enter that.", A_OEFAIL, NULL, A_AEFAIL); return; } if(could_doit(player,thing,A_ELOCK) && check_zone(player, player, thing, 0)) { safe_tel(player,thing); } else { did_it(player, thing, A_EFAIL, "You can't enter that.", A_OEFAIL, NULL, A_AEFAIL); } break; } } void do_leave(player) dbref player; { if (Typeof(db[player].location)==TYPE_ROOM || db[db[player].location].location == NOTHING) { notify(player,"You can't leave"); return; } if(could_doit(player, db[player].location, A_LLOCK)) { enter_room(player,db[db[player].location].location); } else { did_it(player, db[player].location, A_LFAIL, "You can't leave.", A_OLFAIL, NULL, A_ALFAIL); } } /* Find the object holding thing */ dbref inside(thing) dbref thing; { int depth=10; dbref holder; for(holder = thing; depth; depth--, holder = thing, thing = db[holder].location) if(Typeof(thing) == TYPE_ROOM) { return holder; } return (dbref) 0; } /* Find the room the object/player is in */ dbref get_room(thing) dbref thing; { int depth=10; dbref holder; for(holder = thing; depth; depth--, holder = thing, thing = db[holder].location) if(Typeof(thing) == TYPE_ROOM) { return thing; } return (dbref) 0; } /* End move.c */