ACT_MOVE.C
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:28k
源码类别:

Internet/网络编程

开发平台:

WINDOWS

  1. /***************************************************************************
  2.  *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
  3.  *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
  4.  *                                                                         *
  5.  *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
  6.  *  Chastain, Michael Quan, and Mitchell Tse.                              *
  7.  *                                                                         *
  8.  *  In order to use any part of this Merc Diku Mud, you must comply with   *
  9.  *  both the original Diku license in 'license.doc' as well the Merc       *
  10.  *  license in 'license.txt'.  In particular, you may not remove either of *
  11.  *  these copyright notices.                                               *
  12.  *                                                                         *
  13.  *  Much time and thought has gone into this software and you are          *
  14.  *  benefitting.  We hope that you share your changes too.  What goes      *
  15.  *  around, comes around.                                                  *
  16.  ***************************************************************************/
  17. #if defined(macintosh)
  18. #include <types.h>
  19. #else
  20. #include <sys/types.h>
  21. #endif
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <time.h>
  25. #include "merc.h"
  26. char * const dir_name [] =
  27. {
  28.     "north", "east", "south", "west", "up", "down"
  29. };
  30. const sh_int rev_dir [] =
  31. {
  32.     2, 3, 0, 1, 5, 4
  33. };
  34. const sh_int movement_loss [SECT_MAX] =
  35. {
  36.     1, 2, 2, 3, 4, 6, 4, 1, 6, 10, 6
  37. };
  38. /*
  39.  * Local functions.
  40.  */
  41. int find_door args( ( CHAR_DATA *ch, char *arg ) );
  42. bool has_key args( ( CHAR_DATA *ch, int key ) );
  43. void move_char( CHAR_DATA *ch, int door )
  44. {
  45.     CHAR_DATA *fch;
  46.     CHAR_DATA *fch_next;
  47.     ROOM_INDEX_DATA *in_room;
  48.     ROOM_INDEX_DATA *to_room;
  49.     EXIT_DATA *pexit;
  50.     if ( door < 0 || door > 5 )
  51.     {
  52. bug( "Do_move: bad door %d.", door );
  53. return;
  54.     }
  55.     in_room = ch->in_room;
  56.     /* Here is where racial cities attach to the guilds... */
  57.     if (in_room->vnum == 201 && door == 0)
  58.        {
  59.        static EXIT_DATA racial_exit;
  60.        racial_exit.vnum = race_table[ch->race].city_vnum;
  61.        racial_exit.to_room = get_room_index(racial_exit.vnum);
  62.        pexit = &racial_exit;
  63.        }
  64.     else
  65.        pexit = in_room->exit[door];
  66.     if ( ( pexit   /*= in_room->exit[door]*/ ) == NULL
  67.     ||   ( to_room = pexit->to_room      ) == NULL )
  68.     {
  69. send_to_char( "Alas, you cannot go that way.nr", ch );
  70. return;
  71.     }
  72.     if ( IS_SET(pexit->exit_info, EX_CLOSED)
  73.     &&   !IS_AFFECTED(ch, AFF_PASS_DOOR) )
  74.     {
  75. act( "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR );
  76. return;
  77.     }
  78.     if ( IS_AFFECTED(ch, AFF_CHARM)
  79.     &&   ch->master != NULL
  80.     &&   in_room == ch->master->in_room )
  81.     {
  82. send_to_char( "What?  And leave your beloved master?nr", ch );
  83. return;
  84.     }
  85.     if ( room_is_private( to_room ) )
  86.     {
  87. send_to_char( "That room is private right now.nr", ch );
  88. return;
  89.     }
  90.     if ( !IS_NPC(ch) )
  91.     {
  92. int iClass;
  93. int move;
  94. for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
  95. {
  96.     if ( iClass != ch->class
  97.     &&   to_room->vnum == class_table[iClass].guild )
  98.     {
  99. send_to_char( "You aren't allowed in there.nr", ch );
  100. return;
  101.     }
  102. }
  103. if ( in_room->sector_type == SECT_AIR
  104. ||   to_room->sector_type == SECT_AIR )
  105. {
  106.     if ( !IS_AFFECTED(ch, AFF_FLYING) )
  107.     {
  108. send_to_char( "You can't fly.nr", ch );
  109. return;
  110.     }
  111. }
  112. if ( in_room->sector_type == SECT_WATER_NOSWIM
  113. ||   to_room->sector_type == SECT_WATER_NOSWIM )
  114. {
  115.     OBJ_DATA *obj;
  116.     bool found;
  117.     /*
  118.      * Look for a boat.
  119.      */
  120.     found = FALSE;
  121.     /*
  122.      * Suggestion for flying above water by Sludge
  123.      */
  124.     if ( IS_AFFECTED( ch, AFF_FLYING ) )
  125.         found = TRUE;
  126.     for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
  127.     {
  128. if ( obj->item_type == ITEM_BOAT )
  129. {
  130.     found = TRUE;
  131.     break;
  132. }
  133.     }
  134.     if ( !found )
  135.     {
  136. send_to_char( "You need a boat to go there.nr", ch );
  137. return;
  138.     }
  139. }
  140. move = movement_loss[UMIN(SECT_MAX-1, in_room->sector_type)]
  141.      + movement_loss[UMIN(SECT_MAX-1, to_room->sector_type)]
  142.      ;
  143. if ( ch->move < move )
  144. {
  145.     send_to_char( "You are too exhausted.nr", ch );
  146.     return;
  147. }
  148. WAIT_STATE( ch, 1 );
  149. ch->move -= move;
  150.     }
  151.     if ( !IS_AFFECTED(ch, AFF_SNEAK)
  152.     && ( IS_NPC(ch) || !IS_SET(ch->act, PLR_WIZINVIS) ) )
  153. act( "$n leaves $T.", ch, NULL, dir_name[door], TO_ROOM );
  154.     char_from_room( ch );
  155.     char_to_room( ch, to_room );
  156.     if ( !IS_AFFECTED(ch, AFF_SNEAK)
  157.     && ( IS_NPC(ch) || !IS_SET(ch->act, PLR_WIZINVIS) ) )
  158. act( "$n has arrived.", ch, NULL, NULL, TO_ROOM );
  159.     do_look( ch, "auto" );
  160.     for ( fch = in_room->people; fch != NULL; fch = fch_next )
  161.     {
  162. fch_next = fch->next_in_room;
  163. if ( fch->master == ch && fch->position == POS_STANDING )
  164. {
  165.     act( "You follow $N.", fch, NULL, ch, TO_CHAR );
  166.     move_char( fch, door );
  167. }
  168.     }
  169.     mprog_entry_trigger(ch);
  170.     mprog_greet_trigger(ch);
  171.     return;
  172. }
  173. void do_north( CHAR_DATA *ch, char *argument )
  174. {
  175.     move_char( ch, DIR_NORTH );
  176.     return;
  177. }
  178. void do_east( CHAR_DATA *ch, char *argument )
  179. {
  180.     move_char( ch, DIR_EAST );
  181.     return;
  182. }
  183. void do_south( CHAR_DATA *ch, char *argument )
  184. {
  185.     move_char( ch, DIR_SOUTH );
  186.     return;
  187. }
  188. void do_west( CHAR_DATA *ch, char *argument )
  189. {
  190.     move_char( ch, DIR_WEST );
  191.     return;
  192. }
  193. void do_up( CHAR_DATA *ch, char *argument )
  194. {
  195.     move_char( ch, DIR_UP );
  196.     return;
  197. }
  198. void do_down( CHAR_DATA *ch, char *argument )
  199. {
  200.     move_char( ch, DIR_DOWN );
  201.     return;
  202. }
  203. int find_door( CHAR_DATA *ch, char *arg )
  204. {
  205.     EXIT_DATA *pexit;
  206.     int door;
  207.  if ( !str_cmp( arg, "n" ) || !str_cmp( arg, "north" ) ) door = 0;
  208.     else if ( !str_cmp( arg, "e" ) || !str_cmp( arg, "east"  ) ) door = 1;
  209.     else if ( !str_cmp( arg, "s" ) || !str_cmp( arg, "south" ) ) door = 2;
  210.     else if ( !str_cmp( arg, "w" ) || !str_cmp( arg, "west"  ) ) door = 3;
  211.     else if ( !str_cmp( arg, "u" ) || !str_cmp( arg, "up"    ) ) door = 4;
  212.     else if ( !str_cmp( arg, "d" ) || !str_cmp( arg, "down"  ) ) door = 5;
  213.     else
  214.     {
  215. for ( door = 0; door <= 5; door++ )
  216. {
  217.     if ( ( pexit = ch->in_room->exit[door] ) != NULL
  218.     &&   IS_SET(pexit->exit_info, EX_ISDOOR)
  219.     &&   pexit->keyword != NULL
  220.     &&   is_name( arg, pexit->keyword ) )
  221. return door;
  222. }
  223. act( "I see no $T here.", ch, NULL, arg, TO_CHAR );
  224. return -1;
  225.     }
  226.     if ( ( pexit = ch->in_room->exit[door] ) == NULL )
  227.     {
  228. act( "I see no door $T here.", ch, NULL, arg, TO_CHAR );
  229. return -1;
  230.     }
  231.     if ( !IS_SET(pexit->exit_info, EX_ISDOOR) )
  232.     {
  233. send_to_char( "You can't do that.nr", ch );
  234. return -1;
  235.     }
  236.     return door;
  237. }
  238. void do_open( CHAR_DATA *ch, char *argument )
  239. {
  240.     char arg[MAX_INPUT_LENGTH];
  241.     OBJ_DATA *obj;
  242.     int door;
  243.     one_argument( argument, arg );
  244.     if ( arg[0] == '' )
  245.     {
  246. send_to_char( "Open what?nr", ch );
  247. return;
  248.     }
  249.     if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
  250.     {
  251. /* 'open object' */
  252. if ( obj->item_type != ITEM_CONTAINER )
  253.     { send_to_char( "That's not a container.nr", ch ); return; }
  254. if ( !IS_SET(obj->value[1], CONT_CLOSED) )
  255.     { send_to_char( "It's already open.nr",      ch ); return; }
  256. if ( !IS_SET(obj->value[1], CONT_CLOSEABLE) )
  257.     { send_to_char( "You can't do that.nr",      ch ); return; }
  258. if ( IS_SET(obj->value[1], CONT_LOCKED) )
  259.     { send_to_char( "It's locked.nr",            ch ); return; }
  260. REMOVE_BIT(obj->value[1], CONT_CLOSED);
  261. send_to_char( "Ok.nr", ch );
  262. act( "$n opens $p.", ch, obj, NULL, TO_ROOM );
  263. return;
  264.     }
  265.     if ( ( door = find_door( ch, arg ) ) >= 0 )
  266.     {
  267. /* 'open door' */
  268. ROOM_INDEX_DATA *to_room;
  269. EXIT_DATA *pexit;
  270. EXIT_DATA *pexit_rev;
  271. pexit = ch->in_room->exit[door];
  272. if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
  273.     { send_to_char( "It's already open.nr",      ch ); return; }
  274. if (  IS_SET(pexit->exit_info, EX_LOCKED) )
  275.     { send_to_char( "It's locked.nr",            ch ); return; }
  276. REMOVE_BIT(pexit->exit_info, EX_CLOSED);
  277. act( "$n opens the $d.", ch, NULL, pexit->keyword, TO_ROOM );
  278. send_to_char( "Ok.nr", ch );
  279. /* open the other side */
  280. if ( ( to_room   = pexit->to_room               ) != NULL
  281. &&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
  282. &&   pexit_rev->to_room == ch->in_room )
  283. {
  284.     CHAR_DATA *rch;
  285.     REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED );
  286.     for ( rch = to_room->people; rch != NULL; rch = rch->next_in_room )
  287. act( "The $d opens.", rch, NULL, pexit_rev->keyword, TO_CHAR );
  288. }
  289.     }
  290.     return;
  291. }
  292. void do_close( CHAR_DATA *ch, char *argument )
  293. {
  294.     char arg[MAX_INPUT_LENGTH];
  295.     OBJ_DATA *obj;
  296.     int door;
  297.     one_argument( argument, arg );
  298.     if ( arg[0] == '' )
  299.     {
  300. send_to_char( "Close what?nr", ch );
  301. return;
  302.     }
  303.     if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
  304.     {
  305. /* 'close object' */
  306. if ( obj->item_type != ITEM_CONTAINER )
  307.     { send_to_char( "That's not a container.nr", ch ); return; }
  308. if ( IS_SET(obj->value[1], CONT_CLOSED) )
  309.     { send_to_char( "It's already closed.nr",    ch ); return; }
  310. if ( !IS_SET(obj->value[1], CONT_CLOSEABLE) )
  311.     { send_to_char( "You can't do that.nr",      ch ); return; }
  312. SET_BIT(obj->value[1], CONT_CLOSED);
  313. send_to_char( "Ok.nr", ch );
  314. act( "$n closes $p.", ch, obj, NULL, TO_ROOM );
  315. return;
  316.     }
  317.     if ( ( door = find_door( ch, arg ) ) >= 0 )
  318.     {
  319. /* 'close door' */
  320. ROOM_INDEX_DATA *to_room;
  321. EXIT_DATA *pexit;
  322. EXIT_DATA *pexit_rev;
  323. pexit = ch->in_room->exit[door];
  324. if ( IS_SET(pexit->exit_info, EX_CLOSED) )
  325.     { send_to_char( "It's already closed.nr",    ch ); return; }
  326. SET_BIT(pexit->exit_info, EX_CLOSED);
  327. act( "$n closes the $d.", ch, NULL, pexit->keyword, TO_ROOM );
  328. send_to_char( "Ok.nr", ch );
  329. /* close the other side */
  330. if ( ( to_room   = pexit->to_room               ) != NULL
  331. &&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != 0
  332. &&   pexit_rev->to_room == ch->in_room )
  333. {
  334.     CHAR_DATA *rch;
  335.     SET_BIT( pexit_rev->exit_info, EX_CLOSED );
  336.     for ( rch = to_room->people; rch != NULL; rch = rch->next_in_room )
  337. act( "The $d closes.", rch, NULL, pexit_rev->keyword, TO_CHAR );
  338. }
  339.     }
  340.     return;
  341. }
  342. bool has_key( CHAR_DATA *ch, int key )
  343. {
  344.     OBJ_DATA *obj;
  345.     for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
  346.     {
  347. if ( obj->pIndexData->vnum == key )
  348.     return TRUE;
  349.     }
  350.     return FALSE;
  351. }
  352. void do_lock( CHAR_DATA *ch, char *argument )
  353. {
  354.     char arg[MAX_INPUT_LENGTH];
  355.     OBJ_DATA *obj;
  356.     int door;
  357.     one_argument( argument, arg );
  358.     if ( arg[0] == '' )
  359.     {
  360. send_to_char( "Lock what?nr", ch );
  361. return;
  362.     }
  363.     if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
  364.     {
  365. /* 'lock object' */
  366. if ( obj->item_type != ITEM_CONTAINER )
  367.     { send_to_char( "That's not a container.nr", ch ); return; }
  368. if ( !IS_SET(obj->value[1], CONT_CLOSED) )
  369.     { send_to_char( "It's not closed.nr",        ch ); return; }
  370. if ( obj->value[2] < 0 )
  371.     { send_to_char( "It can't be locked.nr",     ch ); return; }
  372. if ( !has_key( ch, obj->value[2] ) )
  373.     { send_to_char( "You lack the key.nr",       ch ); return; }
  374. if ( IS_SET(obj->value[1], CONT_LOCKED) )
  375.     { send_to_char( "It's already locked.nr",    ch ); return; }
  376. SET_BIT(obj->value[1], CONT_LOCKED);
  377. send_to_char( "*Click*nr", ch );
  378. act( "$n locks $p.", ch, obj, NULL, TO_ROOM );
  379. return;
  380.     }
  381.     if ( ( door = find_door( ch, arg ) ) >= 0 )
  382.     {
  383. /* 'lock door' */
  384. ROOM_INDEX_DATA *to_room;
  385. EXIT_DATA *pexit;
  386. EXIT_DATA *pexit_rev;
  387. pexit = ch->in_room->exit[door];
  388. if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
  389.     { send_to_char( "It's not closed.nr",        ch ); return; }
  390. if ( pexit->key < 0 )
  391.     { send_to_char( "It can't be locked.nr",     ch ); return; }
  392. if ( !has_key( ch, pexit->key) )
  393.     { send_to_char( "You lack the key.nr",       ch ); return; }
  394. if ( IS_SET(pexit->exit_info, EX_LOCKED) )
  395.     { send_to_char( "It's already locked.nr",    ch ); return; }
  396. SET_BIT(pexit->exit_info, EX_LOCKED);
  397. send_to_char( "*Click*nr", ch );
  398. act( "$n locks the $d.", ch, NULL, pexit->keyword, TO_ROOM );
  399. /* lock the other side */
  400. if ( ( to_room   = pexit->to_room               ) != NULL
  401. &&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != 0
  402. &&   pexit_rev->to_room == ch->in_room )
  403. {
  404.     SET_BIT( pexit_rev->exit_info, EX_LOCKED );
  405. }
  406.     }
  407.     return;
  408. }
  409. void do_unlock( CHAR_DATA *ch, char *argument )
  410. {
  411.     char arg[MAX_INPUT_LENGTH];
  412.     OBJ_DATA *obj;
  413.     int door;
  414.     one_argument( argument, arg );
  415.     if ( arg[0] == '' )
  416.     {
  417. send_to_char( "Unlock what?nr", ch );
  418. return;
  419.     }
  420.     if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
  421.     {
  422. /* 'unlock object' */
  423. if ( obj->item_type != ITEM_CONTAINER )
  424.     { send_to_char( "That's not a container.nr", ch ); return; }
  425. if ( !IS_SET(obj->value[1], CONT_CLOSED) )
  426.     { send_to_char( "It's not closed.nr",        ch ); return; }
  427. if ( obj->value[2] < 0 )
  428.     { send_to_char( "It can't be unlocked.nr",   ch ); return; }
  429. if ( !has_key( ch, obj->value[2] ) )
  430.     { send_to_char( "You lack the key.nr",       ch ); return; }
  431. if ( !IS_SET(obj->value[1], CONT_LOCKED) )
  432.     { send_to_char( "It's already unlocked.nr",  ch ); return; }
  433. REMOVE_BIT(obj->value[1], CONT_LOCKED);
  434. send_to_char( "*Click*nr", ch );
  435. act( "$n unlocks $p.", ch, obj, NULL, TO_ROOM );
  436. return;
  437.     }
  438.     if ( ( door = find_door( ch, arg ) ) >= 0 )
  439.     {
  440. /* 'unlock door' */
  441. ROOM_INDEX_DATA *to_room;
  442. EXIT_DATA *pexit;
  443. EXIT_DATA *pexit_rev;
  444. pexit = ch->in_room->exit[door];
  445. if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
  446.     { send_to_char( "It's not closed.nr",        ch ); return; }
  447. if ( pexit->key < 0 )
  448.     { send_to_char( "It can't be unlocked.nr",   ch ); return; }
  449. if ( !has_key( ch, pexit->key) )
  450.     { send_to_char( "You lack the key.nr",       ch ); return; }
  451. if ( !IS_SET(pexit->exit_info, EX_LOCKED) )
  452.     { send_to_char( "It's already unlocked.nr",  ch ); return; }
  453. REMOVE_BIT(pexit->exit_info, EX_LOCKED);
  454. send_to_char( "*Click*nr", ch );
  455. act( "$n unlocks the $d.", ch, NULL, pexit->keyword, TO_ROOM );
  456. /* unlock the other side */
  457. if ( ( to_room   = pexit->to_room               ) != NULL
  458. &&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
  459. &&   pexit_rev->to_room == ch->in_room )
  460. {
  461.     REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
  462. }
  463.     }
  464.     return;
  465. }
  466. void do_pick( CHAR_DATA *ch, char *argument )
  467. {
  468.     char arg[MAX_INPUT_LENGTH];
  469.     CHAR_DATA *gch;
  470.     OBJ_DATA *obj;
  471.     int door;
  472.     one_argument( argument, arg );
  473.     if ( arg[0] == '' )
  474.     {
  475. send_to_char( "Pick what?nr", ch );
  476. return;
  477.     }
  478.     WAIT_STATE( ch, skill_table[gsn_pick_lock].beats );
  479.     /* look for guards */
  480.     for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
  481.     {
  482. if ( IS_NPC(gch) && IS_AWAKE(gch) && ch->level + 5 < gch->level )
  483. {
  484.     act( "$N is standing too close to the lock.",
  485. ch, NULL, gch, TO_CHAR );
  486.     return;
  487. }
  488.     }
  489.     if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_pick_lock] )
  490.     {
  491. send_to_char( "You failed.nr", ch);
  492. return;
  493.     }
  494.     if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
  495.     {
  496. /* 'pick object' */
  497. if ( obj->item_type != ITEM_CONTAINER )
  498.     { send_to_char( "That's not a container.nr", ch ); return; }
  499. if ( !IS_SET(obj->value[1], CONT_CLOSED) )
  500.     { send_to_char( "It's not closed.nr",        ch ); return; }
  501. if ( obj->value[2] < 0 )
  502.     { send_to_char( "It can't be unlocked.nr",   ch ); return; }
  503. if ( !IS_SET(obj->value[1], CONT_LOCKED) )
  504.     { send_to_char( "It's already unlocked.nr",  ch ); return; }
  505. if ( IS_SET(obj->value[1], CONT_PICKPROOF) )
  506.     { send_to_char( "You failed.nr",             ch ); return; }
  507. REMOVE_BIT(obj->value[1], CONT_LOCKED);
  508. send_to_char( "*Click*nr", ch );
  509. act( "$n picks $p.", ch, obj, NULL, TO_ROOM );
  510. return;
  511.     }
  512.     if ( ( door = find_door( ch, arg ) ) >= 0 )
  513.     {
  514. /* 'pick door' */
  515. ROOM_INDEX_DATA *to_room;
  516. EXIT_DATA *pexit;
  517. EXIT_DATA *pexit_rev;
  518. pexit = ch->in_room->exit[door];
  519. if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
  520.     { send_to_char( "It's not closed.nr",        ch ); return; }
  521. if ( pexit->key < 0 )
  522.     { send_to_char( "It can't be picked.nr",     ch ); return; }
  523. if ( !IS_SET(pexit->exit_info, EX_LOCKED) )
  524.     { send_to_char( "It's already unlocked.nr",  ch ); return; }
  525. if ( IS_SET(pexit->exit_info, EX_PICKPROOF) )
  526.     { send_to_char( "You failed.nr",             ch ); return; }
  527. REMOVE_BIT(pexit->exit_info, EX_LOCKED);
  528. send_to_char( "*Click*nr", ch );
  529. act( "$n picks the $d.", ch, NULL, pexit->keyword, TO_ROOM );
  530. /* pick the other side */
  531. if ( ( to_room   = pexit->to_room               ) != NULL
  532. &&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
  533. &&   pexit_rev->to_room == ch->in_room )
  534. {
  535.     REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
  536. }
  537.     }
  538.     return;
  539. }
  540. void do_stand( CHAR_DATA *ch, char *argument )
  541. {
  542.     switch ( ch->position )
  543.     {
  544.     case POS_SLEEPING:
  545. if ( IS_AFFECTED(ch, AFF_SLEEP) )
  546.     { send_to_char( "You can't wake up!nr", ch ); return; }
  547. send_to_char( "You wake and stand up.nr", ch );
  548. act( "$n wakes and stands up.", ch, NULL, NULL, TO_ROOM );
  549. ch->position = POS_STANDING;
  550. break;
  551.     case POS_RESTING:
  552. send_to_char( "You stand up.nr", ch );
  553. act( "$n stands up.", ch, NULL, NULL, TO_ROOM );
  554. ch->position = POS_STANDING;
  555. break;
  556.     case POS_STANDING:
  557. send_to_char( "You are already standing.nr", ch );
  558. break;
  559.     case POS_FIGHTING:
  560. send_to_char( "You are already fighting!nr", ch );
  561. break;
  562.     }
  563.     return;
  564. }
  565. void do_rest( CHAR_DATA *ch, char *argument )
  566. {
  567.     switch ( ch->position )
  568.     {
  569.     case POS_SLEEPING:
  570. send_to_char( "You are already sleeping.nr", ch );
  571. break;
  572.     case POS_RESTING:
  573. send_to_char( "You are already resting.nr", ch );
  574. break;
  575.     case POS_STANDING:
  576. send_to_char( "You rest.nr", ch );
  577. act( "$n rests.", ch, NULL, NULL, TO_ROOM );
  578. ch->position = POS_RESTING;
  579. break;
  580.     case POS_FIGHTING:
  581. send_to_char( "You are already fighting!nr", ch );
  582. break;
  583.     }
  584.     return;
  585. }
  586. void do_sleep( CHAR_DATA *ch, char *argument )
  587. {
  588.     switch ( ch->position )
  589.     {
  590.     case POS_SLEEPING:
  591. send_to_char( "You are already sleeping.nr", ch );
  592. break;
  593.     case POS_RESTING:
  594.     case POS_STANDING: 
  595. send_to_char( "You sleep.nr", ch );
  596. act( "$n sleeps.", ch, NULL, NULL, TO_ROOM );
  597. ch->position = POS_SLEEPING;
  598. break;
  599.     case POS_FIGHTING:
  600. send_to_char( "You are already fighting!nr", ch );
  601. break;
  602.     }
  603.     return;
  604. }
  605. void do_wake( CHAR_DATA *ch, char *argument )
  606. {
  607.     char arg[MAX_INPUT_LENGTH];
  608.     CHAR_DATA *victim;
  609.     one_argument( argument, arg );
  610.     if ( arg[0] == '' )
  611. { do_stand( ch, argument ); return; }
  612.     if ( !IS_AWAKE(ch) )
  613. { send_to_char( "You are asleep yourself!nr",       ch ); return; }
  614.     if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  615. { send_to_char( "They aren't here.nr",              ch ); return; }
  616.     if ( IS_AWAKE(victim) )
  617. { act( "$N is already awake.", ch, NULL, victim, TO_CHAR ); return; }
  618.     if ( IS_AFFECTED(victim, AFF_SLEEP) )
  619. { act( "You can't wake $M!",   ch, NULL, victim, TO_CHAR );  return; }
  620.     act( "You wake $M.", ch, NULL, victim, TO_CHAR );
  621.     act( "$n wakes you.", ch, NULL, victim, TO_VICT );
  622.     victim->position = POS_STANDING;
  623.     return;
  624. }
  625. void do_sneak( CHAR_DATA *ch, char *argument )
  626. {
  627.     AFFECT_DATA af;
  628.     send_to_char( "You attempt to move silently.nr", ch );
  629.     affect_strip( ch, gsn_sneak );
  630.     if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_sneak] )
  631.     {
  632. af.type      = gsn_sneak;
  633. af.duration  = ch->level;
  634. af.location  = APPLY_NONE;
  635. af.modifier  = 0;
  636. af.bitvector = AFF_SNEAK;
  637. affect_to_char( ch, &af );
  638.     }
  639.     return;
  640. }
  641. void do_hide( CHAR_DATA *ch, char *argument )
  642. {
  643.     send_to_char( "You attempt to hide.nr", ch );
  644.     if ( IS_AFFECTED(ch, AFF_HIDE) )
  645. REMOVE_BIT(ch->affected_by, AFF_HIDE);
  646.     if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_hide] )
  647. SET_BIT(ch->affected_by, AFF_HIDE);
  648.     return;
  649. }
  650. /*
  651.  * Contributed by Alander.
  652.  */
  653. void do_visible( CHAR_DATA *ch, char *argument )
  654. {
  655.     affect_strip ( ch, gsn_invis );
  656.     affect_strip ( ch, gsn_mass_invis );
  657.     affect_strip ( ch, gsn_sneak );
  658.     REMOVE_BIT   ( ch->affected_by, AFF_HIDE );
  659.     REMOVE_BIT   ( ch->affected_by, AFF_INVISIBLE );
  660.     REMOVE_BIT   ( ch->affected_by, AFF_SNEAK );
  661.     send_to_char( "Ok.nr", ch );
  662.     return;
  663. }
  664. void do_recall( CHAR_DATA *ch, char *argument )
  665. {
  666.     char buf[MAX_STRING_LENGTH];
  667.     CHAR_DATA *victim;
  668.     ROOM_INDEX_DATA *location;
  669.   
  670.     act( "$n prays for transportation!", ch, 0, 0, TO_ROOM );
  671. //    if ( ( location = get_room_index( ROOM_VNUM_TEMPLE ) ) == NULL )
  672.     if ( ( location = get_room_index( race_table[ch->race].city_temple ) ) == NULL )
  673.     {
  674. send_to_char( "You are completely lost.nr", ch );
  675. return;
  676.     }
  677.     if ( ch->in_room == location )
  678. return;
  679.     if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
  680.     ||   IS_AFFECTED(ch, AFF_CURSE) )
  681.     {
  682. send_to_char( "God has forsaken you.nr", ch );
  683. return;
  684.     }
  685.     if ( ( victim = ch->fighting ) != NULL )
  686.     {
  687. int lose;
  688. if ( number_bits( 1 ) == 0 )
  689. {
  690.     WAIT_STATE( ch, 4 );
  691.     lose = (ch->desc != NULL) ? 50 : 100;
  692.     gain_exp( ch, 0 - lose );
  693.     sprintf( buf, "You failed!  You lose %d exps.nr", lose );
  694.     send_to_char( buf, ch );
  695.     return;
  696. }
  697. lose = (ch->desc != NULL) ? 100 : 200;
  698. gain_exp( ch, 0 - lose );
  699. sprintf( buf, "You recall from combat!  You lose %d exps.nr", lose );
  700. send_to_char( buf, ch );
  701. stop_fighting( ch, TRUE );
  702.     }
  703.     ch->move /= 2;
  704.     act( "$n disappears.", ch, NULL, NULL, TO_ROOM );
  705.     char_from_room( ch );
  706.     char_to_room( ch, location );
  707.     act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
  708.     do_look( ch, "auto" );
  709.     return;
  710. }
  711. /*    { "identify", do_identify, POS_STANDING,  0,  LOG_NORMAL   }, */
  712. #define MOB_VNUM_SAGE    8911
  713. void do_identify( CHAR_DATA *ch, char *argument )
  714. {
  715.     OBJ_DATA *obj;
  716.     CHAR_DATA *rch;
  717.     if ( ( obj = get_obj_carry( ch, argument ) ) == NULL )
  718.     {
  719.        send_to_char( "You are not carrying that.nr", ch );
  720.        return;
  721.     }
  722.     for ( rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room )
  723.        if (IS_NPC(rch) && rch->pIndexData->vnum == MOB_VNUM_SAGE)
  724.           break;
  725.     if (!rch)
  726.     {
  727.        send_to_char("No one here seems to know much about that.nr", ch);
  728.        return;
  729.     }
  730.     if (IS_IMMORTAL(ch))
  731.        act( "$n cackles and comps you!nr", rch, obj, ch, TO_VICT );
  732.     else if (ch->gold < obj->level * 100 + 50)
  733.        {
  734.        act( "$n resumes tossing bones without looking at $p.",
  735.              rch, obj, 0, TO_ROOM );
  736.        return;
  737.        }
  738.     else
  739.        {
  740.        ch->gold -= obj->level * 100 + 50;
  741.        send_to_char("Your purse feels lighter.nr", ch);
  742.        }
  743.     act( "$n fondles $p and tosses some chicken bones to the ground.",
  744.        rch, obj, 0, TO_ROOM );
  745.     spell_identify( 0, 0, ch, obj );
  746. }
  747. void do_train( CHAR_DATA *ch, char *argument )
  748. {
  749.     char buf[MAX_STRING_LENGTH];
  750.     CHAR_DATA *mob;
  751.     int hp_gain = 0;
  752.     int mana_gain = 0;
  753.     sh_int *pAbility;
  754.     char *pOutput;
  755.     int cost;
  756.     if ( IS_NPC(ch) )
  757. return;
  758.     /*
  759.      * Check for trainer.
  760.      */
  761.     for ( mob = ch->in_room->people; mob; mob = mob->next_in_room )
  762.     {
  763. if ( IS_NPC(mob) && IS_SET(mob->act, ACT_TRAIN) )
  764.     break;
  765.     }
  766.     if ( mob == NULL )
  767.     {
  768. send_to_char( "You can't do that here.nr", ch );
  769. return;
  770.     }
  771.     if ( argument[0] == '' )
  772.     {
  773. sprintf( buf, "You have %d practice sessions.nr", ch->practice );
  774. send_to_char( buf, ch );
  775. argument = "foo";
  776.     }
  777.     cost = 5;
  778.     if ( !str_cmp( argument, "str" ) )
  779.     {
  780. if ( class_table[ch->class].attr_prime == APPLY_STR )
  781.     cost    = 3;
  782. pAbility    = &ch->pcdata->perm_str;
  783. pOutput     = "strength";
  784.     }
  785.     else if ( !str_cmp( argument, "int" ) )
  786.     {
  787. if ( class_table[ch->class].attr_prime == APPLY_INT )
  788.     cost    = 3;
  789. pAbility    = &ch->pcdata->perm_int;
  790. pOutput     = "intelligence";
  791.     }
  792.     else if ( !str_cmp( argument, "wis" ) )
  793.     {
  794. if ( class_table[ch->class].attr_prime == APPLY_WIS )
  795.     cost    = 3;
  796. pAbility    = &ch->pcdata->perm_wis;
  797. pOutput     = "wisdom";
  798.     }
  799.     else if ( !str_cmp( argument, "dex" ) )
  800.     {
  801. if ( class_table[ch->class].attr_prime == APPLY_DEX )
  802.     cost    = 3;
  803. pAbility    = &ch->pcdata->perm_dex;
  804. pOutput     = "dexterity";
  805.     }
  806.     else if ( !str_cmp( argument, "con" ) )
  807.     {
  808. if ( class_table[ch->class].attr_prime == APPLY_CON )
  809.     cost    = 3;
  810. pAbility    = &ch->pcdata->perm_con;
  811. pOutput     = "constitution";
  812.     }
  813.     else if ( !str_cmp( argument, "hp" ) )
  814.       {
  815.         pAbility = &ch->max_hit;
  816.         pOutput = "number of hit points";
  817.         cost = 1;    /* this is pracs per "train hp" */
  818.         hp_gain = 2; /* this is hp gained per "train hp" */
  819.       }
  820.  
  821.     else if ( !str_cmp( argument, "mana" ) )
  822.       {
  823.         pAbility = &ch->max_mana;
  824.         pOutput = "amount of mana";
  825.         cost =1;
  826.         mana_gain = 3;
  827.       }
  828.     else
  829.     {
  830.    strcpy( buf, "You can train: hp mana" );
  831. if ( ch->pcdata->perm_str < 18 ) strcat( buf, " str" );
  832. if ( ch->pcdata->perm_int < 18 ) strcat( buf, " int" );
  833. if ( ch->pcdata->perm_wis < 18 ) strcat( buf, " wis" );
  834. if ( ch->pcdata->perm_dex < 18 ) strcat( buf, " dex" );
  835. if ( ch->pcdata->perm_con < 18 ) strcat( buf, " con" );
  836. // if ( buf[strlen(buf)-1] != ':' )
  837. // {
  838.     strcat( buf, ".nr" );
  839.     send_to_char( buf, ch );
  840. // }
  841. // else
  842. // {
  843. //     /*
  844. //      * This message dedicated to Jordan ... you big stud!
  845. //      */
  846. //     act( "You have nothing left to train, you $T!",
  847. // ch, NULL,
  848. // ch->sex == SEX_MALE   ? "big stud" :
  849. // ch->sex == SEX_FEMALE ? "hot babe" :
  850. // "wild thing",
  851. // TO_CHAR );
  852. // }
  853. return;
  854.     }
  855.     if ( !str_cmp( argument, "hp" ) )
  856.       {
  857.       
  858.         if ( cost > ch->practice )
  859.   {
  860.             send_to_char( "You don't have enough practices.nr", ch );
  861.             return;
  862.   }
  863.              ch->practice        -= cost;
  864.              *pAbility           += hp_gain;
  865.              act( "Your $T increases!", ch, NULL, pOutput, TO_CHAR );
  866.              act( "$n's $T increases!", ch, NULL, pOutput, TO_ROOM );
  867.              return;
  868.       }
  869. if ( !str_cmp( argument, "mana" ) )
  870.   {
  871.         if ( cost > ch->practice )
  872.   {
  873.             send_to_char( "You don't have enough practices.nr", ch );
  874.             return;
  875.   }
  876.              ch->practice        -= cost;
  877.              *pAbility           += mana_gain;
  878.              act( "Your $T increases!", ch, NULL, pOutput, TO_CHAR );
  879.              act( "$n's $T increases!", ch, NULL, pOutput, TO_ROOM );
  880.              return;
  881.       }
  882.     if ( *pAbility >= 18 )
  883.     {
  884. act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
  885. return;
  886.     }
  887.     if ( cost > ch->practice )
  888.     {
  889. send_to_char( "You don't have enough practices.nr", ch );
  890. return;
  891.     }
  892.     ch->practice -= cost;
  893.     *pAbility += 1;
  894.     act( "Your $T increases!", ch, NULL, pOutput, TO_CHAR );
  895.     act( "$n's $T increases!", ch, NULL, pOutput, TO_ROOM );
  896.     return;
  897. }