/
/*! \file randplace.c
 The randplace command is used to randomly place objects or tokens around
 the world in specific areas, on the ground or on mobs, and/or within a
 specified level range.  The immortal must be carrying the objects.

 Syntax : RANDPLACE <n*obj> mob|ground world|area <num>|level <lvl_num>
     World places objects anywhere.
     Area places objects in the area that occurs at position num in the
       area list.
     Level places objects in areas with that level range.
 Example: randplace 25*tokens ground area 7
     will place 25 tokens on the ground randomly in midgaard.

 \author Jon A. Lambert
 \version 1.96
 \date 06/27/2002
 \remarks
    This code copyright (C) 2000-2002 by Jon A. Lambert<BR>
    <antilochos@ix.netcom.com> -  All rights reserved.<BR>
    No part of this code may be used without my written consent.<BR>

This code released to the PUBLIC DOMAIN on 4/2/2006
*/

#include <stdio.h>
#include <stdlib.h>
#include "merc.h"


void do_randplace (CHAR_DATA * ch, char *argument)
{
  extern AREA_DATA *area_first;

  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  char arg3[MAX_INPUT_LENGTH];
  char arg4[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *pmob;
  ROOM_INDEX_DATA *proom = NULL;
  AREA_DATA *parea;
  AREA_DATA *usearea = NULL;
  OBJ_DATA *obj;
  int number, vnumindex, count;
  int in_world = 0;
  int in_area = 0;
  int at_level = 0;
  int level_or_vnum = 0;
  int stop_on;
  int i;

  if (argument == NULL || argument[0] == '\0') {
    send_to_char
      ("Syntax : RANDPLACE <n*obj> mob|ground world|area <num>|level <lvl_num>\r\n",
      ch);
    send_to_char ("    World places objects anywhere.\r\n", ch);
    send_to_char
      ("    Area places objects in the area that occurs at position num in the area list.\r\n",
      ch);
    send_to_char
      ("    Level places objects in areas with that level range.\r\n", ch);
    send_to_char ("Example: randplace 25*tokens ground area 7\r\n", ch);
    send_to_char
      ("    will place 25 tokens on the ground randomly in midgaard.\r\n",
      ch);
    return;
  }

  argument = one_argument (argument, arg1);
  argument = one_argument (argument, arg2);
  argument = one_argument (argument, arg3);
  argument = one_argument (argument, arg4);
  number = mult_argument (arg1, arg1);

  if (number < 1 || number > 50) {
    send_to_char
      ("You can only randomly place between 1 and 50 objects at a time.\r\n",
      ch);
    return;
  }

  if ((obj = get_obj_carry (ch, arg1, ch)) == NULL) {
    send_to_char ("You are not carrying that item.\r\n", ch);
    return;
  }

  if (str_cmp (arg2, "mob")
    && str_cmp (arg2, "ground")) {
    send_to_char
      ("Do you want to place the objects on MOBs or on the GROUND?\r\n", ch);
    return;
  }

  if (str_cmp (arg3, "world")
    && str_cmp (arg3, "area")
    && str_cmp (arg3, "level")) {
    send_to_char
      ("How do you want to place the objects, anywhere in the WORLD, in a specific AREA, or by LEVEL.\r\n",
      ch);
    return;
  }

  if ((arg4 == NULL || arg4[0] == '\0') && str_cmp (arg3, "world")) {
    send_to_char
      ("Last argument  must be a vnum if AREA or level number if LEVEL.\r\n",
      ch);
    return;
  }

  if (is_number (arg4)) {
    level_or_vnum = atoi (arg4);
    if (!str_cmp (arg3, "area")) {
      for (parea = area_first, i = 0; parea != NULL; parea = parea->next, i++) {
        if (level_or_vnum == i) {
          usearea = parea;
          break;
        }
      }
    }
  }

  /* Get counts on possible valid placements */
  if (!str_cmp (arg2, "mob")) {
    for (pmob = char_list; pmob != NULL; pmob = pmob->next) {
      if (!IS_NPC (pmob))
        continue;
      if (IS_SET (pmob->act, ACT_NOPURGE)
        || pmob->pIndexData == NULL
        || pmob->pIndexData->pShop != NULL
        || IS_SET (pmob->imm_flags, IMM_SUMMON)
        || IS_SET (pmob->act, ACT_PET)
        || IS_SET (pmob->affected_by, AFF_CHARM)
        || IS_SET (pmob->act, ACT_IS_HEALER))
        continue;
      in_world++;
      if (pmob->level >= level_or_vnum && pmob->level <= level_or_vnum + 10)
        at_level++;
      if (pmob->in_room && usearea && usearea == pmob->in_room->area)
        in_area++;
    }
  } else {
    for (parea = area_first; parea != NULL; parea = parea->next) {
      for (vnumindex = parea->min_vnum; vnumindex <= parea->max_vnum;
        vnumindex++) {
        if ((proom = get_room_index (vnumindex)) != NULL) {
          if (IS_SET (proom->room_flags, ROOM_IMP_ONLY)
            || IS_SET (proom->room_flags, ROOM_PRIVATE)
            || IS_SET (proom->room_flags, ROOM_GODS_ONLY)
            || proom->clan != 0 || IS_SET (proom->room_flags, ROOM_NOWHERE))
            continue;
          in_world++;
          if (usearea && usearea == parea)
            in_area++;
          if (level_or_vnum >= parea->low_range
            && level_or_vnum <= parea->high_range)
            at_level++;
        }
      }
    }
  }

  count = 0;
  while (count < number) {

    if (!CAN_WEAR (obj, ITEM_TAKE)) {
      act ("$p is not flagged as TAKEable and will not be placed.\r\n", ch,
        obj, 0, TO_CHAR);
      break;
    }

    if (!str_cmp (arg3, "world"))
      stop_on = number_range (1, in_world);
    else if (!str_cmp (arg3, "area"))
      stop_on = number_range (1, in_area);
    else
      stop_on = number_range (1, at_level);

    i = 0;

    if (!str_cmp (arg2, "mob")) {
      if (!str_cmp (arg3, "world")) {
        for (pmob = char_list; pmob != NULL; pmob = pmob->next) {
          if (!IS_NPC (pmob))
            continue;
          if (IS_SET (pmob->act, ACT_NOPURGE)
            || pmob->pIndexData == NULL
            || pmob->pIndexData->pShop != NULL
            || IS_SET (pmob->imm_flags, IMM_SUMMON)
            || IS_SET (pmob->act, ACT_PET)
            || IS_SET (pmob->affected_by, AFF_CHARM)
            || IS_SET (pmob->act, ACT_IS_HEALER))
            continue;
          i++;
          if (stop_on == i)
            break;
        }
      } else if (!str_cmp (arg3, "level")) {
        for (pmob = char_list; pmob != NULL; pmob = pmob->next) {
          if (!IS_NPC (pmob))
            continue;
          if (IS_SET (pmob->act, ACT_NOPURGE)
            || pmob->pIndexData == NULL
            || pmob->pIndexData->pShop != NULL
            || IS_SET (pmob->imm_flags, IMM_SUMMON)
            || IS_SET (pmob->act, ACT_PET)
            || IS_SET (pmob->affected_by, AFF_CHARM)
            || IS_SET (pmob->act, ACT_IS_HEALER))
            continue;
          if (pmob->level >= level_or_vnum &&
            pmob->level <= level_or_vnum + 10)
            i++;
          if (stop_on == i)
            break;
        }
      } else {
        for (pmob = char_list; pmob != NULL; pmob = pmob->next) {
          if (!IS_NPC (pmob))
            continue;
          if (IS_SET (pmob->act, ACT_NOPURGE)
            || pmob->pIndexData == NULL
            || pmob->pIndexData->pShop != NULL
            || IS_SET (pmob->imm_flags, IMM_SUMMON)
            || IS_SET (pmob->act, ACT_PET)
            || IS_SET (pmob->affected_by, AFF_CHARM)
            || IS_SET (pmob->act, ACT_IS_HEALER))
            continue;
          if (pmob->in_room && usearea && usearea == pmob->in_room->area)
            i++;
          if (stop_on == i)
            break;
        }
      }
      if (!pmob)
        return;
      obj_from_char (obj);
      obj_to_char (obj, pmob);
      sprintf (buf, "%s [%d] placed on mob %s [%d].\r\n",
        obj->short_descr, obj->pIndexData->vnum,
        pmob->short_descr, pmob->pIndexData->vnum);
      send_to_char (buf, ch);
    } else {
      bool leave = FALSE;
      if (!str_cmp (arg3, "world")) {
        for (parea = area_first; parea != NULL; parea = parea->next) {
          for (vnumindex = parea->min_vnum; vnumindex <= parea->max_vnum;
            vnumindex++) {
            if ((proom = get_room_index (vnumindex)) != NULL) {
              if (IS_SET (proom->room_flags, ROOM_IMP_ONLY)
                || IS_SET (proom->room_flags, ROOM_PRIVATE)
                || IS_SET (proom->room_flags, ROOM_GODS_ONLY)
                || proom->clan != 0
                || IS_SET (proom->room_flags, ROOM_NOWHERE))
                continue;
              i++;
              if (stop_on == i) {
                leave = TRUE;
                break;
              }
            }
          }
          if (leave)
            break;
        }
      } else if (!str_cmp (arg3, "level")) {
        for (parea = area_first; parea != NULL; parea = parea->next) {
          for (vnumindex = parea->min_vnum; vnumindex <= parea->max_vnum;
            vnumindex++) {
            if ((proom = get_room_index (vnumindex)) != NULL) {
              if (IS_SET (proom->room_flags, ROOM_IMP_ONLY)
                || IS_SET (proom->room_flags, ROOM_PRIVATE)
                || IS_SET (proom->room_flags, ROOM_GODS_ONLY)
                || proom->clan != 0
                || IS_SET (proom->room_flags, ROOM_NOWHERE))
                continue;
              if (level_or_vnum >= parea->low_range
                && level_or_vnum <= parea->high_range)
                i++;
              if (stop_on == i) {
                leave = TRUE;
                break;
              }
            }
          }
          if (leave)
            break;
        }
      } else {
        for (parea = area_first; parea != NULL; parea = parea->next) {
          for (vnumindex = parea->min_vnum; vnumindex <= parea->max_vnum;
            vnumindex++) {
            if ((proom = get_room_index (vnumindex)) != NULL) {
              if (IS_SET (proom->room_flags, ROOM_IMP_ONLY)
                || IS_SET (proom->room_flags, ROOM_PRIVATE)
                || IS_SET (proom->room_flags, ROOM_GODS_ONLY)
                || proom->clan != 0
                || IS_SET (proom->room_flags, ROOM_NOWHERE))
                continue;
              if (usearea && usearea == parea)
                i++;
              if (stop_on == i) {
                leave = TRUE;
                break;
              }
            }
          }
          if (leave)
            break;
        }
      }
      if (!proom)
        return;
      obj_from_char (obj);
      obj_to_room (obj, proom);
      sprintf (buf, "%s [%d] placed in room %s [%d].\r\n",
        obj->short_descr, obj->pIndexData->vnum, proom->name, proom->vnum);
      send_to_char (buf, ch);
    }
    count++;
    obj = get_obj_carry (ch, arg1, ch);
    if (obj == NULL) {
      break;
    }
  }

  return;
}