/* ************************************************************************
*  file: act.obj1.c , Implementation of commands.         Part of DIKUMUD *
*  Usage : Commands mainly moving around objects.                         *
*  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */

#include "os.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "prototypes.h"

/* extern variables */

extern struct str_app_type str_app[];
extern struct room_data *world;
extern struct descriptor_data *descriptor_list;
extern struct room_data *world;

/* extern functions */

struct obj_data *create_money (int amount);


/* procedures related to get */
void get (struct char_data *ch, struct obj_data *obj_object,
  struct obj_data *sub_object)
{
  struct char_data *tmp_char;
  char buffer[MAX_STRING_LENGTH];

  if (sub_object) {
    obj_from_obj (obj_object);
    obj_to_char (obj_object, ch);
    if (sub_object->carried_by == ch) {
      act ("You get $p from $P.", 0, ch, obj_object, sub_object, TO_CHAR);
      act ("$n gets $p from $s $P.", 1, ch, obj_object, sub_object, TO_ROOM);
    } else {
      act ("You get $p from $P.", 0, ch, obj_object, sub_object, TO_CHAR);

      act ("$n gets $p from $P.", 1, ch, obj_object, sub_object, TO_ROOM);
    }
  } else {
    obj_from_room (obj_object);
    obj_to_char (obj_object, ch);
    act ("You get $p.", 0, ch, obj_object, 0, TO_CHAR);
    act ("$n gets $p.", 1, ch, obj_object, 0, TO_ROOM);
  }
  if ((obj_object->obj_flags.type_flag == ITEM_MONEY) &&
    (obj_object->obj_flags.value[0] >= 1)) {
    obj_from_char (obj_object);
    sprintf (buffer, "There was %d coins.\n\r",
      obj_object->obj_flags.value[0]);
    send_to_char (buffer, ch);
    GET_GOLD (ch) += obj_object->obj_flags.value[0];
    extract_obj (obj_object);
  }
}


void do_get (struct char_data *ch, char *argument, int cmd)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char buffer[MAX_STRING_LENGTH];
  struct obj_data *sub_object;
  struct obj_data *obj_object;
  struct obj_data *next_obj;
  bool found = FALSE;
  bool fail = FALSE;
  int type = 3;

  argument_interpreter (argument, arg1, arg2);

  /* get type */
  if (!*arg1) {
    type = 0;
  }
  if (*arg1 && !*arg2) {
    if (!str_cmp (arg1, "all")) {
      type = 1;
    } else {
      type = 2;
    }
  }
  if (*arg1 && *arg2) {
    if (!str_cmp (arg1, "all")) {
      if (!str_cmp (arg2, "all")) {
        type = 3;
      } else {
        type = 4;
      }
    } else {
      if (!str_cmp (arg2, "all")) {
        type = 5;
      } else {
        type = 6;
      }
    }
  }

  switch (type) {
    /* get */
  case 0:{
      send_to_char ("Get what?\n\r", ch);
    }
    break;
    /* get all */
  case 1:{
      sub_object = 0;
      found = FALSE;
      fail = FALSE;
      for (obj_object = world[ch->in_room].contents;
        obj_object; obj_object = next_obj) {
        next_obj = obj_object->next_content;
        if (CAN_SEE_OBJ (ch, obj_object)) {
          if ((IS_CARRYING_N (ch) + 1) <= CAN_CARRY_N (ch)) {
            if ((IS_CARRYING_W (ch) + obj_object->obj_flags.weight) <=
              CAN_CARRY_W (ch)) {
              if (CAN_WEAR (obj_object, ITEM_TAKE)) {
                get (ch, obj_object, sub_object);
                found = TRUE;
              } else {
                send_to_char ("You can't take that\n\r", ch);
                fail = TRUE;
              }
            } else {
              sprintf (buffer, "%s : You can't carry that much weight.\n\r",
                fname (obj_object->name));
              send_to_char (buffer, ch);
              fail = TRUE;
            }
          } else {
            sprintf (buffer, "%s : You can't carry that many items.\n\r",
              fname (obj_object->name));
            send_to_char (buffer, ch);
            fail = TRUE;
          }
        }
      }
      if (!fail)
        send_to_char ("You see nothing here.\n\r", ch);
    }
    break;
    /* get ??? */
  case 2:{
      sub_object = 0;
      found = FALSE;
      fail = FALSE;
      obj_object = get_obj_in_list_vis (ch, arg1,
        world[ch->in_room].contents);
      if (obj_object) {
        if ((IS_CARRYING_N (ch) + 1 < CAN_CARRY_N (ch))) {
          if ((IS_CARRYING_W (ch) + obj_object->obj_flags.weight) <
            CAN_CARRY_W (ch)) {
            if (CAN_WEAR (obj_object, ITEM_TAKE)) {
              get (ch, obj_object, sub_object);
              found = TRUE;
            } else {
              send_to_char ("You can't take that\n\r", ch);
              fail = TRUE;
            }
          } else {
            sprintf (buffer, "%s : You can't carry that much weight.\n\r",
              fname (obj_object->name));
            send_to_char (buffer, ch);
            fail = TRUE;
          }
        } else {
          sprintf (buffer, "%s : You can't carry that many items.\n\r",
            fname (obj_object->name));
          send_to_char (buffer, ch);
          fail = TRUE;
        }
      } else {
        sprintf (buffer, "You do not see a %s here.\n\r", arg1);
        send_to_char (buffer, ch);
        fail = TRUE;
      }
    }
    break;
    /* get all all */
  case 3:{
      send_to_char ("You must be joking?!\n\r", ch);
    }
    break;
    /* get all ??? */
  case 4:{
      found = FALSE;
      fail = FALSE;
      sub_object = get_obj_in_list_vis (ch, arg2,
        world[ch->in_room].contents);
      if (!sub_object) {
        sub_object = get_obj_in_list_vis (ch, arg2, ch->carrying);
      }
      if (sub_object) {
        if (GET_ITEM_TYPE (sub_object) == ITEM_CONTAINER) {
          if (!IS_SET (sub_object->obj_flags.value[1], CONT_CLOSED)) {
            for (obj_object = sub_object->contains;
              obj_object; obj_object = next_obj) {
              next_obj = obj_object->next_content;
              if (CAN_SEE_OBJ (ch, obj_object)) {
                if ((IS_CARRYING_N (ch) + 1 < CAN_CARRY_N (ch))) {
                  if ((IS_CARRYING_W (ch) + obj_object->obj_flags.weight) <
                    CAN_CARRY_W (ch)) {
                    if (CAN_WEAR (obj_object, ITEM_TAKE)) {
                      get (ch, obj_object, sub_object);
                      found = TRUE;
                    } else {
                      send_to_char ("You can't take that\n\r", ch);
                      fail = TRUE;
                    }
                  } else {
                    sprintf (buffer,
                      "%s : You can't carry that much weight.\n\r",
                      fname (obj_object->name));
                    send_to_char (buffer, ch);
                    fail = TRUE;
                  }
                } else {
                  sprintf (buffer,
                    "%s : You can't carry that many items.\n\r",
                    fname (obj_object->name));
                  send_to_char (buffer, ch);
                  fail = TRUE;
                }
              }
            }
            if (!found && !fail) {
              sprintf (buffer, "You do not see anything in the %s.\n\r",
                fname (sub_object->name));
              send_to_char (buffer, ch);
              fail = TRUE;
            }
          } else {              /* container closed */
            send_to_char ("It's closed.\n\r", ch);
          }
        } else {
          sprintf (buffer, "The %s is not a container.\n\r",
            fname (sub_object->name));
          send_to_char (buffer, ch);
          fail = TRUE;
        }
      } else {
        sprintf (buffer, "You do not see or have the %s.\n\r", arg2);
        send_to_char (buffer, ch);
        fail = TRUE;
      }
    }
    break;
  case 5:{
      send_to_char
        ("You can't take a thing from more than one container.\n\r", ch);
    }
    break;
  case 6:{
      found = FALSE;
      fail = FALSE;
      sub_object = get_obj_in_list_vis (ch, arg2,
        world[ch->in_room].contents);
      if (!sub_object) {
        sub_object = get_obj_in_list_vis (ch, arg2, ch->carrying);
      }
      if (sub_object) {
        if (GET_ITEM_TYPE (sub_object) == ITEM_CONTAINER) {
          if (!IS_SET (sub_object->obj_flags.value[1], CONT_CLOSED)) {
            obj_object = get_obj_in_list_vis (ch, arg1, sub_object->contains);
            if (obj_object) {
              if ((IS_CARRYING_N (ch) + 1 < CAN_CARRY_N (ch))) {
                if ((IS_CARRYING_W (ch) + obj_object->obj_flags.weight) <
                  CAN_CARRY_W (ch)) {
                  if (CAN_WEAR (obj_object, ITEM_TAKE)) {
                    get (ch, obj_object, sub_object);
                    found = TRUE;
                  } else {
                    send_to_char ("You can't take that\n\r", ch);
                    fail = TRUE;
                  }
                } else {
                  sprintf (buffer,
                    "%s : You can't carry that much weight.\n\r",
                    fname (obj_object->name));
                  send_to_char (buffer, ch);
                  fail = TRUE;
                }
              } else {
                sprintf (buffer, "%s : You can't carry that many items.\n\r",
                  fname (obj_object->name));
                send_to_char (buffer, ch);
                fail = TRUE;
              }
            } else {
              sprintf (buffer, "The %s does not contain the %s.\n\r",
                fname (sub_object->name), arg1);
              send_to_char (buffer, ch);
              fail = TRUE;
            }
          } else {
            send_to_char ("It's closed.\n\r", ch);
          }
        } else {
          sprintf (buffer, "The %s is not a container.\n\r",
            fname (sub_object->name));
          send_to_char (buffer, ch);
          fail = TRUE;
        }
      } else {
        sprintf (buffer, "You do not see or have the %s.\n\r", arg2);
        send_to_char (buffer, ch);
        fail = TRUE;
      }
    }
    break;
  }
}


void do_drop (struct char_data *ch, char *argument, int cmd)
{
  char arg[MAX_STRING_LENGTH];
  int amount;
  char buffer[MAX_STRING_LENGTH];
  struct obj_data *tmp_object;
  struct obj_data *next_obj;
  struct char_data *tmp_char;
  bool test = FALSE;

  argument = one_argument (argument, arg);
  if (is_number (arg)) {
    amount = atoi (arg);
    argument = one_argument (argument, arg);
    if (str_cmp ("coins", arg) && str_cmp ("coin", arg)) {
      send_to_char ("Sorry, you can't do that (yet)...\n\r", ch);
      return;
    }
    if (amount < 0) {
      send_to_char ("Sorry, you can't do that!\n\r", ch);
      return;
    }
    if (GET_GOLD (ch) < amount) {
      send_to_char ("You haven't got that many coins!\n\r", ch);
      return;
    }
    send_to_char ("OK.\n\r", ch);
    if (amount == 0)
      return;

    act ("$n drops some gold.", FALSE, ch, 0, 0, TO_ROOM);
    tmp_object = create_money (amount);
    obj_to_room (tmp_object, ch->in_room);
    GET_GOLD (ch) -= amount;
    return;
  }

  if (*arg) {
    if (!str_cmp (arg, "all")) {
      for (tmp_object = ch->carrying; tmp_object; tmp_object = next_obj) {
        next_obj = tmp_object->next_content;
        if (!IS_SET (tmp_object->obj_flags.extra_flags, ITEM_NODROP)) {
          if (CAN_SEE_OBJ (ch, tmp_object)) {
            sprintf (buffer, "You drop the %s.\n\r",
              fname (tmp_object->name));
            send_to_char (buffer, ch);
          } else {
            send_to_char ("You drop something.\n\r", ch);
          }
          act ("$n drops $p.", 1, ch, tmp_object, 0, TO_ROOM);
          obj_from_char (tmp_object);
          obj_to_room (tmp_object, ch->in_room);
          test = TRUE;
        } else {
          if (CAN_SEE_OBJ (ch, tmp_object)) {
            sprintf (buffer, "You can't drop the %s, it must be CURSED!\n\r",
              fname (tmp_object->name));
            send_to_char (buffer, ch);
            test = TRUE;
          }
        }
      }
      if (!test) {
        send_to_char ("You do not seem to have anything.\n\r", ch);
      }
    } else {
      tmp_object = get_obj_in_list_vis (ch, arg, ch->carrying);
      if (tmp_object) {
        if (!IS_SET (tmp_object->obj_flags.extra_flags, ITEM_NODROP)) {
          sprintf (buffer, "You drop the %s.\n\r", fname (tmp_object->name));
          send_to_char (buffer, ch);
          act ("$n drops $p.", 1, ch, tmp_object, 0, TO_ROOM);
          obj_from_char (tmp_object);
          obj_to_room (tmp_object, ch->in_room);
        } else {
          send_to_char ("You can't drop it, it must be CURSED!\n\r", ch);
        }
      } else {
        send_to_char ("You do not have that item.\n\r", ch);
      }
    }
  } else {
    send_to_char ("Drop what?\n\r", ch);
  }
}



void do_put (struct char_data *ch, char *argument, int cmd)
{
  char buffer[MAX_STRING_LENGTH];
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  struct obj_data *obj_object;
  struct obj_data *sub_object;
  struct char_data *tmp_char;
  int bits;

  argument_interpreter (argument, arg1, arg2);
  if (*arg1) {
    if (*arg2) {
      obj_object = get_obj_in_list_vis (ch, arg1, ch->carrying);
      if (obj_object) {
        bits = generic_find (arg2, FIND_OBJ_INV | FIND_OBJ_ROOM,
          ch, &tmp_char, &sub_object);
        if (sub_object) {
          if (GET_ITEM_TYPE (sub_object) == ITEM_CONTAINER) {
            if (!IS_SET (sub_object->obj_flags.value[1], CONT_CLOSED)) {
              if (obj_object == sub_object) {
                send_to_char
                  ("You attempt to fold it into itself, but fail.\n\r", ch);
                return;
              }
              if (((sub_object->obj_flags.weight) +
                  (obj_object->obj_flags.weight)) <
                (sub_object->obj_flags.value[0])) {
                send_to_char ("Ok.\n\r", ch);
                if (bits == FIND_OBJ_INV) {
                  obj_from_char (obj_object);
                  /* make up for above line */
                  IS_CARRYING_W (ch) += GET_OBJ_WEIGHT (obj_object);
/*                obj_from_char(sub_object); do not rearrange order... */
                  obj_to_obj (obj_object, sub_object);
/*                obj_to_char(sub_object,ch);do not rearrange order... */
                } else {
                  obj_from_char (obj_object);
                  /* Do we need obj_from_room? (sub_object,....); */
                  obj_to_obj (obj_object, sub_object);
                  /* Do we need obj_to_room? (sub_object,ch);    */
                }

                act ("$n puts $p in $s $P", TRUE, ch, obj_object, sub_object,
                  TO_ROOM);
              } else {
                send_to_char ("It won't fit.\n\r", ch);
              }
            } else
              send_to_char ("It seems to be closed.\n\r", ch);
          } else {
            sprintf (buffer, "The %s is not a container.\n\r",
              fname (sub_object->name));
            send_to_char (buffer, ch);
          }
        } else {
          sprintf (buffer, "You dont have the %s.\n\r", arg2);
          send_to_char (buffer, ch);
        }
      } else {
        sprintf (buffer, "You dont have the %s.\n\r", arg1);
        send_to_char (buffer, ch);
      }
    } else {
      sprintf (buffer, "Put %s in what?\n\r", arg1);
      send_to_char (buffer, ch);
    }
  } else {
    send_to_char ("Put what in what?\n\r", ch);
  }
}





void do_give (struct char_data *ch, char *argument, int cmd)
{
  char obj_name[80], vict_name[80], buf[MAX_STRING_LENGTH];
  char arg[80];
  int amount;
  struct char_data *vict, *sh;
  struct obj_data *obj;

  argument = one_argument (argument, obj_name);
  if (is_number (obj_name)) {
    amount = atoi (obj_name);
    argument = one_argument (argument, arg);
    if (str_cmp ("coins", arg) && str_cmp ("coin", arg)) {
      send_to_char ("Sorry, you can't do that (yet)...\n\r", ch);
      return;
    }
    if (amount < 0) {
      send_to_char ("Sorry, you can't do that!\n\r", ch);
      return;
    }
    if ((GET_GOLD (ch) < amount) && (IS_NPC (ch) || (GET_LEVEL (ch) < 22))) {
      send_to_char ("You haven't got that many coins!\n\r", ch);
      return;
    }
    argument = one_argument (argument, vict_name);
    if (!*vict_name) {
      send_to_char ("To who?\n\r", ch);
      return;
    }
    if (!(vict = get_char_room_vis (ch, vict_name))) {
      send_to_char ("To who?\n\r", ch);
      return;
    }
    send_to_char ("Ok.\n\r", ch);
    sprintf (buf, "%s gives you %d gold coins.\n\r", PERS (ch, vict), amount);
    send_to_char (buf, vict);
    act ("$n gives some gold to $N.", 1, ch, 0, vict, TO_NOTVICT);
    if (IS_NPC (ch) || (GET_LEVEL (ch) < 22))
      GET_GOLD (ch) -= amount;
    if ((GET_LEVEL (ch) > 20) && (!IS_NPC (ch)) && (!IS_NPC (vict))) {
      sprintf (buf, "%s gives %s %d gold coins.", GET_NAME (ch),
        GET_NAME (vict), amount);
      log (buf);
    }
    GET_GOLD (vict) += amount;
    return;
  }

  argument = one_argument (argument, vict_name);


  if (!*obj_name || !*vict_name) {
    send_to_char ("Give what to who?\n\r", ch);
    return;
  }
  if (!(obj = get_obj_in_list_vis (ch, obj_name, ch->carrying))) {
    send_to_char ("You do not seem to have anything like that.\n\r", ch);
    return;
  }
  if (IS_SET (obj->obj_flags.extra_flags, ITEM_NODROP)) {
    send_to_char ("You can't let go of it! Yeech!!\n\r", ch);
    return;
  }
  if (!(vict = get_char_room_vis (ch, vict_name))) {
    send_to_char ("No one by that name around here.\n\r", ch);
    return;
  }

  if ((1 + IS_CARRYING_N (vict)) > CAN_CARRY_N (vict)) {
    act ("$N seems to have $S hands full.", 0, ch, 0, vict, TO_CHAR);
    return;
  }
  if (obj->obj_flags.weight + IS_CARRYING_W (vict) > CAN_CARRY_W (vict)) {
    act ("$E can't carry that much weight.", 0, ch, 0, vict, TO_CHAR);
    return;
  }
  obj_from_char (obj);
  obj_to_char (obj, vict);
  act ("$n gives $p to $N.", 1, ch, obj, vict, TO_NOTVICT);
  act ("$n gives you $p.", 0, ch, obj, vict, TO_VICT);
  send_to_char ("Ok.\n\r", ch);
}