/* 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 */