TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <stdio.h>
#include "db.h"
#include "config.h"
#include "externs.h"

int moveto(OBJ *what, OBJ *where)
{
  return(enter_room(what, where));
}

static int moveit(OBJ *what, OBJ *where)
{
  OBJ *old;

  if(Typeof(what) == TYPE_ROOM)
  {
    log_error("Trying to move a room.");
    return(0);
  }

  if(Typeof(what) == TYPE_EXIT && Typeof(where) != TYPE_ROOM)
  {
    log_error("Trying to move an exit to something besides a room.");
    return(0);
  }

  if(Typeof(what) == TYPE_EXIT)
  {
    remove_exit(what, what->location);
    add_exit(what, where);
  }
  else
  {
    remove_content(what, what->location);
    add_content(what, where);
  }

  old = what->location;
  what->location = where;

  look_room(what, where);

  if(what != where && !(IS(what, TYPE_PLAYER, PLAYER_INVISIBLE)))
    did_it(what, old, "LEAVE", NULL, "PLEAVE");

  atr_add(what, "LASTLOC", tprintf("%d", old->dbref));

  if(old != where && !(IS(what, TYPE_PLAYER, PLAYER_INVISIBLE)))
    did_it(what, where, "ENTER", NULL, "PENTER");

  return(1);
}

int enter_room(OBJ *player, OBJ *loc)
{
  OBJ *old;

  if(Typeof(player) == TYPE_ROOM)
  {
    notify(player, perm_denied());
    return(0);
  }

  if(Typeof(player) == TYPE_EXIT && Typeof(loc) != TYPE_ROOM)
  {
    notify(player, perm_denied());
    return(0);
  }
 
/* Fix so players can't get stuck in themselves */
  if(Typeof(player) == TYPE_PLAYER)
    if(loc == player)
    {
      notify(player, perm_denied());
      return(0);
    }

  old = player->location;

  if(!moveit(player, loc))
    return(0);

  return(1);
}

void safe_tel(OBJ *player, OBJ *dest)
{
  if(Typeof(player) == TYPE_ROOM)
  {
    notify(player, "I'm sorry, you're not allowed to move.");
    return;
  }

  if(Typeof(player) == TYPE_EXIT && Typeof(dest) != TYPE_ROOM)
  {
    notify(player, "Exits are only allowed in rooms.");
    return;
  }

  enter_room(player, dest);
}

static char *check_builtin_exits(OBJ *loc, char *str, OBJ **link)
{
  char *s;

  if(!string_compare(str, "n") || !string_compare(str, "north"))
    if(*(s = atr_get(loc, "NORTH")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "NORTH"));
  if(!string_compare(str, "s") || !string_compare(str, "south"))
    if(*(s = atr_get(loc, "SOUTH")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "SOUTH"));
  if(!string_compare(str, "e") || !string_compare(str, "east"))
    if(*(s = atr_get(loc, "EAST")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "EAST"));
  if(!string_compare(str, "w") || !string_compare(str, "west"))
    if(*(s = atr_get(loc, "WEST")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "WEST"));
  if(!string_compare(str, "ne") || !string_compare(str, "northeast"))
    if(*(s = atr_get(loc, "NORTHEAST")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "NORTHEAST"));
  if(!string_compare(str, "nw") || !string_compare(str, "northwest"))
    if(*(s = atr_get(loc, "NORTHWEST")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "NORTHWEST"));
  if(!string_compare(str, "se") || !string_compare(str, "southeast"))
    if(*(s = atr_get(loc, "SOUTHEAST")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "SOUTHEAST"));
  if(!string_compare(str, "sw") || !string_compare(str, "southwest"))
    if(*(s = atr_get(loc, "SOUTHWEST")))
      if((*link = match_dbref(s, TYPE_ROOM)))
        return(pseudo_exit_name(loc, "SOUTHWEST"));

  return(NULL);
}

int can_move(OBJ *player, char *direction)
{
  OBJ *exit, *link;

  if(Typeof(player) == TYPE_ROOM || Typeof(player) == TYPE_EXIT)
    return(0);

  if(check_builtin_exits(player->location, direction, &link))
    return(1);

  exit = match_object(player, direction, TYPE_EXIT);
  if(!exit || exit->location != player->location)
    return(0);

  return(1);
}

void do_move(OBJ *player, char *direction)
{
  OBJ *exit = NULL, *old_exit;
  OBJ *loc = player->location;
  OBJ *thing;
  int deep;
  char *builtin_exit;
  OBJ *builtin_link;
  
  if(Typeof(player) == TYPE_ROOM || Typeof(player) == TYPE_EXIT)
  {
    notify(player, "Sorry, you aren't allowed to move.");
    return;
  }
  
  if(!string_compare(direction, "home"))
  {
    if(!power(player, POW_TELEPORT))
    {
      notify(player, perm_denied());
      return;
    }

    if(player->location == player->link)
    {
      notify(player, "But you're already there!");
      return; 
    }

    if(!IS(player, TYPE_PLAYER, PLAYER_INVISIBLE))
      notify_in(loc, player, tprintf("%s goes home.", name(player)));

    safe_tel(player, player->link);
    return;
  }

/* Find the exit */
  if(!(builtin_exit = check_builtin_exits(loc, direction, &builtin_link)))
  {
    exit = match_object(player, direction, TYPE_EXIT);
    if(!exit || exit->location != loc || !exit->link)
    {
      notify(player, "You can't go that way.");
      return;
    }

    if(!could_doit(player, exit, "LOCK"))
    {
      did_it(player, exit, "FAIL", NULL, "PFAIL");
      return;
    }

    did_it(player, exit, "SUCC", NULL, "PSUCC");

    switch(Typeof(exit->link))
    {
      case TYPE_ROOM:
        enter_room(player, exit->link);
        break;
      case TYPE_PLAYER:
      case TYPE_THING:
        safe_tel(player, exit->link);
        break;
      case TYPE_EXIT:
        old_exit = exit;
        for(deep = 0;Typeof(exit->link) == TYPE_EXIT;deep++)
        {
          exit = exit->link;
          if(deep > 99)        /* Recursion check */
          {
            log_error(tprintf("%s links to too many exits.",
              unparse_object(old_exit, old_exit)));
            notify(player, "You can't go that way.");
            return;
          }
        }
        enter_room(player, exit->link);
        break;
    }
  }
  else
  {
    enter_room(player, builtin_link);
  }

  for(thing = loc->contents;thing;thing = thing->next_con)
  {
    if(thing == player)
      continue;

    if(!builtin_exit)
      if(!could_doit(thing, exit, "LSEE"))
        continue;

    if(Typeof(player) == TYPE_PLAYER ||
      (player->flags & PUPPET && !(player->flags & DARK)))
    {
      notify(thing,
        tprintf("%s goes through the exit marked %s.", name(player),
        (!builtin_exit)?name(exit):builtin_exit));
    }
  }

  for(thing = (builtin_exit)?builtin_link->contents:exit->link->contents;
    thing;thing = thing->next_con)
  {
    if(thing == player)
      continue;

    if(!builtin_exit)
      if(!could_doit(thing, exit, "LSEE"))
        continue;

    if(Typeof(player) == TYPE_PLAYER ||
      (player->flags & PUPPET && !(player->flags & DARK)))
    {
      notify(thing, tprintf("%s arrives from %s.",
        name(player), name(loc)));
    }
  }
}

void do_get(OBJ *player, char *what)
{
  OBJ *thing;
  OBJ *loc = player->location;

  if(!*what)
  {
    notify(player, "Get what?");
    return;
  }

  if(Typeof(player) == TYPE_EXIT)
  {
    notify(player, "You can't pick up things!");
    return;
  }

  thing = match_object(player, what, TYPE_THING);
  if(!thing ||
    (thing->location != loc && !controls(player, thing, POW_TELEPORT)))
  {
    notify(player, no_match(what));
    return;
  }

  if(thing->location == player)
  {
    notify(player, "You already have that!");
    return;
  }

  if(could_doit(player, thing, "LOCK"))
  {
    if(moveto(thing, player))
    {
      notify(thing, tprintf("You have been picked up by %s.",
        unparse_object(thing, player)));
      did_it(player, thing, "SUCC", "Taken.", "PSUCC");
    }
  }
  else
    did_it(player, thing, "FAIL", "You can't pick that up.", "PFAIL");
}

void do_drop(OBJ *player, char *name)
{
  OBJ *loc = player->location;
  OBJ *thing;
  
  if(!*name)
  {
    notify(player, "Drop what?");
    return;
  }

  thing = match_object(player, name, TYPE_THING);
  if(!thing || thing->location != player)
  {
    notify(player, no_match(name));
    return;
  }

  if(player->location->owner != player->owner && !Wizard(player))
  {
    notify(player, perm_denied());
    return;
  }

  notify(thing, "Dropped.");
  enter_room(thing, loc);

  did_it(player, thing, "DROP", "Dropped.", "PDROP");   
}

void do_enter(OBJ *player, char *what)
{
  OBJ *thing;
  
  if(!Wizard(player))
  {
    notify(player, perm_denied());
    return;
  }

  thing = match_object(player, what, TYPE_THING|TYPE_PLAYER);
  if(!thing || thing->location != player->location)
  {
    notify(player, no_match(what));
    return;
  }

  if(!could_doit(player, thing, "LENTER"))
  {
    did_it(player, thing, "EFAIL", "You can't enter that.", "PEFAIL");
    return;
  }

  safe_tel(player, thing);
}          

void do_leave(OBJ *player)
{
  if(!Wizard(player) || Typeof(player->location) == TYPE_ROOM)
  {
    notify(player, "You can't leave.");
    return;
  }

  if(!could_doit(player, player->location, "LLEAVE"))
  {
    did_it(player, player->location, "LFAIL", "You can't leave.",
      "PLFAIL");
    return;
  }

  enter_room(player, player->location->location);
}

/* Find the room the object/player is in */
OBJ *get_room(OBJ *thing)
{
  OBJ *old;

  for(old = getloc(thing);getloc(old) != old;old = getloc(old));

  return(old);
}

int bad_direction(char *dir)
{
  char *dir_list[] = {"N", "S", "E", "W", "NE", "NW", "SE", "SW", "U", "D",
                      "North", "South", "East", "West", "NorthEast",
                      "NorthWest", "SouthEast", "SouthWest", "Up", "Down", ""
                     };
  int i;

  for(i = 0;*dir_list[i];++i)
    if(!string_compare(dir, dir_list[i]))
      return(1);
  return(0);
}