muddy/
muddy/CVS/
muddy/area/
muddy/area/CVS/
muddy/clans/CVS/
muddy/classes/CVS/
muddy/doc/
muddy/doc/CVS/
muddy/etc/CVS/
muddy/etc/i3/
muddy/etc/i3/CVS/
muddy/imc/CVS/
muddy/lang/CVS/
muddy/licenses/CVS/
muddy/msgdb/CVS/
muddy/new/CVS/
muddy/notes/
muddy/player/
muddy/races/CVS/
muddy/religions/CVS/
muddy/src/CVS/
muddy/src/comm/CVS/
muddy/src/db/CVS/
muddy/src/intermud/
muddy/src/intermud/CVS/
muddy/src/irc/CVS/
muddy/src/olc/CVS/
/*  $Id: olc_area.c,v 1.666 2004/09/20 10:50:30 shrike Exp $ */

/************************************************************************************
 *    Copyright 2004 Astrum Metaphora consortium                                    *
 *                                                                                  *
 *    Licensed under the Apache License, Version 2.0 (the "License");               *
 *    you may not use this file except in compliance with the License.              *
 *    You may obtain a copy of the License at                                       *
 *                                                                                  *
 *    http://www.apache.org/licenses/LICENSE-2.0                                    *
 *                                                                                  *
 *    Unless required by applicable law or agreed to in writing, software           *
 *    distributed under the License is distributed on an "AS IS" BASIS,             *
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      *
 *    See the License for the specific language governing permissions and           *
 *    limitations under the License.                                                *
 *                                                                                  *
 ************************************************************************************/
/************************************************************************************
 *     ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR           *
 *     ANATOLIA has been brought to you by ANATOLIA consortium                      *
 *       Serdar BULUT {Chronos}         bulut@rorqual.cc.metu.edu.tr                *
 *       Ibrahim Canpunar  {Asena}      canpunar@rorqual.cc.metu.edu.tr             *
 *       Murat BICER  {KIO}             mbicer@rorqual.cc.metu.edu.tr               *
 *       D.Baris ACAR {Powerman}        dbacar@rorqual.cc.metu.edu.tr               *
 *     By using this code, you have agreed to follow the terms of the               *
 *     ANATOLIA license, in the file Anatolia/anatolia.licence                      *
 ***********************************************************************************/

/************************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,                 *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.            *
 *                                                                                  *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael                   *
 *  Chastain, Michael Quan, and Mitchell Tse.                                       *
 *                                                                                  *
 *  In order to use any part of this Merc Diku Mud, you must comply with            *
 *  both the original Diku license in 'license.doc' as well the Merc                *
 *  license in 'license.txt'.  In particular, you may not remove either of          *
 *  these copyright notices.                                                        *
 *                                                                                  *
 *  Much time and thought has gone into this software and you are                   *
 *  benefitting.  We hope that you share your changes too.  What goes               *
 *  around, comes around.                                                           *
 ************************************************************************************/

/************************************************************************************
*       ROM 2.4 is copyright 1993-1995 Russ Taylor                                  *
*       ROM has been brought to you by the ROM consortium                           *
*           Russ Taylor (rtaylor@pacinfo.com)                                       *
*           Gabrielle Taylor (gtaylor@pacinfo.com)                                  *
*           Brian Moore (rom@rom.efn.org)                                           *
*       By using this code, you have agreed to follow the terms of the              *
*       ROM license, in the file Rom24/doc/rom.license                              *
*************************************************************************************/

/************************************************************************************
 * Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru>                                      *
 * All rights reserved.                                                             *
 *                                                                                  *
 * Redistribution and use in source and binary forms, with or without               *
 * modification, are permitted provided that the following conditions               *
 * are met:                                                                         *
 * 1. Redistributions of source code must retain the above copyright                *
 *    notice, this list of conditions and the following disclaimer.                 *
 * 2. Redistributions in binary form must reproduce the above copyright             *
 *    notice, this list of conditions and the following disclaimer in the           *
 *    documentation and/or other materials provided with the distribution.          *
 *                                                                                  *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND           *
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE            *
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE       *
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE          *
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL       *
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS          *
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)            *
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT       *
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY        *
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF           *
 * SUCH DAMAGE.                                                                     *
 ************************************************************************************/
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "olc.h"
#include "db/db.h"
#include "conquer.h"

#define EDIT_AREA(ch, area)	(area = (AREA_DATA*) ch->desc->pEdit)

DECLARE_OLC_FUN(areaed_create          );
DECLARE_OLC_FUN(areaed_edit            );
DECLARE_OLC_FUN(areaed_touch           );
DECLARE_OLC_FUN(areaed_show            );
DECLARE_OLC_FUN(areaed_list            );

DECLARE_OLC_FUN(areaed_name            );
DECLARE_OLC_FUN(areaed_mlname          );
DECLARE_OLC_FUN(areaed_file            );
DECLARE_OLC_FUN(areaed_flags           );
DECLARE_OLC_FUN(areaed_age             );
DECLARE_OLC_FUN(areaed_reset           );
DECLARE_OLC_FUN(areaed_security        );
DECLARE_OLC_FUN(areaed_builders        );
DECLARE_OLC_FUN(areaed_resetmsg        );
DECLARE_OLC_FUN(areaed_minvnum         );
DECLARE_OLC_FUN(areaed_maxvnum         );
DECLARE_OLC_FUN(areaed_move            );
DECLARE_OLC_FUN(areaed_credits         );
DECLARE_OLC_FUN(areaed_minlevel        );
DECLARE_OLC_FUN(areaed_maxlevel        );
DECLARE_OLC_FUN(areaed_clan            );
DECLARE_OLC_FUN(areaed_climat          );
DECLARE_OLC_FUN(areaed_maxguards       );
DECLARE_OLC_FUN(areaed_guardrooms      );
DECLARE_OLC_FUN(areaed_explore_req     );
DECLARE_OLC_FUN(areaed_planet          );
DECLARE_OLC_FUN(areaed_timezone        );
DECLARE_OLC_FUN(areaed_xcoordinat      );
DECLARE_OLC_FUN(areaed_ycoordinat      );
DECLARE_OLC_FUN(areaed_zcoordinat      );
DECLARE_OLC_FUN(areaed_breadth         );
DECLARE_OLC_FUN(areaed_longitude       );

DECLARE_VALIDATE_FUN(validate_security	);
DECLARE_VALIDATE_FUN(validate_minvnum	);
DECLARE_VALIDATE_FUN(validate_maxvnum	);
DECLARE_VALIDATE_FUN(validate_move	);
DECLARE_VALIDATE_FUN(validate_maxguards );

olc_cmd_t olc_cmds_area[] =
    {
        { "create",          areaed_create,          5                        },
        { "edit",            areaed_edit,            5                        },
        { "touch",           areaed_touch,           5                        },
        { "show",            areaed_show,            5                        },
        { "list",            areaed_list,            5                        },

        { "name",            areaed_name,            5                        },
        { "mlname",          areaed_mlname,          5                        },
        { "filename",        areaed_file,            5, validate_filename     },
        { "area",            areaed_flags,           5, area_flags            },
        { "age",             areaed_age,             5                        },
        { "reset",           areaed_reset,           0                        },
        { "security",        areaed_security,        5, validate_security     },
        { "builders",        areaed_builders,        5                        },
        { "resetmsg",        areaed_resetmsg,        0                        },
        { "minvnum",         areaed_minvnum,         0, validate_minvnum      },
        { "maxvnum",         areaed_maxvnum,         0, validate_maxvnum      },
        { "move",            areaed_move,            5, validate_move         },
        { "credits",         areaed_credits,         5                        },
        { "minlevel",        areaed_minlevel,        0                        },
        { "maxlevel",        areaed_maxlevel,        0                        },
        { "clan",            areaed_clan,            5                        },

        { "commands",        show_commands,          0                        },
        { "version",         show_version,           0                        },
        { "climat",          areaed_climat,          0, climat_flags          },
        { "planet",          areaed_planet,          0, planet_flags          },
        { "maxguards",       areaed_maxguards,       0, validate_maxguards    },
        { "guardrooms",      areaed_guardrooms,      0                        },
        { "explorereq",      areaed_explore_req,     0                        },
        
        { "longitude",       areaed_longitude,       0                        },
        { "breadth",         areaed_breadth,         0                        },
        { "timezone",        areaed_timezone,        0                        },
        
        { "xcoordinate",     areaed_xcoordinat,      0                        },
        { "ycoordinate",     areaed_ycoordinat,      0                        },
        { "zcoordinate",     areaed_zcoordinat,      0                        },
        
        { NULL }
    };

AREA_DATA *check_range(AREA_DATA *pArea, int ilower, int iupper);

/*
 * Area Editor Functions.
 */
OLC_FUN(areaed_create)
{
    AREA_DATA *pArea;

    if (ch->pcdata->security < SECURITY_AREA_CREATE)
    {
        char_puts("AreaEd: Insufficient security.\n", ch);
        return FALSE;
    }

    pArea			= new_area();
    area_last->next		= pArea;
    area_last		= pArea;	/* Thanks, Walker. */

    ch->desc->pEdit		= (void*) pArea;
    OLCED(ch)   = olced_lookup(ED_AREA);
    touch_area(pArea);
    char_puts("AreaEd: Area created.\n", ch);
    return FALSE;
}

OLC_FUN(areaed_edit)
{
    AREA_DATA *pArea;
    char arg[MAX_STRING_LENGTH];

    one_argument(argument, arg, sizeof(arg));
    if (arg[0] == '\0')
        pArea = ch->in_room->area;
    else if (!is_number(arg) || (pArea = area_lookup(atoi(arg))) == NULL)
    {
        char_puts("AreaEd: That area vnum does not exist.\n", ch);
        return FALSE;
    }

    if (!IS_BUILDER(ch, pArea))
    {
        char_puts("AreaEd: Insufficient security.\n", ch);
        return FALSE;
    }

    ch->desc->pEdit		= (void *) pArea;
    OLCED(ch)   = olced_lookup(ED_AREA);
    return FALSE;
}

OLC_FUN(areaed_touch)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return touch_area(pArea);
}

OLC_FUN(areaed_show)
{
    AREA_DATA *pArea;
    char arg[MAX_STRING_LENGTH];
    int i;
    BUFFER *output;

    one_argument(argument, arg, sizeof(arg));
    if (arg[0] == '\0')
    {
        if (IS_EDIT(ch, ED_AREA))
            EDIT_AREA(ch, pArea);
        else
            pArea = ch->in_room->area;
    }
    else if (!is_number(arg) || (pArea = area_lookup(atoi(arg))) == NULL)
    {
        char_puts("AreaEd: That area vnum does not exist.\n", ch);
        return FALSE;
    }

    if (!IS_BUILDER(ch, pArea))
    {
        char_puts("AreaEd: Insufficient security.\n", ch);
        return FALSE;
    }

    output = buf_new(ch->lang);
    buf_printf(output, "Name:         [%5d] %s\n", pArea->vnum, pArea->name);

    mlstr_dump(output, "ML name: ", pArea->mlname);

    buf_printf(output, "File:         %s\n",       pArea->file_name);
    buf_printf(output, "Version:      [%.2lf]\n",  pArea->version);
    buf_printf(output, "Vnums:        [%d-%d]\n",  pArea->min_vnum, pArea->max_vnum);
    buf_printf(output, "Levels:       [%d-%d]\n",  pArea->min_level, pArea->max_level);
    if (pArea->clan)
        buf_printf(output, "Clan:         [%s]\n",     clan_name(pArea->clan));
    buf_printf(output, "Age:          [%d]\n",     pArea->age);
    buf_printf(output, "Players:      [%d]\n",     pArea->nplayer);
    buf_printf(output, "Security:     [%d]\n",     pArea->security);
    if (!IS_NULLSTR(pArea->builders))
        buf_printf(output, "Builders:     [%s]\n",     pArea->builders);
    buf_printf(output, "Credits:      [%s]\n",     pArea->credits);
    buf_printf(output, "Flags:        [%s]\n",     flag_string(area_flags, pArea->flags));
    buf_printf(output, "Climat:       [%s]\n\r",   flag_string(climat_flags, pArea->climat_type));
    buf_printf(output, "Planet:       [%s]\n\r",   flag_string(planet_flags, pArea->planet));
    buf_printf(output, "Longitude:    [%-2f]\n\r",   pArea->longitude);
    buf_printf(output, "Breadth:      [%-2f]\n\r",   pArea->breadth);
    buf_printf(output, "Time Zone:    [%d]\n\r",   pArea->timezone);
    buf_printf(output, "X Coordinate: [%d]\n\r",  pArea->x_coord);
    buf_printf(output, "Y Coordinate: [%d]\n\r",  pArea->y_coord);
    buf_printf(output, "Z Coordinate: [%d]\n\r",  pArea->z_coord);
    buf_printf(output, "Sun rise/set: [%-2d] [%-2d]\n\r", pArea->sunrise, pArea->sunset);
    buf_printf(output, "MaxGuards:    [%d]\n",     pArea->max_guard_count);
    buf_printf(output, "GuardRooms:   [");

    for (i = 0; i < MAX_GUARD_COUNT; ++i)
        if (pArea->guard_room_vnums[i] != 0)
            buf_printf(output, " %d ", pArea->guard_room_vnums[i]);
    buf_printf(output, "]\n");
    buf_printf(output, "\n");

    switch (pArea->explore_required)
    {
    case EXPLORE_NOT_REQ:
        buf_printf(output, "Explore before conquer: NOT REQUIRED\n");
        break;
    case EXPLORE_GUARDROOMS_REQ:
        buf_printf(output, "Explore before conquer: ROOMS MUST BE EXPLORED\n");
        break;
    case EXPLORE_ALL_AREA_REQ:
        buf_printf(output, "Explore before conquer: WHOLE AREA MUST BE EXPLORED\n");
        break;
    }

    page_to_char(buf_string(output), ch);
    buf_free(output);

    return FALSE;
}

OLC_FUN(areaed_climat)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_flag64(ch, argument, cmd, &pArea->climat_type);
}

OLC_FUN(areaed_planet)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_flag64(ch, argument, cmd, &pArea->planet);
}

OLC_FUN(areaed_list)
{
    char arg[MAX_STRING_LENGTH];
    AREA_DATA *pArea;
    BUFFER *output = NULL;

    one_argument(argument, arg, sizeof(arg));

    for (pArea = area_first; pArea; pArea = pArea->next)
    {
        if (arg[0] != '\0' && !strstr(strlwr(pArea->name), arg))
            continue;

        if (!IS_BUILDER(ch, pArea))
            continue;

        if (output == NULL)
        {
            output = buf_new(-1);
            buf_printf(output, "[%3s] [%-27s] (%-5s-%5s) [%-10s] %3s [%-10s]\n",
                       "Num", "Area Name", "lvnum", "uvnum",
                       "Filename", "Sec", "Builders");
        }

        buf_printf(output, "[%3d] %s (%-5d-%5d) %-12.12s [%d] [%-10.10s]\n",
                   pArea->vnum, fmt_color_str(pArea->name, 29),
                   pArea->min_vnum, pArea->max_vnum,
                   pArea->file_name, pArea->security, pArea->builders);
    }

    if (output != NULL)
    {
        send_to_char(buf_string(output), ch);
        buf_free(output);
    }
    else
        char_puts("No areas with that name found.\n", ch);
    return FALSE;
}

OLC_FUN(areaed_reset)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    reset_area(pArea);
    char_puts("Area reset.\n", ch);
    return FALSE;
}

OLC_FUN(areaed_name)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_str(ch, argument, cmd, &pArea->name);
}

OLC_FUN(areaed_mlname)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_mlstr(ch, argument, cmd, &pArea->mlname);
}

OLC_FUN(areaed_credits)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_str(ch, argument, cmd, &pArea->credits);
}

OLC_FUN(areaed_file)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_str(ch, argument, cmd, &pArea->file_name);
}

OLC_FUN(areaed_age)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->age);
}

OLC_FUN(areaed_longitude)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_double(ch, argument, cmd, &pArea->longitude);
}

OLC_FUN(areaed_breadth)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_double(ch, argument, cmd, &pArea->breadth);
}

OLC_FUN(areaed_timezone)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->timezone);
}


OLC_FUN(areaed_xcoordinat)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->x_coord);
}

OLC_FUN(areaed_ycoordinat)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->y_coord);
}

OLC_FUN(areaed_zcoordinat)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->z_coord);
}

OLC_FUN(areaed_flags)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_flag64(ch, argument, cmd, &pArea->flags);
}

OLC_FUN(areaed_security)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->security);
}

OLC_FUN(areaed_minlevel)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->min_level);
}

OLC_FUN(areaed_maxlevel)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->max_level);
}

OLC_FUN(areaed_resetmsg)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_mlstr(ch, argument, cmd, &pArea->resetmsg);
}

OLC_FUN(areaed_builders)
{
    AREA_DATA *pArea;
    char name[MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    one_argument(argument, name, sizeof(name));
    if (name[0] == '\0')
    {
        do_help(ch, "'OLC AREA BUILDER'");
        return FALSE;
    }
    if (ch->pcdata->security < SECURITY_AREA_CREATE
            && is_name_raw(ch->name, pArea->builders, str_cmp))
    {
        char_puts("AreaEd: Insufficient security.\n", ch);
        return FALSE;
    }
    name_toggle(ch, name, "AreaEd", &pArea->builders);
    return TRUE;
}

OLC_FUN(areaed_minvnum)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->min_vnum);
}

OLC_FUN(areaed_maxvnum)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->max_vnum);
}

OLC_FUN(areaed_move)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->min_vnum);
}

OLC_FUN(areaed_clan)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_clan(ch, argument, cmd, &pArea->clan);
}

OLC_FUN(areaed_maxguards)
{
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);
    return olced_number(ch, argument, cmd, &pArea->max_guard_count);
}

OLC_FUN(areaed_guardrooms)
{

    int val, i;
    char *endptr;
    char arg[MAX_STRING_LENGTH];
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoomIndex;

    EDIT_AREA(ch, pArea);
    one_argument(argument, arg, sizeof(arg));
    val = strtol(arg, &endptr, 0);
    if (*arg == '\0' || *endptr != '\0')
    {
        char_printf(ch, "Syntax: guardroom number\n");
        return FALSE;
    }

    // validator has been placed here, because there is no number_toggle function
    if ((val < pArea->min_vnum) || (val > pArea->max_vnum))
    {
        char_printf(ch, "AEdit: vnum must be between %d and %d for this area.\n",
                    pArea->min_vnum, pArea->max_vnum);
        return FALSE;
    }
    if (!(pRoomIndex = get_room_index(val)))
    {
        char_printf(ch, "AEdit: guardroom vnum %d does not exist.\n", val);
        return FALSE;
    }

    // trying to find vnum. if it exists we have to delete it from array
    for (i=0; i < pArea->max_guard_count; ++i)
    {
        if (pArea->guard_room_vnums[i] == val)
        {
            pArea->guard_room_vnums[i] = 0;
            char_printf(ch, "%d: room vnum deleted.\n", val);
            return TRUE;
        }
    }
    //trying to find empty space for vnum
    for (i=0; i < pArea->max_guard_count; ++i)
    {
        if (pArea->guard_room_vnums[i] == 0)
        {
            pArea->guard_room_vnums[i] = val;
            char_printf(ch, "%d: room vnum added.\n", val);
            return TRUE;
        }
    }
    // vnum does not exist in list and there are no space for adding
    char_printf(ch, "AEdit: room vnums limit reached. Room %d was not added.\n", val);
    return FALSE;
}

OLC_FUN(areaed_explore_req)
{
    char arg[MAX_STRING_LENGTH];
    AREA_DATA *pArea;

    EDIT_AREA(ch, pArea);
    one_argument(argument, arg, sizeof(arg));

    //possible values: no/rooms/all
    if (!str_prefix(arg, "no"))
    {
        pArea->explore_required = EXPLORE_NOT_REQ;
        char_act("Now char must not explore this area before conquer it.", ch);
        return TRUE;
    }
    if (!str_prefix(arg, "rooms"))
    {
        pArea->explore_required = EXPLORE_GUARDROOMS_REQ;
        char_act("Now char must explore guardrooms in this area before conquer it.", ch);
        return TRUE;
    }
    if (!str_prefix(arg, "all"))
    {
        pArea->explore_required = EXPLORE_ALL_AREA_REQ;
        char_act("Now char must completely explore this area before conquer it.", ch);
        return TRUE;
    }

    // incorrect value
    char_printf(ch, "AEdit: %s - incorrect value. Possible values: no/rooms/all.\n", arg);
    return FALSE;

}

/* Validators */

VALIDATE_FUN(validate_security)
{
    int sec = *(int*) arg;
    if (sec > ch->pcdata->security || sec < 0)
    {
        if (ch->pcdata->security != 0)
            char_printf(ch, "AreaEd: Valid security range is 0..%d.\n", ch->pcdata->security);
        else
            char_puts("AreaEd: Valid security is 0 only.\n", ch);
        return FALSE;
    }
    return TRUE;
}

VALIDATE_FUN(validate_minvnum)
{
    int min_vnum = *(int*) arg;
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);

    if (min_vnum && pArea->max_vnum)
    {
        if (min_vnum > pArea->max_vnum)
        {
            char_puts("AreaEd: Min vnum must be less than max vnum.\n", ch);
            return FALSE;
        }

        if (check_range(pArea, min_vnum, pArea->max_vnum))
        {
            char_puts("AreaEd: Range must include only this area.\n", ch);
            return FALSE;
        }
    }
    return TRUE;
}

VALIDATE_FUN(validate_maxvnum)
{
    int max_vnum = *(int*) arg;
    AREA_DATA *pArea;
    EDIT_AREA(ch, pArea);

    if (pArea->min_vnum && max_vnum)
    {
        if (max_vnum < pArea->min_vnum)
        {
            char_puts("AreaEd: Max vnum must be greater than min vnum.\n", ch);
            return FALSE;
        }

        if (check_range(pArea, pArea->min_vnum, max_vnum))
        {
            char_puts("AreaEd: Range must include only this area.\n", ch);
            return FALSE;
        }
    }
    return TRUE;
}

VALIDATE_FUN(validate_maxguards)
{
    int value = *(int*) arg;
    if (value <0 || value > MAX_GUARD_COUNT)
    {
        char_printf(ch, "AEdit: Guard count for area must be between 0 and %d.\n", MAX_GUARD_COUNT);
        return FALSE;
    }
    return TRUE;
}

#define IN_RANGE(i, l, u) ((l) <= (i) && (i) <= (u))
#define MOVE(i) if (IN_RANGE(i, pArea->min_vnum, pArea->max_vnum)) {	\
			i += delta;					\
			touched = TRUE;					\
		}

static void move_mob(MOB_INDEX_DATA *mob, AREA_DATA *pArea, int delta);
static void move_obj(OBJ_INDEX_DATA *obj, AREA_DATA *pArea, int delta);
static void move_room(ROOM_INDEX_DATA *room, AREA_DATA *pArea, int delta);

VALIDATE_FUN(validate_move)
{
    int i;
    int new_min = *(int*) arg;
    int delta;
    bool touched;
    AREA_DATA *pArea;
    MPCODE *mpc;
    clan_t *clan;
    religion_t *religion;
    hometown_t *hometown;
    EDIT_AREA(ch, pArea);

    if (ch->pcdata->security < SECURITY_AREA_CREATE)
    {
        char_puts("AreaEd: Insufficient security.\n", ch);
        return FALSE;
    }

    if (!pArea->min_vnum || !pArea->max_vnum)
    {
        char_puts("AreaEd: Both min_vnum and max_vnum must be set "
                  "in order to perform area vnum move.\n", ch);
        return FALSE;
    }

    /* check new region */
    delta = new_min - pArea->min_vnum;
    if (check_range(pArea, new_min, pArea->max_vnum+delta))
    {
        char_puts("AreaEd: New vnum range overlaps other areas.\n", ch);
        return FALSE;
    }

    /* everything is ok -- change vnums of all rooms, objs, mobs in area */
    /* fix hometowns */
    touched = FALSE;
    for (i = 0; i < hometowns.nused; i++)
    {
        int j;
        bool touched2 = touched;
        touched = FALSE;
        hometown = HOMETOWN(i);
        for (j = 0; j < MAX_ANUM; j++)
        {
            if (IN_RANGE(hometown->recall[j]->vnum, pArea->min_vnum, pArea->max_vnum))
                touched = TRUE;
            if (IN_RANGE(hometown->map[j]->vnum, pArea->min_vnum, pArea->max_vnum))
                touched = TRUE;
            if (IN_RANGE(hometown->altar[j].room->vnum, pArea->min_vnum, pArea->max_vnum))
                touched = TRUE;
            if (IN_RANGE(hometown->altar[j].pit->vnum, pArea->min_vnum, pArea->max_vnum))
                touched = TRUE;
        }
        if (touched)
            touch_hometown(hometown);
        else
            touched = touched2;
    }
    if (touched)
    {
        char_puts("AreaEd: Changed hometowns:\n", ch);
        for (i = 0; i < hometowns.nused; i++)
        {
            hometown = HOMETOWN(i);
            if (IS_SET(hometown->flags, HOMETOWN_CHANGED))
                char_printf(ch, "- %s\n", hometown->area);
        }
    }

    /* fix religion tattoo vnum */
    touched = FALSE;
    for (i = 0; i < religions.nused; i++)
    {
        bool touched2 = touched;
        touched = FALSE;
        religion = RELIGION(i);
        MOVE(religion->tattoo_vnum);
        if (touched)
            touch_religion(religion);
        else
            touched = touched2;
    }
    if (touched)
    {
        char_puts("AreaEd: Changed religions:\n", ch);
        for (i = 0; i < religions.nused; i++)
        {
            religion = RELIGION(i);
            if (IS_SET(religion->flags, RELIGION_CHANGED))
                char_printf(ch, "- %s\n", religion->name);
        }
    }

    /* fix clan recall, item and altar vnums */
    touched = FALSE;
    for (i = 0; i < clans.nused; i++)
    {
        bool touched2 = touched;
        touched = FALSE;
        clan = CLAN(i);
        MOVE(clan->altar_vnum);
        MOVE(clan->recall_vnum);
        MOVE(clan->obj_vnum);
        MOVE(clan->mark_vnum);
        MOVE(clan->altar_trophy_vnum);
        MOVE(clan->item_at);
        if (touched)
            touch_clan(clan);
        else
            touched = touched2;
    }
    if (touched)
    {
        char_puts("AreaEd: Changed clans:\n", ch);
        for (i = 0; i < clans.nused; i++)
        {
            clan = CLAN(i);
            if (IS_SET(clan->flags, CLAN_CHANGED))
                char_printf(ch, "- %s\n", clan->name);
        }
    }

    /* fix mprogs */
    for (mpc = mpcode_list; mpc; mpc = mpc->next)
        MOVE(mpc->vnum);
    /* fix oprogs */
    for (mpc = opcode_list; mpc; mpc = mpc->next)
        MOVE(mpc->vnum);
    /* fix rprogs */
    for (mpc = rpcode_list; mpc; mpc = mpc->next)
        MOVE(mpc->vnum);

    /* fix mobs */
    for (i = 0; i < MAX_KEY_HASH; i++)
    {
        MOB_INDEX_DATA *mob;

        for (mob = mob_index_hash[i]; mob; mob = mob->next)
            move_mob(mob, pArea, delta);
    }

    /* fix objs */
    for (i = 0; i < MAX_KEY_HASH; i++)
    {
        OBJ_INDEX_DATA *obj;

        for (obj = obj_index_hash[i]; obj; obj = obj->next)
            move_obj(obj, pArea, delta);
    }

    /* fix rooms */
    for (i = 0; i < MAX_KEY_HASH; i++)
    {
        ROOM_INDEX_DATA *room;

        for (room = room_index_hash[i]; room; room = room->next)
            move_room(room, pArea, delta);
    }

    /* rebuild mob index hash */
    top_vnum_mob = 0;
    for (i = 0; i < MAX_KEY_HASH; i++)
    {
        MOB_INDEX_DATA *mob, *mob_next, *mob_prev = NULL;

        for (mob = mob_index_hash[i]; mob; mob = mob_next)
        {
            int mob_hash = mob->vnum % MAX_KEY_HASH;
            mob_next = mob->next;

            if (top_vnum_mob < mob->vnum)
                top_vnum_mob = mob->vnum;

            if (mob_hash != i)
            {
                if (!mob_prev)
                    mob_index_hash[i] = mob->next;
                else
                    mob_prev->next = mob->next;
                mob->next = mob_index_hash[mob_hash];
                mob_index_hash[mob_hash] = mob;
            }
            else
                mob_prev = mob;
        }
    }

    /* rebuild obj index hash */
    top_vnum_obj = 0;
    for (i = 0; i < MAX_KEY_HASH; i++)
    {
        OBJ_INDEX_DATA *obj, *obj_next, *obj_prev = NULL;

        for (obj = obj_index_hash[i]; obj; obj = obj_next)
        {
            int obj_hash = obj->vnum % MAX_KEY_HASH;
            obj_next = obj->next;

            if (top_vnum_obj < obj->vnum)
                top_vnum_obj = obj->vnum;

            if (obj_hash != i)
            {
                if (!obj_prev)
                    obj_index_hash[i] = obj->next;
                else
                    obj_prev->next = obj->next;
                obj->next = obj_index_hash[obj_hash];
                obj_index_hash[obj_hash] = obj;
            }
            else
                obj_prev = obj;
        }
    }

    /* rebuild room index hash */
    top_vnum_room = 0;
    for (i = 0; i < MAX_KEY_HASH; i++)
    {
        ROOM_INDEX_DATA *room, *room_next, *room_prev = NULL;

        for (room = room_index_hash[i]; room; room = room_next)
        {
            int room_hash = room->vnum % MAX_KEY_HASH;
            room_next = room->next;

            if (top_vnum_room < room->vnum)
                top_vnum_room = room->vnum;

            if (room_hash != i)
            {
                if (!room_prev)
                    room_index_hash[i] = room->next;
                else
                    room_prev->next = room->next;
                room->next = room_index_hash[room_hash];
                room_index_hash[room_hash] = room;
            }
            else
                room_prev = room;
        }
    }

    pArea->max_vnum += delta;
    touch_area(pArea);

    char_puts("AreaEd: Changed areas:\n", ch);
    for (pArea = area_first; pArea; pArea = pArea->next)
        if (IS_SET(pArea->flags, AREA_CHANGED))
            char_printf(ch, "[%3d] %s (%s)\n",
                        pArea->vnum, pArea->name, pArea->file_name);
    return TRUE;
}

/* Local functions */

/*****************************************************************************
 Name:		check_range(lower vnum, upper vnum)
 Purpose:	Ensures the range spans only one area.
 Called by:	areaed_vnum(olc_act.c).
 ****************************************************************************/
AREA_DATA *check_range(AREA_DATA *this, int ilower, int iupper)
{
    AREA_DATA *pArea;

    for (pArea = area_first; pArea; pArea = pArea->next)
    {
        if (pArea == this || !pArea->min_vnum || !pArea->max_vnum)
            continue;
        if (IN_RANGE(ilower, pArea->min_vnum, pArea->max_vnum)
                ||  IN_RANGE(iupper, pArea->min_vnum, pArea->max_vnum)
                ||  IN_RANGE(pArea->min_vnum, ilower, iupper)
                ||  IN_RANGE(pArea->max_vnum, ilower, iupper))
            return pArea;
    }
    return NULL;
}

static void move_mob(MOB_INDEX_DATA *mob, AREA_DATA *pArea, int delta)
{
    bool touched = FALSE;
    MPTRIG *mp;
    int old_vnum = mob->vnum;

    MOVE(mob->vnum);

    if (mob->pShop)
        MOVE(mob->pShop->keeper);

    for (mp = mob->mptrig_list; mp; mp = mp->next)
        MOVE(mp->vnum);

    //	MOVE(mob->fvnum);

    /* touch area if it is not area being moved */
    if (touched && !IN_RANGE(old_vnum, pArea->min_vnum, pArea->max_vnum))
        touch_vnum(old_vnum);
}

static void move_obj(OBJ_INDEX_DATA *obj, AREA_DATA *pArea, int delta)
{
    bool touched = FALSE;
    int old_vnum = obj->vnum;

    /* fix containers */
    switch (obj->item_type)
    {
    case ITEM_CONTAINER:
        MOVE(obj->value[2]);
        if (touched)
        {
            OBJ_DATA *o;

            for (o = object_list; o; o = o->next)
                if (o->pIndexData == obj)
                    o->value[2] += delta;
        }
    }

    MOVE(obj->vnum);

    /* touch area if it is not area being moved */
    if (touched && !IN_RANGE(old_vnum, pArea->min_vnum, pArea->max_vnum))
        touch_vnum(old_vnum);
}

static void move_room(ROOM_INDEX_DATA *room, AREA_DATA *pArea, int delta)
{
    int i;
    bool touched = FALSE;
    int old_vnum = room->vnum;
    RESET_DATA *r;

    MOVE(room->vnum);

    for (i = 0; i < MAX_DIR; i++)
    {
        EXIT_DATA *pExit = room->exit[i];

        if (!pExit || !pExit->to_room.r)
            continue;

        if (IN_RANGE(pExit->to_room.r->vnum, pArea->min_vnum+delta,
                     pArea->max_vnum+delta))
            touched = TRUE;
        // Welesh : added for connected areas conversion
        if (IN_RANGE(pExit->to_room.r->vnum, pArea->min_vnum,
                     pArea->max_vnum))
        {
            pExit->to_room.r->vnum += delta;
            touched = TRUE;
        }
        // end-added
    }

    for (r = room->reset_first; r; r = r->next)
    {
        switch (r->command)
        {
        case 'M':
        case 'O':
        case 'P':
            MOVE(r->arg1);
            MOVE(r->arg3);
            break;

        case 'G':
        case 'E':
        case 'D':
        case 'R':
            MOVE(r->arg1);
            break;
        }
    }

    /* touch area if it is not area being moved */
    if (touched && !IN_RANGE(old_vnum, pArea->min_vnum, pArea->max_vnum))
        touch_vnum(old_vnum);
}