/ circle3.1 / src / act.item.c
act.item.c
   1  /* ************************************************************************
   2  *   File: act.item.c                                    Part of CircleMUD *
   3  *  Usage: object handling routines -- get/drop and container handling     *
   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 "constants.h"
  23  
  24  /* extern variables */
  25  extern room_rnum donation_room_1;
  26  #if 0
  27  extern room_rnum donation_room_2;  /* uncomment if needed! */
  28  extern room_rnum donation_room_3;  /* uncomment if needed! */
  29  #endif
  30  
  31  /* local functions */
  32  int can_take_obj(struct char_data *ch, struct obj_data *obj);
  33  void get_check_money(struct char_data *ch, struct obj_data *obj);
  34  int perform_get_from_room(struct char_data *ch, struct obj_data *obj);
  35  void get_from_room(struct char_data *ch, char *arg, int amount);
  36  void perform_give_gold(struct char_data *ch, struct char_data *vict, int amount);
  37  void perform_give(struct char_data *ch, struct char_data *vict, struct obj_data *obj);
  38  int perform_drop(struct char_data *ch, struct obj_data *obj, byte mode, const char *sname, room_rnum RDR);
  39  void perform_drop_gold(struct char_data *ch, int amount, byte mode, room_rnum RDR);
  40  struct char_data *give_find_vict(struct char_data *ch, char *arg);
  41  void weight_change_object(struct obj_data *obj, int weight);
  42  void perform_put(struct char_data *ch, struct obj_data *obj, struct obj_data *cont);
  43  void name_from_drinkcon(struct obj_data *obj);
  44  void get_from_container(struct char_data *ch, struct obj_data *cont, char *arg, int mode, int amount);
  45  void name_to_drinkcon(struct obj_data *obj, int type);
  46  void wear_message(struct char_data *ch, struct obj_data *obj, int where);
  47  void perform_wear(struct char_data *ch, struct obj_data *obj, int where);
  48  int find_eq_pos(struct char_data *ch, struct obj_data *obj, char *arg);
  49  void perform_get_from_container(struct char_data *ch, struct obj_data *obj, struct obj_data *cont, int mode);
  50  void perform_remove(struct char_data *ch, int pos);
  51  ACMD(do_remove);
  52  ACMD(do_put);
  53  ACMD(do_get);
  54  ACMD(do_drop);
  55  ACMD(do_give);
  56  ACMD(do_drink);
  57  ACMD(do_eat);
  58  ACMD(do_pour);
  59  ACMD(do_wear);
  60  ACMD(do_wield);
  61  ACMD(do_grab);
  62  
  63  
  64  void perform_put(struct char_data *ch, struct obj_data *obj,
  65  		      struct obj_data *cont)
  66  {
  67    if (GET_OBJ_WEIGHT(cont) + GET_OBJ_WEIGHT(obj) > GET_OBJ_VAL(cont, 0))
  68      act("$p won't fit in $P.", FALSE, ch, obj, cont, TO_CHAR);
  69    else if (OBJ_FLAGGED(obj, ITEM_NODROP) && IN_ROOM(cont) != NOWHERE)
  70      act("You can't get $p out of your hand.", FALSE, ch, obj, NULL, TO_CHAR);
  71    else {
  72      obj_from_char(obj);
  73      obj_to_obj(obj, cont);
  74  
  75      act("$n puts $p in $P.", TRUE, ch, obj, cont, TO_ROOM);
  76  
  77      /* Yes, I realize this is strange until we have auto-equip on rent. -gg */
  78      if (OBJ_FLAGGED(obj, ITEM_NODROP) && !OBJ_FLAGGED(cont, ITEM_NODROP)) {
  79        SET_BIT(GET_OBJ_EXTRA(cont), ITEM_NODROP);
  80        act("You get a strange feeling as you put $p in $P.", FALSE,
  81                  ch, obj, cont, TO_CHAR);
  82      } else
  83        act("You put $p in $P.", FALSE, ch, obj, cont, TO_CHAR);
  84    }
  85  }
  86  
  87  
  88  /* The following put modes are supported by the code below:
  89  
  90  	1) put <object> <container>
  91  	2) put all.<object> <container>
  92  	3) put all <container>
  93  
  94  	<container> must be in inventory or on ground.
  95  	all objects to be put into container must be in inventory.
  96  */
  97  
  98  ACMD(do_put)
  99  {
 100    char arg1[MAX_INPUT_LENGTH];
 101    char arg2[MAX_INPUT_LENGTH];
 102    char arg3[MAX_INPUT_LENGTH];
 103    struct obj_data *obj, *next_obj, *cont;
 104    struct char_data *tmp_char;
 105    int obj_dotmode, cont_dotmode, found = 0, howmany = 1;
 106    char *theobj, *thecont;
 107  
 108    one_argument(two_arguments(argument, arg1, arg2), arg3);	/* three_arguments */
 109  
 110    if (*arg3 && is_number(arg1)) {
 111      howmany = atoi(arg1);
 112      theobj = arg2;
 113      thecont = arg3;
 114    } else {
 115      theobj = arg1;
 116      thecont = arg2;
 117    }
 118    obj_dotmode = find_all_dots(theobj);
 119    cont_dotmode = find_all_dots(thecont);
 120  
 121    if (!*theobj)
 122      send_to_char(ch, "Put what in what?\r\n");
 123    else if (cont_dotmode != FIND_INDIV)
 124      send_to_char(ch, "You can only put things into one container at a time.\r\n");
 125    else if (!*thecont) {
 126      send_to_char(ch, "What do you want to put %s in?\r\n", obj_dotmode == FIND_INDIV ? "it" : "them");
 127    } else {
 128      generic_find(thecont, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &tmp_char, &cont);
 129      if (!cont)
 130        send_to_char(ch, "You don't see %s %s here.\r\n", AN(thecont), thecont);
 131      else if (GET_OBJ_TYPE(cont) != ITEM_CONTAINER)
 132        act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
 133      else if (OBJVAL_FLAGGED(cont, CONT_CLOSED))
 134        send_to_char(ch, "You'd better open it first!\r\n");
 135      else {
 136        if (obj_dotmode == FIND_INDIV) {	/* put <obj> <container> */
 137  	if (!(obj = get_obj_in_list_vis(ch, theobj, NULL, ch->carrying)))
 138  	  send_to_char(ch, "You aren't carrying %s %s.\r\n", AN(theobj), theobj);
 139  	else if (obj == cont && howmany == 1)
 140  	  send_to_char(ch, "You attempt to fold it into itself, but fail.\r\n");
 141  	else {
 142  	  while (obj && howmany) {
 143  	    next_obj = obj->next_content;
 144              if (obj != cont) {
 145                howmany--;
 146  	      perform_put(ch, obj, cont);
 147              }
 148  	    obj = get_obj_in_list_vis(ch, theobj, NULL, next_obj);
 149  	  }
 150  	}
 151        } else {
 152  	for (obj = ch->carrying; obj; obj = next_obj) {
 153  	  next_obj = obj->next_content;
 154  	  if (obj != cont && CAN_SEE_OBJ(ch, obj) &&
 155  	      (obj_dotmode == FIND_ALL || isname(theobj, obj->name))) {
 156  	    found = 1;
 157  	    perform_put(ch, obj, cont);
 158  	  }
 159  	}
 160  	if (!found) {
 161  	  if (obj_dotmode == FIND_ALL)
 162  	    send_to_char(ch, "You don't seem to have anything to put in it.\r\n");
 163  	  else
 164  	    send_to_char(ch, "You don't seem to have any %ss.\r\n", theobj);
 165  	}
 166        }
 167      }
 168    }
 169  }
 170  
 171  
 172  
 173  int can_take_obj(struct char_data *ch, struct obj_data *obj)
 174  {
 175    if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) {
 176      act("$p: you can't carry that many items.", FALSE, ch, obj, 0, TO_CHAR);
 177      return (0);
 178    } else if ((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(ch)) {
 179      act("$p: you can't carry that much weight.", FALSE, ch, obj, 0, TO_CHAR);
 180      return (0);
 181    } else if (!(CAN_WEAR(obj, ITEM_WEAR_TAKE))) {
 182      act("$p: you can't take that!", FALSE, ch, obj, 0, TO_CHAR);
 183      return (0);
 184    }
 185    return (1);
 186  }
 187  
 188  
 189  void get_check_money(struct char_data *ch, struct obj_data *obj)
 190  {
 191    int value = GET_OBJ_VAL(obj, 0);
 192  
 193    if (GET_OBJ_TYPE(obj) != ITEM_MONEY || value <= 0)
 194      return;
 195  
 196    extract_obj(obj);
 197  
 198    GET_GOLD(ch) += value;
 199  
 200    if (value == 1)
 201      send_to_char(ch, "There was 1 coin.\r\n");
 202    else
 203      send_to_char(ch, "There were %d coins.\r\n", value);
 204  }
 205  
 206  
 207  void perform_get_from_container(struct char_data *ch, struct obj_data *obj,
 208  				     struct obj_data *cont, int mode)
 209  {
 210    if (mode == FIND_OBJ_INV || can_take_obj(ch, obj)) {
 211      if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch))
 212        act("$p: you can't hold any more items.", FALSE, ch, obj, 0, TO_CHAR);
 213      else {
 214        obj_from_obj(obj);
 215        obj_to_char(obj, ch);
 216        act("You get $p from $P.", FALSE, ch, obj, cont, TO_CHAR);
 217        act("$n gets $p from $P.", TRUE, ch, obj, cont, TO_ROOM);
 218        get_check_money(ch, obj);
 219      }
 220    }
 221  }
 222  
 223  
 224  void get_from_container(struct char_data *ch, struct obj_data *cont,
 225  			     char *arg, int mode, int howmany)
 226  {
 227    struct obj_data *obj, *next_obj;
 228    int obj_dotmode, found = 0;
 229  
 230    obj_dotmode = find_all_dots(arg);
 231  
 232    if (OBJVAL_FLAGGED(cont, CONT_CLOSED))
 233      act("$p is closed.", FALSE, ch, cont, 0, TO_CHAR);
 234    else if (obj_dotmode == FIND_INDIV) {
 235      if (!(obj = get_obj_in_list_vis(ch, arg, NULL, cont->contains))) {
 236        char buf[MAX_STRING_LENGTH];
 237  
 238        snprintf(buf, sizeof(buf), "There doesn't seem to be %s %s in $p.", AN(arg), arg);
 239        act(buf, FALSE, ch, cont, 0, TO_CHAR);
 240      } else {
 241        struct obj_data *obj_next;
 242        while (obj && howmany--) {
 243          obj_next = obj->next_content;
 244          perform_get_from_container(ch, obj, cont, mode);
 245          obj = get_obj_in_list_vis(ch, arg, NULL, obj_next);
 246        }
 247      }
 248    } else {
 249      if (obj_dotmode == FIND_ALLDOT && !*arg) {
 250        send_to_char(ch, "Get all of what?\r\n");
 251        return;
 252      }
 253      for (obj = cont->contains; obj; obj = next_obj) {
 254        next_obj = obj->next_content;
 255        if (CAN_SEE_OBJ(ch, obj) &&
 256  	  (obj_dotmode == FIND_ALL || isname(arg, obj->name))) {
 257  	found = 1;
 258  	perform_get_from_container(ch, obj, cont, mode);
 259        }
 260      }
 261      if (!found) {
 262        if (obj_dotmode == FIND_ALL)
 263  	act("$p seems to be empty.", FALSE, ch, cont, 0, TO_CHAR);
 264        else {
 265          char buf[MAX_STRING_LENGTH];
 266  
 267  	snprintf(buf, sizeof(buf), "You can't seem to find any %ss in $p.", arg);
 268  	act(buf, FALSE, ch, cont, 0, TO_CHAR);
 269        }
 270      }
 271    }
 272  }
 273  
 274  
 275  int perform_get_from_room(struct char_data *ch, struct obj_data *obj)
 276  {
 277    if (can_take_obj(ch, obj)) {
 278      obj_from_room(obj);
 279      obj_to_char(obj, ch);
 280      act("You get $p.", FALSE, ch, obj, 0, TO_CHAR);
 281      act("$n gets $p.", TRUE, ch, obj, 0, TO_ROOM);
 282      get_check_money(ch, obj);
 283      return (1);
 284    }
 285    return (0);
 286  }
 287  
 288  
 289  void get_from_room(struct char_data *ch, char *arg, int howmany)
 290  {
 291    struct obj_data *obj, *next_obj;
 292    int dotmode, found = 0;
 293  
 294    dotmode = find_all_dots(arg);
 295  
 296    if (dotmode == FIND_INDIV) {
 297      if (!(obj = get_obj_in_list_vis(ch, arg, NULL, world[IN_ROOM(ch)].contents)))
 298        send_to_char(ch, "You don't see %s %s here.\r\n", AN(arg), arg);
 299      else {
 300        struct obj_data *obj_next;
 301        while(obj && howmany--) {
 302  	obj_next = obj->next_content;
 303          perform_get_from_room(ch, obj);
 304          obj = get_obj_in_list_vis(ch, arg, NULL, obj_next);
 305        }
 306      }
 307    } else {
 308      if (dotmode == FIND_ALLDOT && !*arg) {
 309        send_to_char(ch, "Get all of what?\r\n");
 310        return;
 311      }
 312      for (obj = world[IN_ROOM(ch)].contents; obj; obj = next_obj) {
 313        next_obj = obj->next_content;
 314        if (CAN_SEE_OBJ(ch, obj) &&
 315  	  (dotmode == FIND_ALL || isname(arg, obj->name))) {
 316  	found = 1;
 317  	perform_get_from_room(ch, obj);
 318        }
 319      }
 320      if (!found) {
 321        if (dotmode == FIND_ALL)
 322  	send_to_char(ch, "There doesn't seem to be anything here.\r\n");
 323        else
 324  	send_to_char(ch, "You don't see any %ss here.\r\n", arg);
 325      }
 326    }
 327  }
 328  
 329  
 330  
 331  ACMD(do_get)
 332  {
 333    char arg1[MAX_INPUT_LENGTH];
 334    char arg2[MAX_INPUT_LENGTH];
 335    char arg3[MAX_INPUT_LENGTH];
 336  
 337    int cont_dotmode, found = 0, mode;
 338    struct obj_data *cont;
 339    struct char_data *tmp_char;
 340  
 341    one_argument(two_arguments(argument, arg1, arg2), arg3);	/* three_arguments */
 342  
 343    if (!*arg1)
 344      send_to_char(ch, "Get what?\r\n");
 345    else if (!*arg2)
 346      get_from_room(ch, arg1, 1);
 347    else if (is_number(arg1) && !*arg3)
 348      get_from_room(ch, arg2, atoi(arg1));
 349    else {
 350      int amount = 1;
 351      if (is_number(arg1)) {
 352        amount = atoi(arg1);
 353        strcpy(arg1, arg2);	/* strcpy: OK (sizeof: arg1 == arg2) */
 354        strcpy(arg2, arg3);	/* strcpy: OK (sizeof: arg2 == arg3) */
 355      }
 356      cont_dotmode = find_all_dots(arg2);
 357      if (cont_dotmode == FIND_INDIV) {
 358        mode = generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &tmp_char, &cont);
 359        if (!cont)
 360  	send_to_char(ch, "You don't have %s %s.\r\n", AN(arg2), arg2);
 361        else if (GET_OBJ_TYPE(cont) != ITEM_CONTAINER)
 362  	act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
 363        else
 364  	get_from_container(ch, cont, arg1, mode, amount);
 365      } else {
 366        if (cont_dotmode == FIND_ALLDOT && !*arg2) {
 367  	send_to_char(ch, "Get from all of what?\r\n");
 368  	return;
 369        }
 370        for (cont = ch->carrying; cont; cont = cont->next_content)
 371  	if (CAN_SEE_OBJ(ch, cont) &&
 372  	    (cont_dotmode == FIND_ALL || isname(arg2, cont->name))) {
 373  	  if (GET_OBJ_TYPE(cont) == ITEM_CONTAINER) {
 374  	    found = 1;
 375  	    get_from_container(ch, cont, arg1, FIND_OBJ_INV, amount);
 376  	  } else if (cont_dotmode == FIND_ALLDOT) {
 377  	    found = 1;
 378  	    act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
 379  	  }
 380  	}
 381        for (cont = world[IN_ROOM(ch)].contents; cont; cont = cont->next_content)
 382  	if (CAN_SEE_OBJ(ch, cont) &&
 383  	    (cont_dotmode == FIND_ALL || isname(arg2, cont->name))) {
 384  	  if (GET_OBJ_TYPE(cont) == ITEM_CONTAINER) {
 385  	    get_from_container(ch, cont, arg1, FIND_OBJ_ROOM, amount);
 386  	    found = 1;
 387  	  } else if (cont_dotmode == FIND_ALLDOT) {
 388  	    act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
 389  	    found = 1;
 390  	  }
 391  	}
 392        if (!found) {
 393  	if (cont_dotmode == FIND_ALL)
 394  	  send_to_char(ch, "You can't seem to find any containers.\r\n");
 395  	else
 396  	  send_to_char(ch, "You can't seem to find any %ss here.\r\n", arg2);
 397        }
 398      }
 399    }
 400  }
 401  
 402  
 403  void perform_drop_gold(struct char_data *ch, int amount,
 404  		            byte mode, room_rnum RDR)
 405  {
 406    struct obj_data *obj;
 407  
 408    if (amount <= 0)
 409      send_to_char(ch, "Heh heh heh.. we are jolly funny today, eh?\r\n");
 410    else if (GET_GOLD(ch) < amount)
 411      send_to_char(ch, "You don't have that many coins!\r\n");
 412    else {
 413      if (mode != SCMD_JUNK) {
 414        WAIT_STATE(ch, PULSE_VIOLENCE);	/* to prevent coin-bombing */
 415        obj = create_money(amount);
 416        if (mode == SCMD_DONATE) {
 417  	send_to_char(ch, "You throw some gold into the air where it disappears in a puff of smoke!\r\n");
 418  	act("$n throws some gold into the air where it disappears in a puff of smoke!",
 419  	    FALSE, ch, 0, 0, TO_ROOM);
 420  	obj_to_room(obj, RDR);
 421  	act("$p suddenly appears in a puff of orange smoke!", 0, 0, obj, 0, TO_ROOM);
 422        } else {
 423          char buf[MAX_STRING_LENGTH];
 424  
 425  	snprintf(buf, sizeof(buf), "$n drops %s.", money_desc(amount));
 426  	act(buf, TRUE, ch, 0, 0, TO_ROOM);
 427  
 428  	send_to_char(ch, "You drop some gold.\r\n");
 429  	obj_to_room(obj, IN_ROOM(ch));
 430        }
 431      } else {
 432        char buf[MAX_STRING_LENGTH];
 433  
 434        snprintf(buf, sizeof(buf), "$n drops %s which disappears in a puff of smoke!", money_desc(amount));
 435        act(buf, FALSE, ch, 0, 0, TO_ROOM);
 436  
 437        send_to_char(ch, "You drop some gold which disappears in a puff of smoke!\r\n");
 438      }
 439      GET_GOLD(ch) -= amount;
 440    }
 441  }
 442  
 443  
 444  #define VANISH(mode) ((mode == SCMD_DONATE || mode == SCMD_JUNK) ? \
 445  		      "  It vanishes in a puff of smoke!" : "")
 446  
 447  int perform_drop(struct char_data *ch, struct obj_data *obj,
 448  		     byte mode, const char *sname, room_rnum RDR)
 449  {
 450    char buf[MAX_STRING_LENGTH];
 451    int value;
 452  
 453    if (OBJ_FLAGGED(obj, ITEM_NODROP)) {
 454      snprintf(buf, sizeof(buf), "You can't %s $p, it must be CURSED!", sname);
 455      act(buf, FALSE, ch, obj, 0, TO_CHAR);
 456      return (0);
 457    }
 458  
 459    snprintf(buf, sizeof(buf), "You %s $p.%s", sname, VANISH(mode));
 460    act(buf, FALSE, ch, obj, 0, TO_CHAR);
 461  
 462    snprintf(buf, sizeof(buf), "$n %ss $p.%s", sname, VANISH(mode));
 463    act(buf, TRUE, ch, obj, 0, TO_ROOM);
 464  
 465    obj_from_char(obj);
 466  
 467    if ((mode == SCMD_DONATE) && OBJ_FLAGGED(obj, ITEM_NODONATE))
 468      mode = SCMD_JUNK;
 469  
 470    switch (mode) {
 471    case SCMD_DROP:
 472      obj_to_room(obj, IN_ROOM(ch));
 473      return (0);
 474    case SCMD_DONATE:
 475      obj_to_room(obj, RDR);
 476      act("$p suddenly appears in a puff a smoke!", FALSE, 0, obj, 0, TO_ROOM);
 477      return (0);
 478    case SCMD_JUNK:
 479      value = MAX(1, MIN(200, GET_OBJ_COST(obj) / 16));
 480      extract_obj(obj);
 481      return (value);
 482    default:
 483      log("SYSERR: Incorrect argument %d passed to perform_drop.", mode);
 484      break;
 485    }
 486  
 487    return (0);
 488  }
 489  
 490  
 491  
 492  ACMD(do_drop)
 493  {
 494    char arg[MAX_INPUT_LENGTH];
 495    struct obj_data *obj, *next_obj;
 496    room_rnum RDR = 0;
 497    byte mode = SCMD_DROP;
 498    int dotmode, amount = 0, multi;
 499    const char *sname;
 500  
 501    switch (subcmd) {
 502    case SCMD_JUNK:
 503      sname = "junk";
 504      mode = SCMD_JUNK;
 505      break;
 506    case SCMD_DONATE:
 507      sname = "donate";
 508      mode = SCMD_DONATE;
 509      switch (rand_number(0, 2)) {
 510      case 0:
 511        mode = SCMD_JUNK;
 512        break;
 513      case 1:
 514      case 2:
 515        RDR = real_room(donation_room_1);
 516        break;
 517  /*    case 3: RDR = real_room(donation_room_2); break;
 518        case 4: RDR = real_room(donation_room_3); break;
 519  */
 520      }
 521      if (RDR == NOWHERE) {
 522        send_to_char(ch, "Sorry, you can't donate anything right now.\r\n");
 523        return;
 524      }
 525      break;
 526    default:
 527      sname = "drop";
 528      break;
 529    }
 530  
 531    argument = one_argument(argument, arg);
 532  
 533    if (!*arg) {
 534      send_to_char(ch, "What do you want to %s?\r\n", sname);
 535      return;
 536    } else if (is_number(arg)) {
 537      multi = atoi(arg);
 538      one_argument(argument, arg);
 539      if (!str_cmp("coins", arg) || !str_cmp("coin", arg))
 540        perform_drop_gold(ch, multi, mode, RDR);
 541      else if (multi <= 0)
 542        send_to_char(ch, "Yeah, that makes sense.\r\n");
 543      else if (!*arg)
 544        send_to_char(ch, "What do you want to %s %d of?\r\n", sname, multi);
 545      else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
 546        send_to_char(ch, "You don't seem to have any %ss.\r\n", arg);
 547      else {
 548        do {
 549          next_obj = get_obj_in_list_vis(ch, arg, NULL, obj->next_content);
 550          amount += perform_drop(ch, obj, mode, sname, RDR);
 551          obj = next_obj;
 552        } while (obj && --multi);
 553      }
 554    } else {
 555      dotmode = find_all_dots(arg);
 556  
 557      /* Can't junk or donate all */
 558      if ((dotmode == FIND_ALL) && (subcmd == SCMD_JUNK || subcmd == SCMD_DONATE)) {
 559        if (subcmd == SCMD_JUNK)
 560  	send_to_char(ch, "Go to the dump if you want to junk EVERYTHING!\r\n");
 561        else
 562  	send_to_char(ch, "Go do the donation room if you want to donate EVERYTHING!\r\n");
 563        return;
 564      }
 565      if (dotmode == FIND_ALL) {
 566        if (!ch->carrying)
 567  	send_to_char(ch, "You don't seem to be carrying anything.\r\n");
 568        else
 569  	for (obj = ch->carrying; obj; obj = next_obj) {
 570  	  next_obj = obj->next_content;
 571  	  amount += perform_drop(ch, obj, mode, sname, RDR);
 572  	}
 573      } else if (dotmode == FIND_ALLDOT) {
 574        if (!*arg) {
 575  	send_to_char(ch, "What do you want to %s all of?\r\n", sname);
 576  	return;
 577        }
 578        if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
 579  	send_to_char(ch, "You don't seem to have any %ss.\r\n", arg);
 580  
 581        while (obj) {
 582  	next_obj = get_obj_in_list_vis(ch, arg, NULL, obj->next_content);
 583  	amount += perform_drop(ch, obj, mode, sname, RDR);
 584  	obj = next_obj;
 585        }
 586      } else {
 587        if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
 588  	send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
 589        else
 590  	amount += perform_drop(ch, obj, mode, sname, RDR);
 591      }
 592    }
 593  
 594    if (amount && (subcmd == SCMD_JUNK)) {
 595      send_to_char(ch, "You have been rewarded by the gods!\r\n");
 596      act("$n has been rewarded by the gods!", TRUE, ch, 0, 0, TO_ROOM);
 597      GET_GOLD(ch) += amount;
 598    }
 599  }
 600  
 601  
 602  void perform_give(struct char_data *ch, struct char_data *vict,
 603  		       struct obj_data *obj)
 604  {
 605    if (OBJ_FLAGGED(obj, ITEM_NODROP)) {
 606      act("You can't let go of $p!!  Yeech!", FALSE, ch, obj, 0, TO_CHAR);
 607      return;
 608    }
 609    if (IS_CARRYING_N(vict) >= CAN_CARRY_N(vict)) {
 610      act("$N seems to have $S hands full.", FALSE, ch, 0, vict, TO_CHAR);
 611      return;
 612    }
 613    if (GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(vict) > CAN_CARRY_W(vict)) {
 614      act("$E can't carry that much weight.", FALSE, ch, 0, vict, TO_CHAR);
 615      return;
 616    }
 617    obj_from_char(obj);
 618    obj_to_char(obj, vict);
 619    act("You give $p to $N.", FALSE, ch, obj, vict, TO_CHAR);
 620    act("$n gives you $p.", FALSE, ch, obj, vict, TO_VICT);
 621    act("$n gives $p to $N.", TRUE, ch, obj, vict, TO_NOTVICT);
 622  }
 623  
 624  /* utility function for give */
 625  struct char_data *give_find_vict(struct char_data *ch, char *arg)
 626  {
 627    struct char_data *vict;
 628  
 629    skip_spaces(&arg);
 630    if (!*arg)
 631      send_to_char(ch, "To who?\r\n");
 632    else if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM)))
 633      send_to_char(ch, "%s", NOPERSON);
 634    else if (vict == ch)
 635      send_to_char(ch, "What's the point of that?\r\n");
 636    else
 637      return (vict);
 638  
 639    return (NULL);
 640  }
 641  
 642  
 643  void perform_give_gold(struct char_data *ch, struct char_data *vict,
 644  		            int amount)
 645  {
 646    char buf[MAX_STRING_LENGTH];
 647  
 648    if (amount <= 0) {
 649      send_to_char(ch, "Heh heh heh ... we are jolly funny today, eh?\r\n");
 650      return;
 651    }
 652    if ((GET_GOLD(ch) < amount) && (IS_NPC(ch) || (GET_LEVEL(ch) < LVL_GOD))) {
 653      send_to_char(ch, "You don't have that many coins!\r\n");
 654      return;
 655    }
 656    send_to_char(ch, "%s", OK);
 657  
 658    snprintf(buf, sizeof(buf), "$n gives you %d gold coin%s.", amount, amount == 1 ? "" : "s");
 659    act(buf, FALSE, ch, 0, vict, TO_VICT);
 660  
 661    snprintf(buf, sizeof(buf), "$n gives %s to $N.", money_desc(amount));
 662    act(buf, TRUE, ch, 0, vict, TO_NOTVICT);
 663  
 664    if (IS_NPC(ch) || (GET_LEVEL(ch) < LVL_GOD))
 665      GET_GOLD(ch) -= amount;
 666    GET_GOLD(vict) += amount;
 667  }
 668  
 669  
 670  ACMD(do_give)
 671  {
 672    char arg[MAX_STRING_LENGTH];
 673    int amount, dotmode;
 674    struct char_data *vict;
 675    struct obj_data *obj, *next_obj;
 676  
 677    argument = one_argument(argument, arg);
 678  
 679    if (!*arg)
 680      send_to_char(ch, "Give what to who?\r\n");
 681    else if (is_number(arg)) {
 682      amount = atoi(arg);
 683      argument = one_argument(argument, arg);
 684      if (!str_cmp("coins", arg) || !str_cmp("coin", arg)) {
 685        one_argument(argument, arg);
 686        if ((vict = give_find_vict(ch, arg)) != NULL)
 687  	perform_give_gold(ch, vict, amount);
 688        return;
 689      } else if (!*arg)	/* Give multiple code. */
 690        send_to_char(ch, "What do you want to give %d of?\r\n", amount);
 691      else if (!(vict = give_find_vict(ch, argument)))
 692        return;
 693      else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 
 694        send_to_char(ch, "You don't seem to have any %ss.\r\n", arg);
 695      else {
 696        while (obj && amount--) {
 697  	next_obj = get_obj_in_list_vis(ch, arg, NULL, obj->next_content);
 698  	perform_give(ch, vict, obj);
 699  	obj = next_obj;
 700        }
 701      }
 702    } else {
 703      char buf1[MAX_INPUT_LENGTH];
 704  
 705      one_argument(argument, buf1);
 706      if (!(vict = give_find_vict(ch, buf1)))
 707        return;
 708      dotmode = find_all_dots(arg);
 709      if (dotmode == FIND_INDIV) {
 710        if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
 711  	send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
 712        else
 713  	perform_give(ch, vict, obj);
 714      } else {
 715        if (dotmode == FIND_ALLDOT && !*arg) {
 716  	send_to_char(ch, "All of what?\r\n");
 717  	return;
 718        }
 719        if (!ch->carrying)
 720  	send_to_char(ch, "You don't seem to be holding anything.\r\n");
 721        else
 722  	for (obj = ch->carrying; obj; obj = next_obj) {
 723  	  next_obj = obj->next_content;
 724  	  if (CAN_SEE_OBJ(ch, obj) &&
 725  	      ((dotmode == FIND_ALL || isname(arg, obj->name))))
 726  	    perform_give(ch, vict, obj);
 727  	}
 728      }
 729    }
 730  }
 731  
 732  
 733  
 734  void weight_change_object(struct obj_data *obj, int weight)
 735  {
 736    struct obj_data *tmp_obj;
 737    struct char_data *tmp_ch;
 738  
 739    if (IN_ROOM(obj) != NOWHERE) {
 740      GET_OBJ_WEIGHT(obj) += weight;
 741    } else if ((tmp_ch = obj->carried_by)) {
 742      obj_from_char(obj);
 743      GET_OBJ_WEIGHT(obj) += weight;
 744      obj_to_char(obj, tmp_ch);
 745    } else if ((tmp_obj = obj->in_obj)) {
 746      obj_from_obj(obj);
 747      GET_OBJ_WEIGHT(obj) += weight;
 748      obj_to_obj(obj, tmp_obj);
 749    } else {
 750      log("SYSERR: Unknown attempt to subtract weight from an object.");
 751    }
 752  }
 753  
 754  
 755  
 756  void name_from_drinkcon(struct obj_data *obj)
 757  {
 758    char *new_name, *cur_name, *next;
 759    const char *liqname;
 760    int liqlen, cpylen;
 761  
 762    if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN))
 763      return;
 764  
 765    liqname = drinknames[GET_OBJ_VAL(obj, 2)];
 766    if (!isname(liqname, obj->name)) {
 767      log("SYSERR: Can't remove liquid '%s' from '%s' (%d) item.", liqname, obj->name, obj->item_number);
 768      return;
 769    }
 770  
 771    liqlen = strlen(liqname);
 772    CREATE(new_name, char, strlen(obj->name) - strlen(liqname)); /* +1 for NUL, -1 for space */
 773  
 774    for (cur_name = obj->name; cur_name; cur_name = next) {
 775      if (*cur_name == ' ')
 776        cur_name++;
 777  
 778      if ((next = strchr(cur_name, ' ')))
 779        cpylen = next - cur_name;
 780      else
 781        cpylen = strlen(cur_name);
 782  
 783      if (!strn_cmp(cur_name, liqname, liqlen))
 784        continue;
 785  
 786      if (*new_name)
 787        strcat(new_name, " ");	/* strcat: OK (size precalculated) */
 788      strncat(new_name, cur_name, cpylen);	/* strncat: OK (size precalculated) */
 789    }
 790  
 791    if (GET_OBJ_RNUM(obj) == NOTHING || obj->name != obj_proto[GET_OBJ_RNUM(obj)].name)
 792      free(obj->name);
 793    obj->name = new_name;
 794  }
 795  
 796  
 797  
 798  void name_to_drinkcon(struct obj_data *obj, int type)
 799  {
 800    char *new_name;
 801  
 802    if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN))
 803      return;
 804  
 805    CREATE(new_name, char, strlen(obj->name) + strlen(drinknames[type]) + 2);
 806    sprintf(new_name, "%s %s", obj->name, drinknames[type]);	/* sprintf: OK */
 807  
 808    if (GET_OBJ_RNUM(obj) == NOTHING || obj->name != obj_proto[GET_OBJ_RNUM(obj)].name)
 809      free(obj->name);
 810  
 811    obj->name = new_name;
 812  }
 813  
 814  
 815  
 816  ACMD(do_drink)
 817  {
 818    char arg[MAX_INPUT_LENGTH];
 819    struct obj_data *temp;
 820    struct affected_type af;
 821    int amount, weight;
 822    int on_ground = 0;
 823  
 824    one_argument(argument, arg);
 825  
 826    if (IS_NPC(ch))	/* Cannot use GET_COND() on mobs. */
 827      return;
 828  
 829    if (!*arg) {
 830      send_to_char(ch, "Drink from what?\r\n");
 831      return;
 832    }
 833    if (!(temp = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) {
 834      if (!(temp = get_obj_in_list_vis(ch, arg, NULL, world[IN_ROOM(ch)].contents))) {
 835        send_to_char(ch, "You can't find it!\r\n");
 836        return;
 837      } else
 838        on_ground = 1;
 839    }
 840    if ((GET_OBJ_TYPE(temp) != ITEM_DRINKCON) &&
 841        (GET_OBJ_TYPE(temp) != ITEM_FOUNTAIN)) {
 842      send_to_char(ch, "You can't drink from that!\r\n");
 843      return;
 844    }
 845    if (on_ground && (GET_OBJ_TYPE(temp) == ITEM_DRINKCON)) {
 846      send_to_char(ch, "You have to be holding that to drink from it.\r\n");
 847      return;
 848    }
 849    if ((GET_COND(ch, DRUNK) > 10) && (GET_COND(ch, THIRST) > 0)) {
 850      /* The pig is drunk */
 851      send_to_char(ch, "You can't seem to get close enough to your mouth.\r\n");
 852      act("$n tries to drink but misses $s mouth!", TRUE, ch, 0, 0, TO_ROOM);
 853      return;
 854    }
 855    if ((GET_COND(ch, FULL) > 20) && (GET_COND(ch, THIRST) > 0)) {
 856      send_to_char(ch, "Your stomach can't contain anymore!\r\n");
 857      return;
 858    }
 859    if (!GET_OBJ_VAL(temp, 1)) {
 860      send_to_char(ch, "It's empty.\r\n");
 861      return;
 862    }
 863    if (subcmd == SCMD_DRINK) {
 864      char buf[MAX_STRING_LENGTH];
 865  
 866      snprintf(buf, sizeof(buf), "$n drinks %s from $p.", drinks[GET_OBJ_VAL(temp, 2)]);
 867      act(buf, TRUE, ch, temp, 0, TO_ROOM);
 868  
 869      send_to_char(ch, "You drink the %s.\r\n", drinks[GET_OBJ_VAL(temp, 2)]);
 870  
 871      if (drink_aff[GET_OBJ_VAL(temp, 2)][DRUNK] > 0)
 872        amount = (25 - GET_COND(ch, THIRST)) / drink_aff[GET_OBJ_VAL(temp, 2)][DRUNK];
 873      else
 874        amount = rand_number(3, 10);
 875  
 876    } else {
 877      act("$n sips from $p.", TRUE, ch, temp, 0, TO_ROOM);
 878      send_to_char(ch, "It tastes like %s.\r\n", drinks[GET_OBJ_VAL(temp, 2)]);
 879      amount = 1;
 880    }
 881  
 882    amount = MIN(amount, GET_OBJ_VAL(temp, 1));
 883  
 884    /* You can't subtract more than the object weighs */
 885    weight = MIN(amount, GET_OBJ_WEIGHT(temp));
 886  
 887    weight_change_object(temp, -weight);	/* Subtract amount */
 888  
 889    gain_condition(ch, DRUNK,  drink_aff[GET_OBJ_VAL(temp, 2)][DRUNK]  * amount / 4);
 890    gain_condition(ch, FULL,   drink_aff[GET_OBJ_VAL(temp, 2)][FULL]   * amount / 4);
 891    gain_condition(ch, THIRST, drink_aff[GET_OBJ_VAL(temp, 2)][THIRST] * amount / 4);
 892  
 893    if (GET_COND(ch, DRUNK) > 10)
 894      send_to_char(ch, "You feel drunk.\r\n");
 895  
 896    if (GET_COND(ch, THIRST) > 20)
 897      send_to_char(ch, "You don't feel thirsty any more.\r\n");
 898  
 899    if (GET_COND(ch, FULL) > 20)
 900      send_to_char(ch, "You are full.\r\n");
 901  
 902    if (GET_OBJ_VAL(temp, 3)) {	/* The crap was poisoned ! */
 903      send_to_char(ch, "Oops, it tasted rather strange!\r\n");
 904      act("$n chokes and utters some strange sounds.", TRUE, ch, 0, 0, TO_ROOM);
 905  
 906      af.type = SPELL_POISON;
 907      af.duration = amount * 3;
 908      af.modifier = 0;
 909      af.location = APPLY_NONE;
 910      af.bitvector = AFF_POISON;
 911      affect_join(ch, &af, FALSE, FALSE, FALSE, FALSE);
 912    }
 913    /* empty the container, and no longer poison. */
 914    GET_OBJ_VAL(temp, 1) -= amount;
 915    if (!GET_OBJ_VAL(temp, 1)) {	/* The last bit */
 916      name_from_drinkcon(temp);
 917      GET_OBJ_VAL(temp, 2) = 0;
 918      GET_OBJ_VAL(temp, 3) = 0;
 919    }
 920    return;
 921  }
 922  
 923  
 924  
 925  ACMD(do_eat)
 926  {
 927    char arg[MAX_INPUT_LENGTH];
 928    struct obj_data *food;
 929    struct affected_type af;
 930    int amount;
 931  
 932    one_argument(argument, arg);
 933  
 934    if (IS_NPC(ch))	/* Cannot use GET_COND() on mobs. */
 935      return;
 936  
 937    if (!*arg) {
 938      send_to_char(ch, "Eat what?\r\n");
 939      return;
 940    }
 941    if (!(food = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) {
 942      send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
 943      return;
 944    }
 945    if (subcmd == SCMD_TASTE && ((GET_OBJ_TYPE(food) == ITEM_DRINKCON) ||
 946  			       (GET_OBJ_TYPE(food) == ITEM_FOUNTAIN))) {
 947      do_drink(ch, argument, 0, SCMD_SIP);
 948      return;
 949    }
 950    if ((GET_OBJ_TYPE(food) != ITEM_FOOD) && (GET_LEVEL(ch) < LVL_GOD)) {
 951      send_to_char(ch, "You can't eat THAT!\r\n");
 952      return;
 953    }
 954    if (GET_COND(ch, FULL) > 20) {/* Stomach full */
 955      send_to_char(ch, "You are too full to eat more!\r\n");
 956      return;
 957    }
 958    if (subcmd == SCMD_EAT) {
 959      act("You eat $p.", FALSE, ch, food, 0, TO_CHAR);
 960      act("$n eats $p.", TRUE, ch, food, 0, TO_ROOM);
 961    } else {
 962      act("You nibble a little bit of $p.", FALSE, ch, food, 0, TO_CHAR);
 963      act("$n tastes a little bit of $p.", TRUE, ch, food, 0, TO_ROOM);
 964    }
 965  
 966    amount = (subcmd == SCMD_EAT ? GET_OBJ_VAL(food, 0) : 1);
 967  
 968    gain_condition(ch, FULL, amount);
 969  
 970    if (GET_COND(ch, FULL) > 20)
 971      send_to_char(ch, "You are full.\r\n");
 972  
 973    if (GET_OBJ_VAL(food, 3) && (GET_LEVEL(ch) < LVL_IMMORT)) {
 974      /* The crap was poisoned ! */
 975      send_to_char(ch, "Oops, that tasted rather strange!\r\n");
 976      act("$n coughs and utters some strange sounds.", FALSE, ch, 0, 0, TO_ROOM);
 977  
 978      af.type = SPELL_POISON;
 979      af.duration = amount * 2;
 980      af.modifier = 0;
 981      af.location = APPLY_NONE;
 982      af.bitvector = AFF_POISON;
 983      affect_join(ch, &af, FALSE, FALSE, FALSE, FALSE);
 984    }
 985    if (subcmd == SCMD_EAT)
 986      extract_obj(food);
 987    else {
 988      if (!(--GET_OBJ_VAL(food, 0))) {
 989        send_to_char(ch, "There's nothing left now.\r\n");
 990        extract_obj(food);
 991      }
 992    }
 993  }
 994  
 995  
 996  ACMD(do_pour)
 997  {
 998    char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
 999    struct obj_data *from_obj = NULL, *to_obj = NULL;
1000    int amount;
1001  
1002    two_arguments(argument, arg1, arg2);
1003  
1004    if (subcmd == SCMD_POUR) {
1005      if (!*arg1) {		/* No arguments */
1006        send_to_char(ch, "From what do you want to pour?\r\n");
1007        return;
1008      }
1009      if (!(from_obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying))) {
1010        send_to_char(ch, "You can't find it!\r\n");
1011        return;
1012      }
1013      if (GET_OBJ_TYPE(from_obj) != ITEM_DRINKCON) {
1014        send_to_char(ch, "You can't pour from that!\r\n");
1015        return;
1016      }
1017    }
1018    if (subcmd == SCMD_FILL) {
1019      if (!*arg1) {		/* no arguments */
1020        send_to_char(ch, "What do you want to fill?  And what are you filling it from?\r\n");
1021        return;
1022      }
1023      if (!(to_obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying))) {
1024        send_to_char(ch, "You can't find it!\r\n");
1025        return;
1026      }
1027      if (GET_OBJ_TYPE(to_obj) != ITEM_DRINKCON) {
1028        act("You can't fill $p!", FALSE, ch, to_obj, 0, TO_CHAR);
1029        return;
1030      }
1031      if (!*arg2) {		/* no 2nd argument */
1032        act("What do you want to fill $p from?", FALSE, ch, to_obj, 0, TO_CHAR);
1033        return;
1034      }
1035      if (!(from_obj = get_obj_in_list_vis(ch, arg2, NULL, world[IN_ROOM(ch)].contents))) {
1036        send_to_char(ch, "There doesn't seem to be %s %s here.\r\n", AN(arg2), arg2);
1037        return;
1038      }
1039      if (GET_OBJ_TYPE(from_obj) != ITEM_FOUNTAIN) {
1040        act("You can't fill something from $p.", FALSE, ch, from_obj, 0, TO_CHAR);
1041        return;
1042      }
1043    }
1044    if (GET_OBJ_VAL(from_obj, 1) == 0) {
1045      act("The $p is empty.", FALSE, ch, from_obj, 0, TO_CHAR);
1046      return;
1047    }
1048    if (subcmd == SCMD_POUR) {	/* pour */
1049      if (!*arg2) {
1050        send_to_char(ch, "Where do you want it?  Out or in what?\r\n");
1051        return;
1052      }
1053      if (!str_cmp(arg2, "out")) {
1054        act("$n empties $p.", TRUE, ch, from_obj, 0, TO_ROOM);
1055        act("You empty $p.", FALSE, ch, from_obj, 0, TO_CHAR);
1056  
1057        weight_change_object(from_obj, -GET_OBJ_VAL(from_obj, 1)); /* Empty */
1058  
1059        name_from_drinkcon(from_obj);
1060        GET_OBJ_VAL(from_obj, 1) = 0;
1061        GET_OBJ_VAL(from_obj, 2) = 0;
1062        GET_OBJ_VAL(from_obj, 3) = 0;
1063  
1064        return;
1065      }
1066      if (!(to_obj = get_obj_in_list_vis(ch, arg2, NULL, ch->carrying))) {
1067        send_to_char(ch, "You can't find it!\r\n");
1068        return;
1069      }
1070      if ((GET_OBJ_TYPE(to_obj) != ITEM_DRINKCON) &&
1071  	(GET_OBJ_TYPE(to_obj) != ITEM_FOUNTAIN)) {
1072        send_to_char(ch, "You can't pour anything into that.\r\n");
1073        return;
1074      }
1075    }
1076    if (to_obj == from_obj) {
1077      send_to_char(ch, "A most unproductive effort.\r\n");
1078      return;
1079    }
1080    if ((GET_OBJ_VAL(to_obj, 1) != 0) &&
1081        (GET_OBJ_VAL(to_obj, 2) != GET_OBJ_VAL(from_obj, 2))) {
1082      send_to_char(ch, "There is already another liquid in it!\r\n");
1083      return;
1084    }
1085    if (!(GET_OBJ_VAL(to_obj, 1) < GET_OBJ_VAL(to_obj, 0))) {
1086      send_to_char(ch, "There is no room for more.\r\n");
1087      return;
1088    }
1089    if (subcmd == SCMD_POUR)
1090      send_to_char(ch, "You pour the %s into the %s.", drinks[GET_OBJ_VAL(from_obj, 2)], arg2);
1091  
1092    if (subcmd == SCMD_FILL) {
1093      act("You gently fill $p from $P.", FALSE, ch, to_obj, from_obj, TO_CHAR);
1094      act("$n gently fills $p from $P.", TRUE, ch, to_obj, from_obj, TO_ROOM);
1095    }
1096    /* New alias */
1097    if (GET_OBJ_VAL(to_obj, 1) == 0)
1098      name_to_drinkcon(to_obj, GET_OBJ_VAL(from_obj, 2));
1099  
1100    /* First same type liq. */
1101    GET_OBJ_VAL(to_obj, 2) = GET_OBJ_VAL(from_obj, 2);
1102  
1103    /* Then how much to pour */
1104    GET_OBJ_VAL(from_obj, 1) -= (amount =
1105  			 (GET_OBJ_VAL(to_obj, 0) - GET_OBJ_VAL(to_obj, 1)));
1106  
1107    GET_OBJ_VAL(to_obj, 1) = GET_OBJ_VAL(to_obj, 0);
1108  
1109    if (GET_OBJ_VAL(from_obj, 1) < 0) {	/* There was too little */
1110      GET_OBJ_VAL(to_obj, 1) += GET_OBJ_VAL(from_obj, 1);
1111      amount += GET_OBJ_VAL(from_obj, 1);
1112      name_from_drinkcon(from_obj);
1113      GET_OBJ_VAL(from_obj, 1) = 0;
1114      GET_OBJ_VAL(from_obj, 2) = 0;
1115      GET_OBJ_VAL(from_obj, 3) = 0;
1116    }
1117    /* Then the poison boogie */
1118    GET_OBJ_VAL(to_obj, 3) =
1119      (GET_OBJ_VAL(to_obj, 3) || GET_OBJ_VAL(from_obj, 3));
1120  
1121    /* And the weight boogie */
1122    weight_change_object(from_obj, -amount);
1123    weight_change_object(to_obj, amount);	/* Add weight */
1124  }
1125  
1126  
1127  
1128  void wear_message(struct char_data *ch, struct obj_data *obj, int where)
1129  {
1130    const char *wear_messages[][2] = {
1131      {"$n lights $p and holds it.",
1132      "You light $p and hold it."},
1133  
1134      {"$n slides $p on to $s right ring finger.",
1135      "You slide $p on to your right ring finger."},
1136  
1137      {"$n slides $p on to $s left ring finger.",
1138      "You slide $p on to your left ring finger."},
1139  
1140      {"$n wears $p around $s neck.",
1141      "You wear $p around your neck."},
1142  
1143      {"$n wears $p around $s neck.",
1144      "You wear $p around your neck."},
1145  
1146      {"$n wears $p on $s body.",
1147      "You wear $p on your body."},
1148  
1149      {"$n wears $p on $s head.",
1150      "You wear $p on your head."},
1151  
1152      {"$n puts $p on $s legs.",
1153      "You put $p on your legs."},
1154  
1155      {"$n wears $p on $s feet.",
1156      "You wear $p on your feet."},
1157  
1158      {"$n puts $p on $s hands.",
1159      "You put $p on your hands."},
1160  
1161      {"$n wears $p on $s arms.",
1162      "You wear $p on your arms."},
1163  
1164      {"$n straps $p around $s arm as a shield.",
1165      "You start to use $p as a shield."},
1166  
1167      {"$n wears $p about $s body.",
1168      "You wear $p around your body."},
1169  
1170      {"$n wears $p around $s waist.",
1171      "You wear $p around your waist."},
1172  
1173      {"$n puts $p on around $s right wrist.",
1174      "You put $p on around your right wrist."},
1175  
1176      {"$n puts $p on around $s left wrist.",
1177      "You put $p on around your left wrist."},
1178  
1179      {"$n wields $p.",
1180      "You wield $p."},
1181  
1182      {"$n grabs $p.",
1183      "You grab $p."}
1184    };
1185  
1186    act(wear_messages[where][0], TRUE, ch, obj, 0, TO_ROOM);
1187    act(wear_messages[where][1], FALSE, ch, obj, 0, TO_CHAR);
1188  }
1189  
1190  
1191  
1192  void perform_wear(struct char_data *ch, struct obj_data *obj, int where)
1193  {
1194    /*
1195     * ITEM_WEAR_TAKE is used for objects that do not require special bits
1196     * to be put into that position (e.g. you can hold any object, not just
1197     * an object with a HOLD bit.)
1198     */
1199  
1200    int wear_bitvectors[] = {
1201      ITEM_WEAR_TAKE, ITEM_WEAR_FINGER, ITEM_WEAR_FINGER, ITEM_WEAR_NECK,
1202      ITEM_WEAR_NECK, ITEM_WEAR_BODY, ITEM_WEAR_HEAD, ITEM_WEAR_LEGS,
1203      ITEM_WEAR_FEET, ITEM_WEAR_HANDS, ITEM_WEAR_ARMS, ITEM_WEAR_SHIELD,
1204      ITEM_WEAR_ABOUT, ITEM_WEAR_WAIST, ITEM_WEAR_WRIST, ITEM_WEAR_WRIST,
1205      ITEM_WEAR_WIELD, ITEM_WEAR_TAKE
1206    };
1207  
1208    const char *already_wearing[] = {
1209      "You're already using a light.\r\n",
1210      "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
1211      "You're already wearing something on both of your ring fingers.\r\n",
1212      "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
1213      "You can't wear anything else around your neck.\r\n",
1214      "You're already wearing something on your body.\r\n",
1215      "You're already wearing something on your head.\r\n",
1216      "You're already wearing something on your legs.\r\n",
1217      "You're already wearing something on your feet.\r\n",
1218      "You're already wearing something on your hands.\r\n",
1219      "You're already wearing something on your arms.\r\n",
1220      "You're already using a shield.\r\n",
1221      "You're already wearing something about your body.\r\n",
1222      "You already have something around your waist.\r\n",
1223      "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
1224      "You're already wearing something around both of your wrists.\r\n",
1225      "You're already wielding a weapon.\r\n",
1226      "You're already holding something.\r\n"
1227    };
1228  
1229    /* first, make sure that the wear position is valid. */
1230    if (!CAN_WEAR(obj, wear_bitvectors[where])) {
1231      act("You can't wear $p there.", FALSE, ch, obj, 0, TO_CHAR);
1232      return;
1233    }
1234    /* for neck, finger, and wrist, try pos 2 if pos 1 is already full */
1235    if ((where == WEAR_FINGER_R) || (where == WEAR_NECK_1) || (where == WEAR_WRIST_R))
1236      if (GET_EQ(ch, where))
1237        where++;
1238  
1239    if (GET_EQ(ch, where)) {
1240      send_to_char(ch, "%s", already_wearing[where]);
1241      return;
1242    }
1243    wear_message(ch, obj, where);
1244    obj_from_char(obj);
1245    equip_char(ch, obj, where);
1246  }
1247  
1248  
1249  
1250  int find_eq_pos(struct char_data *ch, struct obj_data *obj, char *arg)
1251  {
1252    int where = -1;
1253  
1254    const char *keywords[] = {
1255      "!RESERVED!",
1256      "finger",
1257      "!RESERVED!",
1258      "neck",
1259      "!RESERVED!",
1260      "body",
1261      "head",
1262      "legs",
1263      "feet",
1264      "hands",
1265      "arms",
1266      "shield",
1267      "about",
1268      "waist",
1269      "wrist",
1270      "!RESERVED!",
1271      "!RESERVED!",
1272      "!RESERVED!",
1273      "\n"
1274    };
1275  
1276    if (!arg || !*arg) {
1277      if (CAN_WEAR(obj, ITEM_WEAR_FINGER))      where = WEAR_FINGER_R;
1278      if (CAN_WEAR(obj, ITEM_WEAR_NECK))        where = WEAR_NECK_1;
1279      if (CAN_WEAR(obj, ITEM_WEAR_BODY))        where = WEAR_BODY;
1280      if (CAN_WEAR(obj, ITEM_WEAR_HEAD))        where = WEAR_HEAD;
1281      if (CAN_WEAR(obj, ITEM_WEAR_LEGS))        where = WEAR_LEGS;
1282      if (CAN_WEAR(obj, ITEM_WEAR_FEET))        where = WEAR_FEET;
1283      if (CAN_WEAR(obj, ITEM_WEAR_HANDS))       where = WEAR_HANDS;
1284      if (CAN_WEAR(obj, ITEM_WEAR_ARMS))        where = WEAR_ARMS;
1285      if (CAN_WEAR(obj, ITEM_WEAR_SHIELD))      where = WEAR_SHIELD;
1286      if (CAN_WEAR(obj, ITEM_WEAR_ABOUT))       where = WEAR_ABOUT;
1287      if (CAN_WEAR(obj, ITEM_WEAR_WAIST))       where = WEAR_WAIST;
1288      if (CAN_WEAR(obj, ITEM_WEAR_WRIST))       where = WEAR_WRIST_R;
1289    } else if ((where = search_block(arg, keywords, FALSE)) < 0)
1290      send_to_char(ch, "'%s'?  What part of your body is THAT?\r\n", arg);
1291  
1292    return (where);
1293  }
1294  
1295  
1296  
1297  ACMD(do_wear)
1298  {
1299    char arg1[MAX_INPUT_LENGTH];
1300    char arg2[MAX_INPUT_LENGTH];
1301    struct obj_data *obj, *next_obj;
1302    int where, dotmode, items_worn = 0;
1303  
1304    two_arguments(argument, arg1, arg2);
1305  
1306    if (!*arg1) {
1307      send_to_char(ch, "Wear what?\r\n");
1308      return;
1309    }
1310    dotmode = find_all_dots(arg1);
1311  
1312    if (*arg2 && (dotmode != FIND_INDIV)) {
1313      send_to_char(ch, "You can't specify the same body location for more than one item!\r\n");
1314      return;
1315    }
1316    if (dotmode == FIND_ALL) {
1317      for (obj = ch->carrying; obj; obj = next_obj) {
1318        next_obj = obj->next_content;
1319        if (CAN_SEE_OBJ(ch, obj) && (where = find_eq_pos(ch, obj, 0)) >= 0) {
1320  	items_worn++;
1321  	perform_wear(ch, obj, where);
1322        }
1323      }
1324      if (!items_worn)
1325        send_to_char(ch, "You don't seem to have anything wearable.\r\n");
1326    } else if (dotmode == FIND_ALLDOT) {
1327      if (!*arg1) {
1328        send_to_char(ch, "Wear all of what?\r\n");
1329        return;
1330      }
1331      if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
1332        send_to_char(ch, "You don't seem to have any %ss.\r\n", arg1);
1333      else
1334        while (obj) {
1335  	next_obj = get_obj_in_list_vis(ch, arg1, NULL, obj->next_content);
1336  	if ((where = find_eq_pos(ch, obj, 0)) >= 0)
1337  	  perform_wear(ch, obj, where);
1338  	else
1339  	  act("You can't wear $p.", FALSE, ch, obj, 0, TO_CHAR);
1340  	obj = next_obj;
1341        }
1342    } else {
1343      if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
1344        send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg1), arg1);
1345      else {
1346        if ((where = find_eq_pos(ch, obj, arg2)) >= 0)
1347  	perform_wear(ch, obj, where);
1348        else if (!*arg2)
1349  	act("You can't wear $p.", FALSE, ch, obj, 0, TO_CHAR);
1350      }
1351    }
1352  }
1353  
1354  
1355  
1356  ACMD(do_wield)
1357  {
1358    char arg[MAX_INPUT_LENGTH];
1359    struct obj_data *obj;
1360  
1361    one_argument(argument, arg);
1362  
1363    if (!*arg)
1364      send_to_char(ch, "Wield what?\r\n");
1365    else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
1366      send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
1367    else {
1368      if (!CAN_WEAR(obj, ITEM_WEAR_WIELD))
1369        send_to_char(ch, "You can't wield that.\r\n");
1370      else if (GET_OBJ_WEIGHT(obj) > str_app[STRENGTH_APPLY_INDEX(ch)].wield_w)
1371        send_to_char(ch, "It's too heavy for you to use.\r\n");
1372      else
1373        perform_wear(ch, obj, WEAR_WIELD);
1374    }
1375  }
1376  
1377  
1378  
1379  ACMD(do_grab)
1380  {
1381    char arg[MAX_INPUT_LENGTH];
1382    struct obj_data *obj;
1383  
1384    one_argument(argument, arg);
1385  
1386    if (!*arg)
1387      send_to_char(ch, "Hold what?\r\n");
1388    else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
1389      send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
1390    else {
1391      if (GET_OBJ_TYPE(obj) == ITEM_LIGHT)
1392        perform_wear(ch, obj, WEAR_LIGHT);
1393      else {
1394        if (!CAN_WEAR(obj, ITEM_WEAR_HOLD) && GET_OBJ_TYPE(obj) != ITEM_WAND &&
1395        GET_OBJ_TYPE(obj) != ITEM_STAFF && GET_OBJ_TYPE(obj) != ITEM_SCROLL &&
1396  	  GET_OBJ_TYPE(obj) != ITEM_POTION)
1397  	send_to_char(ch, "You can't hold that.\r\n");
1398        else
1399  	perform_wear(ch, obj, WEAR_HOLD);
1400      }
1401    }
1402  }
1403  
1404  
1405  
1406  void perform_remove(struct char_data *ch, int pos)
1407  {
1408    struct obj_data *obj;
1409  
1410    if (!(obj = GET_EQ(ch, pos)))
1411      log("SYSERR: perform_remove: bad pos %d passed.", pos);
1412    else if (OBJ_FLAGGED(obj, ITEM_NODROP))
1413      act("You can't remove $p, it must be CURSED!", FALSE, ch, obj, 0, TO_CHAR);
1414    else if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch))
1415      act("$p: you can't carry that many items!", FALSE, ch, obj, 0, TO_CHAR);
1416    else {
1417      obj_to_char(unequip_char(ch, pos), ch);
1418      act("You stop using $p.", FALSE, ch, obj, 0, TO_CHAR);
1419      act("$n stops using $p.", TRUE, ch, obj, 0, TO_ROOM);
1420    }
1421  }
1422  
1423  
1424  
1425  ACMD(do_remove)
1426  {
1427    char arg[MAX_INPUT_LENGTH];
1428    int i, dotmode, found;
1429  
1430    one_argument(argument, arg);
1431  
1432    if (!*arg) {
1433      send_to_char(ch, "Remove what?\r\n");
1434      return;
1435    }
1436    dotmode = find_all_dots(arg);
1437  
1438    if (dotmode == FIND_ALL) {
1439      found = 0;
1440      for (i = 0; i < NUM_WEARS; i++)
1441        if (GET_EQ(ch, i)) {
1442  	perform_remove(ch, i);
1443  	found = 1;
1444        }
1445      if (!found)
1446        send_to_char(ch, "You're not using anything.\r\n");
1447    } else if (dotmode == FIND_ALLDOT) {
1448      if (!*arg)
1449        send_to_char(ch, "Remove all of what?\r\n");
1450      else {
1451        found = 0;
1452        for (i = 0; i < NUM_WEARS; i++)
1453  	if (GET_EQ(ch, i) && CAN_SEE_OBJ(ch, GET_EQ(ch, i)) &&
1454  	    isname(arg, GET_EQ(ch, i)->name)) {
1455  	  perform_remove(ch, i);
1456  	  found = 1;
1457  	}
1458        if (!found)
1459  	send_to_char(ch, "You don't seem to be using any %ss.\r\n", arg);
1460      }
1461    } else {
1462      if ((i = get_obj_pos_in_equip_vis(ch, arg, NULL, ch->equipment)) < 0)
1463        send_to_char(ch, "You don't seem to be using %s %s.\r\n", AN(arg), arg);
1464      else
1465        perform_remove(ch, i);
1466    }
1467  }