/ circle3.1 / src / act.movement.c
act.movement.c
  1  /* ************************************************************************
  2  *   File: act.movement.c                                Part of CircleMUD *
  3  *  Usage: movement commands, door handling, & sleep/rest/etc state        *
  4  *                                                                         *
  5  *  All rights reserved.  See license.doc for complete information.        *
  6  *                                                                         *
  7  *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
  8  *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
  9  ************************************************************************ */
 10  
 11  #include "conf.h"
 12  #include "sysdep.h"
 13  
 14  
 15  #include "structs.h"
 16  #include "utils.h"
 17  #include "comm.h"
 18  #include "interpreter.h"
 19  #include "handler.h"
 20  #include "db.h"
 21  #include "spells.h"
 22  #include "house.h"
 23  #include "constants.h"
 24  
 25  
 26  /* external variables  */
 27  extern int tunnel_size;
 28  
 29  /* external functions */
 30  int special(struct char_data *ch, int cmd, char *arg);
 31  void death_cry(struct char_data *ch);
 32  int find_eq_pos(struct char_data *ch, struct obj_data *obj, char *arg);
 33  
 34  /* local functions */
 35  int has_boat(struct char_data *ch);
 36  int find_door(struct char_data *ch, const char *type, char *dir, const char *cmdname);
 37  int has_key(struct char_data *ch, obj_vnum key);
 38  void do_doorcmd(struct char_data *ch, struct obj_data *obj, int door, int scmd);
 39  int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd);
 40  ACMD(do_gen_door);
 41  ACMD(do_enter);
 42  ACMD(do_leave);
 43  ACMD(do_stand);
 44  ACMD(do_sit);
 45  ACMD(do_rest);
 46  ACMD(do_sleep);
 47  ACMD(do_wake);
 48  ACMD(do_follow);
 49  
 50  
 51  /* simple function to determine if char can walk on water */
 52  int has_boat(struct char_data *ch)
 53  {
 54    struct obj_data *obj;
 55    int i;
 56  
 57  /*
 58    if (ROOM_IDENTITY(IN_ROOM(ch)) == DEAD_SEA)
 59      return (1);
 60  */
 61  
 62    if (GET_LEVEL(ch) > LVL_IMMORT)
 63      return (1);
 64  
 65    if (AFF_FLAGGED(ch, AFF_WATERWALK))
 66      return (1);
 67  
 68    /* non-wearable boats in inventory will do it */
 69    for (obj = ch->carrying; obj; obj = obj->next_content)
 70      if (GET_OBJ_TYPE(obj) == ITEM_BOAT && (find_eq_pos(ch, obj, NULL) < 0))
 71        return (1);
 72  
 73    /* and any boat you're wearing will do it too */
 74    for (i = 0; i < NUM_WEARS; i++)
 75      if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_BOAT)
 76        return (1);
 77  
 78    return (0);
 79  }
 80  
 81    
 82  
 83  /* do_simple_move assumes
 84   *    1. That there is no master and no followers.
 85   *    2. That the direction exists.
 86   *
 87   *   Returns :
 88   *   1 : If succes.
 89   *   0 : If fail
 90   */
 91  int do_simple_move(struct char_data *ch, int dir, int need_specials_check)
 92  {
 93    char throwaway[MAX_INPUT_LENGTH] = ""; /* Functions assume writable. */
 94    room_rnum was_in;
 95    int need_movement;
 96  
 97    /*
 98     * Check for special routines (North is 1 in command list, but 0 here) Note
 99     * -- only check if following; this avoids 'double spec-proc' bug
100     */
101    if (need_specials_check && special(ch, dir + 1, throwaway))
102      return (0);
103  
104    /* charmed? */
105    if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) {
106      send_to_char(ch, "The thought of leaving your master makes you weep.\r\n");
107      act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM);
108      return (0);
109    }
110  
111    /* if this room or the one we're going to needs a boat, check for one */
112    if ((SECT(IN_ROOM(ch)) == SECT_WATER_NOSWIM) ||
113        (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) {
114      if (!has_boat(ch)) {
115        send_to_char(ch, "You need a boat to go there.\r\n");
116        return (0);
117      }
118    }
119  
120    /* move points needed is avg. move loss for src and destination sect type */
121    need_movement = (movement_loss[SECT(IN_ROOM(ch))] +
122  		   movement_loss[SECT(EXIT(ch, dir)->to_room)]) / 2;
123  
124    if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) {
125      if (need_specials_check && ch->master)
126        send_to_char(ch, "You are too exhausted to follow.\r\n");
127      else
128        send_to_char(ch, "You are too exhausted.\r\n");
129  
130      return (0);
131    }
132    if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_ATRIUM)) {
133      if (!House_can_enter(ch, GET_ROOM_VNUM(EXIT(ch, dir)->to_room))) {
134        send_to_char(ch, "That's private property -- no trespassing!\r\n");
135        return (0);
136      }
137    }
138    if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) &&
139        num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) >= tunnel_size) {
140      if (tunnel_size > 1)
141        send_to_char(ch, "There isn't enough room for you to go there!\r\n");
142      else
143        send_to_char(ch, "There isn't enough room there for more than one person!\r\n");
144      return (0);
145    }
146    /* Mortals and low level gods cannot enter greater god rooms. */
147    if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) &&
148  	GET_LEVEL(ch) < LVL_GRGOD) {
149      send_to_char(ch, "You aren't godly enough to use that room!\r\n");
150      return (0);
151    }
152  
153    /* Now we know we're allow to go into the room. */
154    if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch))
155      GET_MOVE(ch) -= need_movement;
156  
157    if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
158      char buf2[MAX_STRING_LENGTH];
159  
160      snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]);
161      act(buf2, TRUE, ch, 0, 0, TO_ROOM);
162    }
163    was_in = IN_ROOM(ch);
164    char_from_room(ch);
165    char_to_room(ch, world[was_in].dir_option[dir]->to_room);
166  
167    if (!AFF_FLAGGED(ch, AFF_SNEAK))
168      act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);
169  
170    if (ch->desc != NULL)
171      look_at_room(ch, 0);
172  
173    if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) {
174      log_death_trap(ch);
175      death_cry(ch);
176      extract_char(ch);
177      return (0);
178    }
179    return (1);
180  }
181  
182  
183  int perform_move(struct char_data *ch, int dir, int need_specials_check)
184  {
185    room_rnum was_in;
186    struct follow_type *k, *next;
187  
188    if (ch == NULL || dir < 0 || dir >= NUM_OF_DIRS || FIGHTING(ch))
189      return (0);
190    else if (!EXIT(ch, dir) || EXIT(ch, dir)->to_room == NOWHERE)
191      send_to_char(ch, "Alas, you cannot go that way...\r\n");
192    else if (EXIT_FLAGGED(EXIT(ch, dir), EX_CLOSED)) {
193      if (EXIT(ch, dir)->keyword)
194        send_to_char(ch, "The %s seems to be closed.\r\n", fname(EXIT(ch, dir)->keyword));
195      else
196        send_to_char(ch, "It seems to be closed.\r\n");
197    } else {
198      if (!ch->followers)
199        return (do_simple_move(ch, dir, need_specials_check));
200  
201      was_in = IN_ROOM(ch);
202      if (!do_simple_move(ch, dir, need_specials_check))
203        return (0);
204  
205      for (k = ch->followers; k; k = next) {
206        next = k->next;
207        if ((IN_ROOM(k->follower) == was_in) &&
208  	  (GET_POS(k->follower) >= POS_STANDING)) {
209  	act("You follow $N.\r\n", FALSE, k->follower, 0, ch, TO_CHAR);
210  	perform_move(k->follower, dir, 1);
211        }
212      }
213      return (1);
214    }
215    return (0);
216  }
217  
218  
219  ACMD(do_move)
220  {
221    /*
222     * This is basically a mapping of cmd numbers to perform_move indices.
223     * It cannot be done in perform_move because perform_move is called
224     * by other functions which do not require the remapping.
225     */
226    perform_move(ch, subcmd - 1, 0);
227  }
228  
229  
230  int find_door(struct char_data *ch, const char *type, char *dir, const char *cmdname)
231  {
232    int door;
233  
234    if (*dir) {			/* a direction was specified */
235      if ((door = search_block(dir, dirs, FALSE)) == -1) {	/* Partial Match */
236        send_to_char(ch, "That's not a direction.\r\n");
237        return (-1);
238      }
239      if (EXIT(ch, door)) {	/* Braces added according to indent. -gg */
240        if (EXIT(ch, door)->keyword) {
241  	if (isname(type, EXIT(ch, door)->keyword))
242  	  return (door);
243  	else {
244  	  send_to_char(ch, "I see no %s there.\r\n", type);
245  	  return (-1);
246          }
247        } else
248  	return (door);
249      } else {
250        send_to_char(ch, "I really don't see how you can %s anything there.\r\n", cmdname);
251        return (-1);
252      }
253    } else {			/* try to locate the keyword */
254      if (!*type) {
255        send_to_char(ch, "What is it you want to %s?\r\n", cmdname);
256        return (-1);
257      }
258      for (door = 0; door < NUM_OF_DIRS; door++)
259        if (EXIT(ch, door))
260  	if (EXIT(ch, door)->keyword)
261  	  if (isname(type, EXIT(ch, door)->keyword))
262  	    return (door);
263  
264      send_to_char(ch, "There doesn't seem to be %s %s here.\r\n", AN(type), type);
265      return (-1);
266    }
267  }
268  
269  
270  int has_key(struct char_data *ch, obj_vnum key)
271  {
272    struct obj_data *o;
273  
274    for (o = ch->carrying; o; o = o->next_content)
275      if (GET_OBJ_VNUM(o) == key)
276        return (1);
277  
278    if (GET_EQ(ch, WEAR_HOLD))
279      if (GET_OBJ_VNUM(GET_EQ(ch, WEAR_HOLD)) == key)
280        return (1);
281  
282    return (0);
283  }
284  
285  
286  
287  #define NEED_OPEN	(1 << 0)
288  #define NEED_CLOSED	(1 << 1)
289  #define NEED_UNLOCKED	(1 << 2)
290  #define NEED_LOCKED	(1 << 3)
291  
292  const char *cmd_door[] =
293  {
294    "open",
295    "close",
296    "unlock",
297    "lock",
298    "pick"
299  };
300  
301  const int flags_door[] =
302  {
303    NEED_CLOSED | NEED_UNLOCKED,
304    NEED_OPEN,
305    NEED_CLOSED | NEED_LOCKED,
306    NEED_CLOSED | NEED_UNLOCKED,
307    NEED_CLOSED | NEED_LOCKED
308  };
309  
310  
311  #define EXITN(room, door)		(world[room].dir_option[door])
312  #define OPEN_DOOR(room, obj, door)	((obj) ?\
313  		(REMOVE_BIT(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) :\
314  		(REMOVE_BIT(EXITN(room, door)->exit_info, EX_CLOSED)))
315  #define CLOSE_DOOR(room, obj, door)	((obj) ?\
316  		(SET_BIT(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) :\
317  		(SET_BIT(EXITN(room, door)->exit_info, EX_CLOSED)))
318  #define LOCK_DOOR(room, obj, door)	((obj) ?\
319  		(SET_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) :\
320  		(SET_BIT(EXITN(room, door)->exit_info, EX_LOCKED)))
321  #define UNLOCK_DOOR(room, obj, door)	((obj) ?\
322  		(REMOVE_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) :\
323  		(REMOVE_BIT(EXITN(room, door)->exit_info, EX_LOCKED)))
324  #define TOGGLE_LOCK(room, obj, door)	((obj) ?\
325  		(TOGGLE_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) :\
326  		(TOGGLE_BIT(EXITN(room, door)->exit_info, EX_LOCKED)))
327  
328  void do_doorcmd(struct char_data *ch, struct obj_data *obj, int door, int scmd)
329  {
330    char buf[MAX_STRING_LENGTH];
331    size_t len;
332    room_rnum other_room = NOWHERE;
333    struct room_direction_data *back = NULL;
334  
335    len = snprintf(buf, sizeof(buf), "$n %ss ", cmd_door[scmd]);
336    if (!obj && ((other_room = EXIT(ch, door)->to_room) != NOWHERE))
337      if ((back = world[other_room].dir_option[rev_dir[door]]) != NULL)
338        if (back->to_room != IN_ROOM(ch))
339  	back = NULL;
340  
341    switch (scmd) {
342    case SCMD_OPEN:
343      OPEN_DOOR(IN_ROOM(ch), obj, door);
344      if (back)
345        OPEN_DOOR(other_room, obj, rev_dir[door]);
346      send_to_char(ch, "%s", OK);
347      break;
348  
349    case SCMD_CLOSE:
350      CLOSE_DOOR(IN_ROOM(ch), obj, door);
351      if (back)
352        CLOSE_DOOR(other_room, obj, rev_dir[door]);
353      send_to_char(ch, "%s", OK);
354      break;
355  
356    case SCMD_LOCK:
357      LOCK_DOOR(IN_ROOM(ch), obj, door);
358      if (back)
359        LOCK_DOOR(other_room, obj, rev_dir[door]);
360      send_to_char(ch, "*Click*\r\n");
361      break;
362  
363    case SCMD_UNLOCK:
364      UNLOCK_DOOR(IN_ROOM(ch), obj, door);
365      if (back)
366        UNLOCK_DOOR(other_room, obj, rev_dir[door]);
367      send_to_char(ch, "*Click*\r\n");
368      break;
369  
370    case SCMD_PICK:
371      TOGGLE_LOCK(IN_ROOM(ch), obj, door);
372      if (back)
373        TOGGLE_LOCK(other_room, obj, rev_dir[door]);
374      send_to_char(ch, "The lock quickly yields to your skills.\r\n");
375      len = strlcpy(buf, "$n skillfully picks the lock on ", sizeof(buf));
376      break;
377    }
378  
379    /* Notify the room. */
380    if (len < sizeof(buf))
381      snprintf(buf + len, sizeof(buf) - len, "%s%s.",
382  	obj ? "" : "the ", obj ? "$p" : EXIT(ch, door)->keyword ? "$F" : "door");
383    if (!obj || IN_ROOM(obj) != NOWHERE)
384      act(buf, FALSE, ch, obj, obj ? 0 : EXIT(ch, door)->keyword, TO_ROOM);
385  
386    /* Notify the other room */
387    if (back && (scmd == SCMD_OPEN || scmd == SCMD_CLOSE))
388        send_to_room(EXIT(ch, door)->to_room, "The %s is %s%s from the other side.",
389  		back->keyword ? fname(back->keyword) : "door", cmd_door[scmd],
390  		scmd == SCMD_CLOSE ? "d" : "ed");
391  }
392  
393  
394  int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd)
395  {
396    int percent, skill_lvl;
397  
398    if (scmd != SCMD_PICK)
399      return (1);
400  
401    percent = rand_number(1, 101);
402    skill_lvl = GET_SKILL(ch, SKILL_PICK_LOCK) + dex_app_skill[GET_DEX(ch)].p_locks;
403  
404    if (keynum == NOTHING)
405      send_to_char(ch, "Odd - you can't seem to find a keyhole.\r\n");
406    else if (pickproof)
407      send_to_char(ch, "It resists your attempts to pick it.\r\n");
408    else if (percent > skill_lvl)
409      send_to_char(ch, "You failed to pick the lock.\r\n");
410    else
411      return (1);
412  
413    return (0);
414  }
415  
416  
417  #define DOOR_IS_OPENABLE(ch, obj, door)	((obj) ? \
418  			((GET_OBJ_TYPE(obj) == ITEM_CONTAINER) && \
419  			OBJVAL_FLAGGED(obj, CONT_CLOSEABLE)) :\
420  			(EXIT_FLAGGED(EXIT(ch, door), EX_ISDOOR)))
421  #define DOOR_IS_OPEN(ch, obj, door)	((obj) ? \
422  			(!OBJVAL_FLAGGED(obj, CONT_CLOSED)) :\
423  			(!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED)))
424  #define DOOR_IS_UNLOCKED(ch, obj, door)	((obj) ? \
425  			(!OBJVAL_FLAGGED(obj, CONT_LOCKED)) :\
426  			(!EXIT_FLAGGED(EXIT(ch, door), EX_LOCKED)))
427  #define DOOR_IS_PICKPROOF(ch, obj, door) ((obj) ? \
428  			(OBJVAL_FLAGGED(obj, CONT_PICKPROOF)) : \
429  			(EXIT_FLAGGED(EXIT(ch, door), EX_PICKPROOF)))
430  
431  #define DOOR_IS_CLOSED(ch, obj, door)	(!(DOOR_IS_OPEN(ch, obj, door)))
432  #define DOOR_IS_LOCKED(ch, obj, door)	(!(DOOR_IS_UNLOCKED(ch, obj, door)))
433  #define DOOR_KEY(ch, obj, door)		((obj) ? (GET_OBJ_VAL(obj, 2)) : \
434  					(EXIT(ch, door)->key))
435  
436  ACMD(do_gen_door)
437  {
438    int door = -1;
439    obj_vnum keynum;
440    char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH];
441    struct obj_data *obj = NULL;
442    struct char_data *victim = NULL;
443  
444    skip_spaces(&argument);
445    if (!*argument) {
446      send_to_char(ch, "%c%s what?\r\n", UPPER(*cmd_door[subcmd]), cmd_door[subcmd] + 1);
447      return;
448    }
449    two_arguments(argument, type, dir);
450    if (!generic_find(type, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj))
451      door = find_door(ch, type, dir, cmd_door[subcmd]);
452  
453    if ((obj) || (door >= 0)) {
454      keynum = DOOR_KEY(ch, obj, door);
455      if (!(DOOR_IS_OPENABLE(ch, obj, door)))
456        act("You can't $F that!", FALSE, ch, 0, cmd_door[subcmd], TO_CHAR);
457      else if (!DOOR_IS_OPEN(ch, obj, door) &&
458  	     IS_SET(flags_door[subcmd], NEED_OPEN))
459        send_to_char(ch, "But it's already closed!\r\n");
460      else if (!DOOR_IS_CLOSED(ch, obj, door) &&
461  	     IS_SET(flags_door[subcmd], NEED_CLOSED))
462        send_to_char(ch, "But it's currently open!\r\n");
463      else if (!(DOOR_IS_LOCKED(ch, obj, door)) &&
464  	     IS_SET(flags_door[subcmd], NEED_LOCKED))
465        send_to_char(ch, "Oh.. it wasn't locked, after all..\r\n");
466      else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) &&
467  	     IS_SET(flags_door[subcmd], NEED_UNLOCKED))
468        send_to_char(ch, "It seems to be locked.\r\n");
469      else if (!has_key(ch, keynum) && (GET_LEVEL(ch) < LVL_GOD) &&
470  	     ((subcmd == SCMD_LOCK) || (subcmd == SCMD_UNLOCK)))
471        send_to_char(ch, "You don't seem to have the proper key.\r\n");
472      else if (ok_pick(ch, keynum, DOOR_IS_PICKPROOF(ch, obj, door), subcmd))
473        do_doorcmd(ch, obj, door, subcmd);
474    }
475    return;
476  }
477  
478  
479  
480  ACMD(do_enter)
481  {
482    char buf[MAX_INPUT_LENGTH];
483    int door;
484  
485    one_argument(argument, buf);
486  
487    if (*buf) {			/* an argument was supplied, search for door
488  				 * keyword */
489      for (door = 0; door < NUM_OF_DIRS; door++)
490        if (EXIT(ch, door))
491  	if (EXIT(ch, door)->keyword)
492  	  if (!str_cmp(EXIT(ch, door)->keyword, buf)) {
493  	    perform_move(ch, door, 1);
494  	    return;
495  	  }
496      send_to_char(ch, "There is no %s here.\r\n", buf);
497    } else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_INDOORS))
498      send_to_char(ch, "You are already indoors.\r\n");
499    else {
500      /* try to locate an entrance */
501      for (door = 0; door < NUM_OF_DIRS; door++)
502        if (EXIT(ch, door))
503  	if (EXIT(ch, door)->to_room != NOWHERE)
504  	  if (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) &&
505  	      ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_INDOORS)) {
506  	    perform_move(ch, door, 1);
507  	    return;
508  	  }
509      send_to_char(ch, "You can't seem to find anything to enter.\r\n");
510    }
511  }
512  
513  
514  ACMD(do_leave)
515  {
516    int door;
517  
518    if (OUTSIDE(ch))
519      send_to_char(ch, "You are outside.. where do you want to go?\r\n");
520    else {
521      for (door = 0; door < NUM_OF_DIRS; door++)
522        if (EXIT(ch, door))
523  	if (EXIT(ch, door)->to_room != NOWHERE)
524  	  if (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) &&
525  	    !ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_INDOORS)) {
526  	    perform_move(ch, door, 1);
527  	    return;
528  	  }
529      send_to_char(ch, "I see no obvious exits to the outside.\r\n");
530    }
531  }
532  
533  
534  ACMD(do_stand)
535  {
536    switch (GET_POS(ch)) {
537    case POS_STANDING:
538      send_to_char(ch, "You are already standing.\r\n");
539      break;
540    case POS_SITTING:
541      send_to_char(ch, "You stand up.\r\n");
542      act("$n clambers to $s feet.", TRUE, ch, 0, 0, TO_ROOM);
543      /* Will be sitting after a successful bash and may still be fighting. */
544      GET_POS(ch) = FIGHTING(ch) ? POS_FIGHTING : POS_STANDING;
545      break;
546    case POS_RESTING:
547      send_to_char(ch, "You stop resting, and stand up.\r\n");
548      act("$n stops resting, and clambers on $s feet.", TRUE, ch, 0, 0, TO_ROOM);
549      GET_POS(ch) = POS_STANDING;
550      break;
551    case POS_SLEEPING:
552      send_to_char(ch, "You have to wake up first!\r\n");
553      break;
554    case POS_FIGHTING:
555      send_to_char(ch, "Do you not consider fighting as standing?\r\n");
556      break;
557    default:
558      send_to_char(ch, "You stop floating around, and put your feet on the ground.\r\n");
559      act("$n stops floating around, and puts $s feet on the ground.",
560  	TRUE, ch, 0, 0, TO_ROOM);
561      GET_POS(ch) = POS_STANDING;
562      break;
563    }
564  }
565  
566  
567  ACMD(do_sit)
568  {
569    switch (GET_POS(ch)) {
570    case POS_STANDING:
571      send_to_char(ch, "You sit down.\r\n");
572      act("$n sits down.", FALSE, ch, 0, 0, TO_ROOM);
573      GET_POS(ch) = POS_SITTING;
574      break;
575    case POS_SITTING:
576      send_to_char(ch, "You're sitting already.\r\n");
577      break;
578    case POS_RESTING:
579      send_to_char(ch, "You stop resting, and sit up.\r\n");
580      act("$n stops resting.", TRUE, ch, 0, 0, TO_ROOM);
581      GET_POS(ch) = POS_SITTING;
582      break;
583    case POS_SLEEPING:
584      send_to_char(ch, "You have to wake up first.\r\n");
585      break;
586    case POS_FIGHTING:
587      send_to_char(ch, "Sit down while fighting? Are you MAD?\r\n");
588      break;
589    default:
590      send_to_char(ch, "You stop floating around, and sit down.\r\n");
591      act("$n stops floating around, and sits down.", TRUE, ch, 0, 0, TO_ROOM);
592      GET_POS(ch) = POS_SITTING;
593      break;
594    }
595  }
596  
597  
598  ACMD(do_rest)
599  {
600    switch (GET_POS(ch)) {
601    case POS_STANDING:
602      send_to_char(ch, "You sit down and rest your tired bones.\r\n");
603      act("$n sits down and rests.", TRUE, ch, 0, 0, TO_ROOM);
604      GET_POS(ch) = POS_RESTING;
605      break;
606    case POS_SITTING:
607      send_to_char(ch, "You rest your tired bones.\r\n");
608      act("$n rests.", TRUE, ch, 0, 0, TO_ROOM);
609      GET_POS(ch) = POS_RESTING;
610      break;
611    case POS_RESTING:
612      send_to_char(ch, "You are already resting.\r\n");
613      break;
614    case POS_SLEEPING:
615      send_to_char(ch, "You have to wake up first.\r\n");
616      break;
617    case POS_FIGHTING:
618      send_to_char(ch, "Rest while fighting?  Are you MAD?\r\n");
619      break;
620    default:
621      send_to_char(ch, "You stop floating around, and stop to rest your tired bones.\r\n");
622      act("$n stops floating around, and rests.", FALSE, ch, 0, 0, TO_ROOM);
623      GET_POS(ch) = POS_SITTING;
624      break;
625    }
626  }
627  
628  
629  ACMD(do_sleep)
630  {
631    switch (GET_POS(ch)) {
632    case POS_STANDING:
633    case POS_SITTING:
634    case POS_RESTING:
635      send_to_char(ch, "You go to sleep.\r\n");
636      act("$n lies down and falls asleep.", TRUE, ch, 0, 0, TO_ROOM);
637      GET_POS(ch) = POS_SLEEPING;
638      break;
639    case POS_SLEEPING:
640      send_to_char(ch, "You are already sound asleep.\r\n");
641      break;
642    case POS_FIGHTING:
643      send_to_char(ch, "Sleep while fighting?  Are you MAD?\r\n");
644      break;
645    default:
646      send_to_char(ch, "You stop floating around, and lie down to sleep.\r\n");
647      act("$n stops floating around, and lie down to sleep.",
648  	TRUE, ch, 0, 0, TO_ROOM);
649      GET_POS(ch) = POS_SLEEPING;
650      break;
651    }
652  }
653  
654  
655  ACMD(do_wake)
656  {
657    char arg[MAX_INPUT_LENGTH];
658    struct char_data *vict;
659    int self = 0;
660  
661    one_argument(argument, arg);
662    if (*arg) {
663      if (GET_POS(ch) == POS_SLEEPING)
664        send_to_char(ch, "Maybe you should wake yourself up first.\r\n");
665      else if ((vict = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM)) == NULL)
666        send_to_char(ch, "%s", NOPERSON);
667      else if (vict == ch)
668        self = 1;
669      else if (AWAKE(vict))
670        act("$E is already awake.", FALSE, ch, 0, vict, TO_CHAR);
671      else if (AFF_FLAGGED(vict, AFF_SLEEP))
672        act("You can't wake $M up!", FALSE, ch, 0, vict, TO_CHAR);
673      else if (GET_POS(vict) < POS_SLEEPING)
674        act("$E's in pretty bad shape!", FALSE, ch, 0, vict, TO_CHAR);
675      else {
676        act("You wake $M up.", FALSE, ch, 0, vict, TO_CHAR);
677        act("You are awakened by $n.", FALSE, ch, 0, vict, TO_VICT | TO_SLEEP);
678        GET_POS(vict) = POS_SITTING;
679      }
680      if (!self)
681        return;
682    }
683    if (AFF_FLAGGED(ch, AFF_SLEEP))
684      send_to_char(ch, "You can't wake up!\r\n");
685    else if (GET_POS(ch) > POS_SLEEPING)
686      send_to_char(ch, "You are already awake...\r\n");
687    else {
688      send_to_char(ch, "You awaken, and sit up.\r\n");
689      act("$n awakens.", TRUE, ch, 0, 0, TO_ROOM);
690      GET_POS(ch) = POS_SITTING;
691    }
692  }
693  
694  
695  ACMD(do_follow)
696  {
697    char buf[MAX_INPUT_LENGTH];
698    struct char_data *leader;
699  
700    one_argument(argument, buf);
701  
702    if (*buf) {
703      if (!(leader = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM))) {
704        send_to_char(ch, "%s", NOPERSON);
705        return;
706      }
707    } else {
708      send_to_char(ch, "Whom do you wish to follow?\r\n");
709      return;
710    }
711  
712    if (ch->master == leader) {
713      act("You are already following $M.", FALSE, ch, 0, leader, TO_CHAR);
714      return;
715    }
716    if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master)) {
717      act("But you only feel like following $N!", FALSE, ch, 0, ch->master, TO_CHAR);
718    } else {			/* Not Charmed follow person */
719      if (leader == ch) {
720        if (!ch->master) {
721  	send_to_char(ch, "You are already following yourself.\r\n");
722  	return;
723        }
724        stop_follower(ch);
725      } else {
726        if (circle_follow(ch, leader)) {
727  	send_to_char(ch, "Sorry, but following in loops is not allowed.\r\n");
728  	return;
729        }
730        if (ch->master)
731  	stop_follower(ch);
732        REMOVE_BIT(AFF_FLAGS(ch), AFF_GROUP);
733        add_follower(ch, leader);
734      }
735    }
736  }