nakedmudv3.0/
nakedmudv3.0/lib/
nakedmudv3.0/lib/logs/
nakedmudv3.0/lib/misc/
nakedmudv3.0/lib/players/
nakedmudv3.0/lib/pymodules/
nakedmudv3.0/lib/txt/
nakedmudv3.0/lib/world/
nakedmudv3.0/lib/world/examples/
nakedmudv3.0/lib/world/examples/mproto/
nakedmudv3.0/lib/world/examples/oproto/
nakedmudv3.0/lib/world/examples/reset/
nakedmudv3.0/lib/world/examples/rproto/
nakedmudv3.0/lib/world/examples/trigger/
nakedmudv3.0/lib/world/limbo/
nakedmudv3.0/lib/world/limbo/rproto/
nakedmudv3.0/src/alias/
nakedmudv3.0/src/char_vars/
nakedmudv3.0/src/editor/
nakedmudv3.0/src/example_module/
nakedmudv3.0/src/help/
nakedmudv3.0/src/set_val/
nakedmudv3.0/src/socials/
nakedmudv3.0/src/time/
//*****************************************************************************
//
// movement.c
//
// all of the functions assocciated with moving (chars and objects)
//
//*****************************************************************************

#include "mud.h"
#include "utils.h"
#include "character.h"
#include "world.h"
#include "zone.h"
#include "room.h"
#include "exit.h"
#include "handler.h"
#include "inform.h"
#include "object.h"
#include "movement.h"
#include "hooks.h"



//*****************************************************************************
// mandatory modules
//*****************************************************************************
#include "items/items.h"
#include "items/furniture.h"



//*****************************************************************************
// implementation of movement.h
//*****************************************************************************
EXIT_DATA *try_move_mssg(CHAR_DATA *ch, const char *dir) {
  ROOM_DATA *old_room = charGetRoom(ch);
  EXIT_DATA     *exit = try_move(ch, dir);
  
  // did we successfully move?
  if(exit != NULL) {
    ROOM_DATA *new_room = charGetRoom(ch);
    int          dirnum = dirGetNum(dir);
    // are we using an abbreviated direction name?
    if(dirnum == DIR_NONE && !roomGetExit(old_room, dir))
      dirnum = dirGetAbbrevNum(dir);

    // now, we have to temporarily go back to the old room so we can do
    // leave messages. Then we come back to the new room and do enter messages
    char_from_room(ch);
    char_to_room(ch, old_room);
    if(*exitGetSpecLeave(exit))
      message(ch, NULL, NULL, NULL, TRUE, TO_ROOM, exitGetSpecLeave(exit));
    else if(dirnum == DIR_NONE)
      send_around_char(ch, TRUE, "%s leaves.\r\n", charGetName(ch));
    else
      send_around_char(ch, TRUE, "%s leaves %s.\r\n", charGetName(ch), 
		       dirGetName(dirnum));
    char_from_room(ch);
    char_to_room(ch, new_room);
    
    // do we have a special enter message? If so, use them
    if(*exitGetSpecEnter(exit))
      message(ch, NULL, NULL, NULL, FALSE, TO_ROOM, exitGetSpecEnter(exit));
    else if(dirnum == DIR_NONE)
      send_around_char(ch, TRUE, "%s has arrived.\r\n", charGetName(ch));
    else
      send_around_char(ch, TRUE, "%s arrives from the %s.\r\n",
		       charGetName(ch), dirGetName(dirGetOpposite(dirnum)));
  }
  return exit;
}

EXIT_DATA *try_move(CHAR_DATA *ch, const char *dir) {
  EXIT_DATA *exit = roomGetExit(charGetRoom(ch), dir);
  ROOM_DATA   *to = NULL;

  // are we using an abbreviated direction name?
  if(exit == NULL && dirGetAbbrevNum(dir) != DIR_NONE) {
    dir  = dirGetName(dirGetAbbrevNum(dir));
    exit = roomGetExit(charGetRoom(ch), dir);
  }

  // did we find an exit?
  if(exit == NULL || !can_see_exit(ch, exit))
    send_to_char(ch, "{gAlas, there is no exit in that direction.\r\n");
  else if(exitIsClosed(exit))
    send_to_char(ch, "You will have to open %s first.\r\n",
		 (*exitGetName(exit) ? exitGetName(exit) : "it"));
  else if((to = worldGetRoom(gameworld, exitGetTo(exit))) == NULL)
    send_to_char(ch, "It doesn't look like %s leads anywhere!", 
		 (*exitGetName(exit) ? exitGetName(exit) : "it"));
  else {
    ROOM_DATA  *old_room = charGetRoom(ch);

    // try all of our exit hooks
    hookRun("exit", ch, old_room, exit);

    char_from_room(ch);
    char_to_room(ch, to);
    look_at_room(ch, charGetRoom(ch));

    // now try all of our entrance hooks
    hookRun("enter", ch, to, NULL);

    return exit;
  }

  // our exit failed
  return NULL;
}

//
// cmd_move is the basic entry into all of the movement utilities. See
// try_move() in movement.h
COMMAND(cmd_move) {
  try_move_mssg(ch, cmd);
}



//*****************************************************************************
// Functions and commands for changing position (sleeping, standing, etc)
//*****************************************************************************
bool try_change_pos(CHAR_DATA *ch, int pos) {
  if(charGetPos(ch) == pos) {
    send_to_char(ch, "You are already %s.\r\n", posGetName(pos));
    return FALSE;
  }
  else {
    send_to_char(ch, "You %s.\r\n", posGetActionSelf(pos));
    send_around_char(ch, TRUE, "%s %s.\r\n", 
		     charGetName(ch), posGetActionOther(pos));
    charSetPos(ch, pos);
    return TRUE;
  }
}

bool try_use_furniture(CHAR_DATA *ch, char *arg, int pos) {
  // strip out "at" and "on". People might be 
  // trying "sit at table" or "sleep on bed"
  strip_word(arg, "at");
  strip_word(arg, "on");

  OBJ_DATA *furniture = generic_find(ch, arg,
				     FIND_TYPE_OBJ, 
				     FIND_SCOPE_ROOM | FIND_SCOPE_VISIBLE,
				     FALSE, NULL);
  
  if(furniture == NULL)
    send_to_char(ch, "Where did you want to %s?\r\n", posGetActionSelf(pos));
  else if(!objIsType(furniture, "furniture"))
    send_to_char(ch, "But that's not furniture!\r\n");
  // make sure we found something we might be able to sit on
  else if(charGetFurniture(ch) == furniture)
    send_to_char(ch, "You're already %s %s.\r\n",
		 (furnitureGetType(furniture) == FURNITURE_ON ? "on" : "at"),
		 objGetName(furniture));

  else if(furnitureGetCapacity(furniture) <= listSize(objGetUsers(furniture)))
    send_to_char(ch, "There isn't any room left.\r\n");
  
  else {
    // if we're already sitting on something, get up first
    if(charGetFurniture(ch)) {
      send_to_char(ch, "You stand up from %s.\r\n", 
		   objGetName(charGetFurniture(ch)));
      message(ch, NULL, charGetFurniture(ch), NULL,TRUE, TO_ROOM,
	      "$n stands up from $o.");
      char_from_furniture(ch);
    }

    // send out messages
    char other_buf[SMALL_BUFFER];
    sprintf(other_buf, "$n %s %s $o.",	
	    posGetActionOther(pos),
	    (furnitureGetType(furniture) == FURNITURE_ON ? "on" : "at"));
    message(ch, NULL, furniture, NULL, TRUE, TO_ROOM, other_buf);

    send_to_char(ch, "You %s %s %s.\r\n",
		 posGetActionSelf(pos),
		 (furnitureGetType(furniture) == FURNITURE_ON ? "on" : "at"),
		 objGetName(furniture));

    // now sit down on the new thing
    char_to_furniture(ch, furniture);
    charSetPos(ch, pos);
    return TRUE;
  }

  return FALSE;
}

COMMAND(cmd_sit) {
  if(!arg || !*arg)
    try_change_pos(ch, POS_SITTING);
  else
    try_use_furniture(ch, arg, POS_SITTING);
}

COMMAND(cmd_sleep) {
  if(!arg || !*arg)
    try_change_pos(ch, POS_SLEEPING);
  else
    try_use_furniture(ch, arg, POS_SLEEPING);
}

COMMAND(cmd_stand) {
  if(charGetPos(ch) == POS_FLYING) {
    send_to_char(ch, "You stop flying.\r\n");
    send_around_char(ch, TRUE, "%s stops flying.\r\n", charGetName(ch));
    charSetPos(ch, POS_STANDING);
  }
  else {
    if(try_change_pos(ch, POS_STANDING) && charGetFurniture(ch))
      char_from_furniture(ch);
  }
}

COMMAND(cmd_wake) {
  send_to_char(ch, "You stop sleeping and sit up.\r\n");
  send_around_char(ch, TRUE, "%s stops sleeping and sits up.\r\n",
		   charGetName(ch));
  charSetPos(ch, POS_SITTING);
}