/******************************************************************************
 Snippet: Wilderness system (v1.0).
 Author:  Richard Woolcock (aka KaVir).
 Date:    2nd September 1998.
 ******************************************************************************
 File:    wild_update.c
 Purpose: Deals with the wilderness update routine.
 ******************************************************************************
 This code is copyright (C) 1998 by Richard Woolcock.  It may be used and
 distributed freely, as long as you do not remove this copyright notice.
 ******************************************************************************/

/******************************************************************************
 Required libraries
 ******************************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "wild.h"

/******************************************************************************
 Local operation prototypes
 ******************************************************************************/

void	auto_chopping	args( ( CHAR_DATA *ch ) );
void	auto_trim	args( ( CHAR_DATA *ch ) );
void	auto_fishing	args( ( CHAR_DATA *ch ) );
void	auto_digging	args( ( CHAR_DATA *ch ) );
void	auto_saw	args( ( CHAR_DATA *ch ) );
void	auto_build	args( ( CHAR_DATA *ch ) );
void	auto_mining	args( ( CHAR_DATA *ch ) );
void	auto_hoe	args( ( CHAR_DATA *ch ) );
void	auto_seed	args( ( CHAR_DATA *ch ) );
void	auto_scythe	args( ( CHAR_DATA *ch ) );
void	auto_road	args( ( CHAR_DATA *ch ) );
void	make_resource	args( ( CHAR_DATA *ch, RESOURCE_TYPE resource ) );

/******************************************************************************
 Global operations
 ******************************************************************************/

void wilderness_update( void )
{
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    static int loop_x = 0;
    static int loop_y = 0;
    int update_x = 0;
    static int update_y = 0;
    extern CHAR_DATA *first_wilderness;

    for ( update_x = 0; update_x < 1000; update_x++ )
    {
	int xx = update_x;
	int yy = update_y;
	switch (map_data(update_x,update_y))
	{
	    default: break;
	    case WILD_FIELD_SEEDED: 
		set_map_data(update_x, update_y, WILD_FIELD_WHEAT);
		break;
	    case WILD_FOREST_1: 
		if (number_range(1,3) == 1) 
		    set_map_data(update_x, update_y, WILD_FOREST_2);
		break;
	    case WILD_FOREST_2: 
		if (number_range(1,3) == 1) 
		    set_map_data(update_x, update_y, WILD_FOREST_3);
		break;
	    case WILD_FOREST_3: 
		if (number_range(1,3) == 1) 
		    set_map_data(update_x, update_y, WILD_FOREST_4);
		break;
	    case WILD_FOREST_4:
		if (number_range(1,3) == 1) 
		{
		    switch (number_range(1,4))
		    {
			default:
			case 1: if (++xx >= 1000) xx = 0;   break;
			case 2: if (--xx <     0) xx = 999; break;
			case 3: if (++yy >= 1000) yy = 0;   break;
			case 4: if (--yy <     0) yy = 999; break;
		    }
		    switch (map_data(xx, yy))
		    {
			default: break;
			case WILD_PLAINS:
			    set_map_data(update_x, update_y, WILD_FOREST_1);
			    break;
			case WILD_FOREST_1:
			    set_map_data(update_x, update_y, WILD_FOREST_2);
			    break;
			case WILD_FOREST_2:
			    set_map_data(update_x, update_y, WILD_FOREST_3);
			    break;
			case WILD_FOREST_3:
			    set_map_data(update_x, update_y, WILD_FOREST_4);
			    break;
		    }
		}
		break;
	}
    }
    if ( ++update_y >= 1000 ) update_y = 0;

    if (check_world_saving())
    {
	if ( map_changed(loop_x, loop_y) == TRUE )
	{
	    wild_write( loop_x, loop_y );
	    set_map_changed(loop_x, loop_y, FALSE);
	}

	if ( ++loop_x >= 10 )
	{
	    loop_x = 0;
	    if ( ++loop_y >= 10 )
	    {
		loop_y = 0;
	    }
	}
    }

    for ( ch = first_wilderness; ch != NULL; ch = ch_next )
    {
	ch_next = ch->next_wilderness;
	if (ch->action == WA_NONE) continue;
	switch (ch->action)
	{
	    default: break;
	    case WA_CHOPPING_SWING:
	    case WA_CHOPPING_CHOP:
		auto_chopping(ch);
		break;
	    case WA_TRIM:
		auto_trim(ch);
		break;
	    case WA_FISHING_MENDING:
	    case WA_FISHING_CASTING:
	    case WA_FISHING_WAITING:
	    case WA_FISHING_REELING:
		auto_fishing(ch);
		break;
	    case WA_DIGGING_SWING:
	    case WA_DIGGING_CHOP:
		auto_digging(ch);
		break;
	    case WA_BUILDING_FOUNDATION:
	    case WA_BUILDING_FLOOR_1:
	    case WA_BUILDING_FLOOR_2:
	    case WA_BUILDING_FLOOR_3:
	    case WA_BUILDING_1:
	    case WA_BUILDING_2:
	    case WA_BUILDING_3:
	    case WA_BUILDING_ROOF_1:
	    case WA_BUILDING_ROOF_2:
	    case WA_BUILDING_ROOF_3:
	    case WA_BUILDING_COMPLETE:
		auto_build(ch);
		break;
	    case WA_SAW:
		auto_saw(ch);
		break;
	    case WA_MINING_SWING:
	    case WA_MINING_CHOP:
		auto_mining(ch);
		break;
	    case WA_HOE:
		auto_hoe(ch);
		break;
	    case WA_SEED:
		auto_seed(ch);
		break;
	    case WA_SCYTHE:
		auto_scythe(ch);
		break;
	    case WA_ROAD:
		auto_road(ch);
		break;
	}
    }

    return;
}

/******************************************************************************
 Local operations
 ******************************************************************************/

void auto_trim( CHAR_DATA *ch )
{
    OBJ_DATA *knife;
    OBJ_DATA *obj;

    if ( ( obj = get_obj_here( ch, "tree" ) ) == NULL )
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( obj->item_type != ITEM_RESOURCE || obj->value[1] != RESOURCE_TREE )
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( ( knife = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	knife->item_type != ITEM_WEAPON || knife->value[3] != 3 )
    {
	if ( ( knife = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    knife->item_type != ITEM_WEAPON || knife->value[3] != 3 )
	{
	    send_to_char("You need to hold a slashing weapon to trim trees.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }
    switch (number_range(1,3))
    {
	default:
	case 1:
	case 2:
	    act("You scrape $p along a tree, slashing off a branch.",ch,knife,NULL,TO_CHAR);
	    act("$n scrapes $p along a tree, slashing off a branch.",ch,knife,NULL,TO_ROOM);
	    break;
	case 3:
	    act("You scrape $p along a tree, slashing off some leaves.",ch,knife,NULL,TO_CHAR);
	    act("$n scrapes $p along a tree, slashing off some leaves.",ch,knife,NULL,TO_ROOM);
	    ch->state += get_curr_dex(ch);
	    if (ch->state >= ch->quality)
	    {
		act("You have finished trimming $p.",ch,obj,NULL,TO_CHAR);
		act("$n has finished trimming $p.",ch,obj,NULL,TO_ROOM);
		free_string(obj->name);
		obj->name = str_dup("log");
		free_string(obj->short_descr);
		obj->short_descr = str_dup("a log");
		free_string(obj->description);
		obj->description = str_dup("A log is lying here.");
		obj->weight -= 5;
		obj->value[0] = obj->weight;
		obj->value[1] = RESOURCE_LOG;
		if (obj->weight < 20) obj->weight = 20;
		ch->action = WA_NONE;
		ch->state = 0;
		ch->quality = 0;
	    }
	    break;
    }
}

void auto_saw( CHAR_DATA *ch )
{
    OBJ_DATA *saw;
    OBJ_DATA *obj;

    if ( ( obj = get_obj_here( ch, "log" ) ) == NULL )
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( obj->item_type != ITEM_RESOURCE || obj->value[1] != RESOURCE_LOG )
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( ( saw = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	saw->item_type != ITEM_TOOL || saw->value[0] != TOOL_SAW )
    {
	if ( ( saw = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    saw->item_type != ITEM_TOOL || saw->value[0] != TOOL_SAW )
	{
	    send_to_char("You need to hold a saw to saw up logs.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    act("You run $p back and forth across the log.",ch,saw,NULL,TO_CHAR);
    act("$n runs $p back and forth across the log.",ch,saw,NULL,TO_ROOM);
    ch->state += get_curr_str(ch);
    if (ch->state >= ch->quality)
    {
	act("You have finished sawing up $p.",ch,obj,NULL,TO_CHAR);
	act("$n has finished sawing up $p.",ch,obj,NULL,TO_ROOM);
	send_to_char("The wood has been added to rooms resources, and will remain as long as there\n\r",ch);
	send_to_char("is someone in the room or the wood is used up.\n\r",ch);
	ch->in_room->wood += obj->weight;
	extract_obj(obj);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
    }
}

void auto_road( CHAR_DATA *ch )
{
    OBJ_DATA *obj;
    bool in_plains = FALSE;

    if (ch->x >= 0 || ch->y >= 0) switch (map_data(ch->x,ch->y))
    {
	default: break;
	case WILD_PLAINS:
	    in_plains = TRUE;
	    break;
    }

    if (!in_plains)
    {
	send_to_char("You cannot lay a road here.\n\r",ch);
	return;
    }

    if ( ( obj = get_obj_here( ch, "stone" ) ) == NULL )
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( obj->item_type != ITEM_RESOURCE || obj->value[1] != RESOURCE_ROCK )
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if (get_eq_char(ch, WEAR_WIELD) != NULL ||
	get_eq_char(ch, WEAR_HOLD ) != NULL )
    {
	send_to_char("You need two free hands to lay a road.\n\r",ch);
	return;
    }

    act("You place $p into the ground.",ch,obj,NULL,TO_CHAR);
    act("$n places $p into the ground.",ch,obj,NULL,TO_ROOM);
    ch->in_room->ground += obj->value[0];
    extract_obj(obj);

    if (ch->in_room->ground >= 100)
    {
	act("You have finished laying the road.",ch,NULL,NULL,TO_CHAR);
	act("$n has finished laying the road.",ch,NULL,NULL,TO_ROOM);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	set_map_data(ch->x, ch->y, WILD_ROAD);
	do_wsave(ch,"zone");
    }
}

void auto_hoe( CHAR_DATA *ch )
{
    OBJ_DATA *hoe;

    if ( ( hoe = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	hoe->item_type != ITEM_TOOL || hoe->value[0] != TOOL_HOE )
    {
	if ( ( hoe = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    hoe->item_type != ITEM_TOOL || hoe->value[0] != TOOL_HOE )
	{
	    send_to_char("You need to hold a hoe to hoe a field.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    act("You push $p through the soil.",ch,hoe,NULL,TO_CHAR);
    act("$n pushes $p through the soil.",ch,hoe,NULL,TO_ROOM);

    ch->in_room->ground += get_curr_str(ch);
    if (ch->in_room->ground >= 100)
    {
	act("You have finished hoeing the field.",ch,NULL,NULL,TO_CHAR);
	act("$n has finished hoeing the field.",ch,NULL,NULL,TO_ROOM);
	set_map_data(ch->x, ch->y, WILD_FIELD_HOED);
	ch->in_room->ground = 0;
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
    }
}

void auto_seed( CHAR_DATA *ch )
{
    OBJ_DATA *bag;

    if ( ( bag = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	bag->item_type != ITEM_TOOL || bag->value[0] != TOOL_SEEDS )
    {
	if ( ( bag = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    bag->item_type != ITEM_TOOL || bag->value[0] != TOOL_SEEDS )
	{
	    send_to_char("You need to hold some seeds to seed a field.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    act("You reach into $p and scatter a handful over the soil.",ch,bag,NULL,TO_CHAR);
    act("$n reaches into $p and scatters a handful over the soil.",ch,bag,NULL,TO_ROOM);

    ch->in_room->ground += number_range(1,3);
    if (ch->in_room->ground >= 20)
    {
	act("You have finished seeding the field.",ch,NULL,NULL,TO_CHAR);
	act("$n has finished seeding the field.",ch,NULL,NULL,TO_ROOM);
	set_map_data(ch->x, ch->y, WILD_FIELD_SEEDED);
	ch->in_room->ground = 0;
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
    }
    if (--bag->value[1] <= 0)
    {
	act("You throw away $p, having used all the seeds.",ch,bag,NULL,TO_CHAR);
	act("$n throws away $p, having used all the seeds.",ch,bag,NULL,TO_ROOM);
	extract_obj(bag);
    }
}

void auto_scythe( CHAR_DATA *ch )
{
    OBJ_DATA *scythe;

    if ( ( scythe = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	scythe->item_type != ITEM_TOOL || scythe->value[0] != TOOL_SCYTHE )
    {
	if ( ( scythe = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    scythe->item_type != ITEM_TOOL || scythe->value[0] != TOOL_SCYTHE )
	{
	    send_to_char("You need to hold a scythe to chop down wheat.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    act("You sweep $p through the wheat.",ch,scythe,NULL,TO_CHAR);
    act("$n sweeps $p through the wheat.",ch,scythe,NULL,TO_ROOM);

    ch->in_room->ground += number_range(1,3);
    if (ch->in_room->ground >= 20)
    {
	act("You have finished scything the field.",ch,NULL,NULL,TO_CHAR);
	act("$n has finished scything the field.",ch,NULL,NULL,TO_ROOM);
	set_map_data(ch->x, ch->y, WILD_PLAINS);
	do_wsave(ch,"zone");
	ch->in_room->ground = 0;
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	make_resource(ch, RESOURCE_WHEAT);
    }
}

void auto_mining( CHAR_DATA *ch )
{
    OBJ_DATA *pick;
    int improve_state;

    if ( ( pick = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	pick->item_type != ITEM_TOOL || pick->value[0] != TOOL_PICK )
    {
	if ( ( pick = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    pick->item_type != ITEM_TOOL || pick->value[0] != TOOL_PICK )
	{
	    send_to_char("You need to hold a pick to do some mining.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    switch (ch->action)
    {
	default:
	case WA_MINING_SWING:
	    act("You tear $p out of the wall.",ch,pick,NULL,TO_CHAR);
	    act("$n tears $p out of the wall.",ch,pick,NULL,TO_ROOM);
	    ch->action = WA_MINING_CHOP;
	    improve_state = get_curr_str(ch);
	    ch->state += improve_state;
	    if (ch->state >= ch->quality)
	    {
		switch (map_data(ch->x,ch->y))
		{
		    default:
		    case WILD_MINE_EMPTY:
			send_to_char("You realise that this mine has been exhausted of all resources.\n\r",ch);
			break;
		    case WILD_MINE_STONE_1:
		    case WILD_MINE_STONE_2:
			send_to_char("A large piece of rock falls out of the wall!\n\r",ch);
			act("A large piece of rock falls out of the wall!",ch,NULL,NULL,TO_ROOM);
			make_resource(ch, RESOURCE_ROCK);
			break;
		    case WILD_MINE_IRON_1:
		    case WILD_MINE_IRON_2:
			send_to_char("A large chunk of iron ore falls out of the wall!\n\r",ch);
			act("A large chuck of iron ore falls out of the wall!",ch,NULL,NULL,TO_ROOM);
			make_resource(ch, RESOURCE_IRON);
			break;
		    case WILD_MINE_GOLD_1:
		    case WILD_MINE_GOLD_2:
			send_to_char("A nugget of gold ore falls out of the wall!\n\r",ch);
			act("A nugget of gold ore falls out of the wall!",ch,NULL,NULL,TO_ROOM);
			make_resource(ch, RESOURCE_GOLD);
			break;
		    case WILD_MINE_OIL_1:
		    case WILD_MINE_OIL_2:
			send_to_char("A stream of oil pours out of the wall!\n\r",ch);
			act("A stream of oil pours out of the wall!",ch,NULL,NULL,TO_ROOM);
			make_resource(ch, RESOURCE_OIL);
			break;
		}
		ch->action = WA_NONE;
		ch->state = 0;
		ch->quality = 0;
		if (number_range(1,10) == 1) switch (map_data(ch->x,ch->y))
		{
		    default: break;
		    case WILD_MINE_STONE_1:
		    case WILD_MINE_IRON_1:
		    case WILD_MINE_GOLD_1:
		    case WILD_MINE_OIL_1:
			set_map_data(ch->x, ch->y, WILD_MINE_EMPTY);
			break;
		    case WILD_MINE_STONE_2:
			set_map_data(ch->x, ch->y, WILD_MINE_STONE_1);
			break;
		    case WILD_MINE_IRON_2:
			set_map_data(ch->x, ch->y, WILD_MINE_IRON_1);
			break;
		    case WILD_MINE_GOLD_2:
			set_map_data(ch->x, ch->y, WILD_MINE_GOLD_1);
			break;
		    case WILD_MINE_OIL_2:
			set_map_data(ch->x, ch->y, WILD_MINE_OIL_1);
			break;
		}
	    }
	    break;
	case WA_MINING_CHOP:
	    act("You swing $p into the wall.",ch,pick,NULL,TO_CHAR);
	    act("$n swings $p into the wall.",ch,pick,NULL,TO_ROOM);
	    ch->action = WA_MINING_SWING;
	    break;
    }
    return;
}

void auto_build( CHAR_DATA *ch )
{
    OBJ_DATA * hammer;
    OBJ_DATA * obj;
    int        resources;
    char       map_pos;
    int        change;

    if (ch->x >= 0 && ch->y >= 0) 
	map_pos = map_data(ch->x,ch->y);
    else
    {
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if (ch->in_room->ground > 0)
    {
	send_to_char("Someone has already started building a road here.\n\r",ch);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if (ch->in_room->build <= 0)
    {
	send_to_char("The building is complete.\n\r",ch);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if (ch->in_room->wood <= 0)
    {
	send_to_char("There is no more wood left in the room.\n\r",ch);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( ( hammer = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	hammer->item_type != ITEM_TOOL || hammer->value[0] != TOOL_HAMMER )
    {
	if ( ( hammer = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    hammer->item_type != ITEM_TOOL || hammer->value[0] != TOOL_HAMMER )
	{
	    send_to_char("You need a hammer to build.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    if ( ( obj = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	obj->item_type != ITEM_TOOL || obj->value[0] != TOOL_NAILS )
    {
	if ( ( obj = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    obj->item_type != ITEM_TOOL || obj->value[0] != TOOL_NAILS )
	{
	    send_to_char("You need some nails to build.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }

    switch (map_pos)
    {
	default:
	case WILD_PLAINS:		  resources = 100; break;
	case WILD_BUILDING_CONSTRUCTION:  resources = 100; break;
	case WILD_HUT:     
	case WILD_HUT_OWNED:     
	case WILD_HUT_LOCKED:		  resources = 200; break;
	case WILD_CABIN:   
	case WILD_CABIN_OWNED:   
	case WILD_CABIN_LOCKED:	 	  resources = 400; break;
	case WILD_COTTAGE: 
	case WILD_COTTAGE_OWNED: 
	case WILD_COTTAGE_LOCKED:	  resources = 600; break;
	case WILD_MOUNTAINS_NONE:
	case WILD_MOUNTAINS_STONE:
	case WILD_MOUNTAINS_IRON:
	case WILD_MOUNTAINS_GOLD:
	case WILD_MOUNTAINS_OIL:	  resources = 50;  break;
    }

    --ch->in_room->wood;
    ++ch->in_room->build;

    change = ch->in_room->build * 100 / resources;

    switch (ch->action)
    {
	case WA_BUILDING_FOUNDATION:
	    act("You pick up a wooden beam and push it into the ground.",ch,NULL,NULL,TO_CHAR);
	    act("$n picks up a wooden beam and pushes it into the ground.",ch,NULL,NULL,TO_ROOM);
	    if (map_pos == WILD_PLAINS)
	    {
		set_map_data(ch->x, ch->y, WILD_BUILDING_CONSTRUCTION);
		do_wsave(ch,"zone");
	    }
	    if (change >= 10) ch->action = WA_BUILDING_FLOOR_1;
	    break;
	case WA_BUILDING_FLOOR_1:
	    act("You pick up a plank of wood and place it across the ground.",ch,NULL,NULL,TO_CHAR);
	    act("$n picks up a plank of wood and places it across the ground.",ch,NULL,NULL,TO_ROOM);
	    ch->action = WA_BUILDING_FLOOR_2;
	    break;
	case WA_BUILDING_FLOOR_2:
	    act("You reach into $p and take out some nails.",ch,obj,NULL,TO_CHAR);
	    act("$n reaches into $p and takes out some nails.",ch,obj,NULL,TO_ROOM);
	    ch->action = WA_BUILDING_FLOOR_3;
	    break;
	case WA_BUILDING_FLOOR_3:
	    act("You hammer some nails into the floor with $p.",ch,hammer,NULL,TO_CHAR);
	    act("$n hammers some nails into the floor with $p.",ch,hammer,NULL,TO_ROOM);
	    if (number_range(1,3) == 1) ch->action = WA_BUILDING_FLOOR_2;
	    if (change >= 20) ch->action = WA_BUILDING_1;
	    if (--obj->value[1] <= 0)
	    {
		act("You throw away $p, having used all the nails.",ch,obj,NULL,TO_CHAR);
		act("$n throws away $p, having used all the nails.",ch,obj,NULL,TO_ROOM);
		extract_obj(obj);
	    }
	    break;
	case WA_BUILDING_1:
	    act("You pick up a plank of wood and place it against the wooden structure.",ch,NULL,NULL,TO_CHAR);
	    act("$n picks up a plank of wood and places it against the wooden structure.",ch,NULL,NULL,TO_ROOM);
	    ch->action = WA_BUILDING_2;
	    break;
	case WA_BUILDING_2:
	    act("You reach into $p and take out some nails.",ch,obj,NULL,TO_CHAR);
	    act("$n reaches into $p and takes out some nails.",ch,obj,NULL,TO_ROOM);
	    ch->action = WA_BUILDING_3;
	    break;
	case WA_BUILDING_3:
	    act("You hammer some nails into the wall with $p.",ch,hammer,NULL,TO_CHAR);
	    act("$n hammers some nails into the wall with $p.",ch,hammer,NULL,TO_ROOM);
	    if (number_range(1,3) == 1) ch->action = WA_BUILDING_2;
	    if (change >= 90) ch->action = WA_BUILDING_ROOF_1;
	    if (--obj->value[1] <= 0)
	    {
		act("You throw away $p, having used all the nails.",ch,obj,NULL,TO_CHAR);
		act("$n throws away $p, having used all the nails.",ch,obj,NULL,TO_ROOM);
		extract_obj(obj);
	    }
	    break;
	case WA_BUILDING_ROOF_1:
	    act("You pick up a plank of wood and place it across the roof.",ch,NULL,NULL,TO_CHAR);
	    act("$n picks up a plank of wood and places it across the roof.",ch,NULL,NULL,TO_ROOM);
	    ch->action = WA_BUILDING_ROOF_2;
	    break;
	case WA_BUILDING_ROOF_2:
	    act("You reach into $p and take out some nails.",ch,obj,NULL,TO_CHAR);
	    act("$n reaches into $p and takes out some nails.",ch,obj,NULL,TO_ROOM);
	    ch->action = WA_BUILDING_ROOF_3;
	    break;
	case WA_BUILDING_ROOF_3:
	    act("You hammer some nails into the roof with $p.",ch,hammer,NULL,TO_CHAR);
	    act("$n hammers some nails into the roof with $p.",ch,hammer,NULL,TO_ROOM);
	    if (number_range(1,3) == 1) ch->action = WA_BUILDING_ROOF_2;
	    if (change >= 100) ch->action = WA_BUILDING_COMPLETE;
	    if (--obj->value[1] <= 0)
	    {
		act("You throw away $p, having used all the nails.",ch,obj,NULL,TO_CHAR);
		act("$n throws away $p, having used all the nails.",ch,obj,NULL,TO_ROOM);
		extract_obj(obj);
	    }
	    break;
	case WA_BUILDING_COMPLETE:
	    act("You hammer the final nail into the building!",ch,NULL,NULL,TO_CHAR);
	    act("$n hammers the final nail into the building!",ch,NULL,NULL,TO_ROOM);
	    if (--obj->value[1] <= 0)
	    {
		act("You throw away $p, having used all the nails.",ch,obj,NULL,TO_CHAR);
		act("$n throws away $p, having used all the nails.",ch,obj,NULL,TO_ROOM);
		extract_obj(obj);
	    }
	    break;
    }

    if ( ch->action != WA_BUILDING_COMPLETE )
    {
	return;
    }

    ch->in_room->build = 0;

    switch (map_pos)
    {
	default:
	case WILD_PLAINS:
	case WILD_BUILDING_CONSTRUCTION:
	    set_map_data(ch->x, ch->y, WILD_HUT);
	    break;
	case WILD_HUT:
	    set_map_data(ch->x, ch->y, WILD_CABIN);
	    break;
	case WILD_HUT_OWNED:
	    set_map_data(ch->x, ch->y, WILD_CABIN_OWNED);
	    break;
	case WILD_HUT_LOCKED:
	    set_map_data(ch->x, ch->y, WILD_CABIN_LOCKED);
	    break;
	case WILD_CABIN:
	    set_map_data(ch->x, ch->y, WILD_COTTAGE);
	    break;
	case WILD_CABIN_OWNED:
	    set_map_data(ch->x, ch->y, WILD_COTTAGE_OWNED);
	    break;
	case WILD_CABIN_LOCKED:
	    set_map_data(ch->x, ch->y, WILD_COTTAGE_LOCKED);
	    break;
	case WILD_COTTAGE:
	    set_map_data(ch->x, ch->y, WILD_HOUSE);
	    break;
	case WILD_COTTAGE_OWNED:
	    set_map_data(ch->x, ch->y, WILD_HOUSE_OWNED);
	    break;
	case WILD_COTTAGE_LOCKED:
	    set_map_data(ch->x, ch->y, WILD_HOUSE_LOCKED);
	    break;
	case WILD_MOUNTAINS_NONE:
	    set_map_data(ch->x, ch->y, WILD_MINE_STRUCTURE_EMPTY);
	    break;
	case WILD_MOUNTAINS_STONE:
	    set_map_data(ch->x, ch->y, WILD_MINE_STRUCTURE_STONE);
	    break;
	case WILD_MOUNTAINS_IRON:
	    set_map_data(ch->x, ch->y, WILD_MINE_STRUCTURE_IRON);
	    break;
	case WILD_MOUNTAINS_GOLD:
	    set_map_data(ch->x, ch->y, WILD_MINE_STRUCTURE_GOLD);
	    break;
	case WILD_MOUNTAINS_OIL:
	    set_map_data(ch->x, ch->y, WILD_MINE_STRUCTURE_OIL);
	    break;
    }
    do_wsave(ch,"zone");
    return;
}

void auto_chopping( CHAR_DATA *ch )
{
    OBJ_DATA *axe;
    bool in_forest = FALSE;
    int improve_state = 0;

    if (ch->x >= 0 || ch->y >= 0) switch (map_data(ch->x,ch->y))
    {
	default: break;
	case WILD_FOREST_1:
	case WILD_FOREST_2:
	case WILD_FOREST_3:
	case WILD_FOREST_4:
	    in_forest = TRUE;
	    break;
    }

    if (!in_forest)
    {
	send_to_char("There are no trees left to chop down!\n\r",ch);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( ( axe = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	axe->item_type != ITEM_WEAPON || axe->value[3] != 1 )
    {
	if ( ( axe = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    axe->item_type != ITEM_WEAPON || axe->value[3] != 1 )
	{
	    send_to_char("You need to hold a slicing weapon to chop down trees.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    ch->quality = 0;
	    return;
	}
    }
    switch (ch->action)
    {
	default:
	case WA_CHOPPING_SWING:
	    act("You swing back $p.",ch,axe,NULL,TO_CHAR);
	    act("$n swings back $p.",ch,axe,NULL,TO_ROOM);
	    ch->action = WA_CHOPPING_CHOP;
	    break;
	case WA_CHOPPING_CHOP:
	    act("You swing $p into a tree.",ch,axe,NULL,TO_CHAR);
	    act("$n swings $p into a tree.",ch,axe,NULL,TO_ROOM);
	    ch->action = WA_CHOPPING_SWING;
	    improve_state = get_curr_str(ch);
	    ch->state += improve_state;
	    if (ch->state >= ch->quality)
	    {
		send_to_char("The tree falls to the ground with a loud crash!\n\r",ch);
		act("The tree falls to the ground with a loud crash!",ch,NULL,NULL,TO_ROOM);
		make_resource(ch, RESOURCE_TREE);
		ch->action = WA_NONE;
		ch->state = 0;
		ch->quality = 0;
		switch (map_data(ch->x,ch->y))
		{
		    default: break;
		    case WILD_FOREST_1:
			set_map_data(ch->x, ch->y, WILD_PLAINS);
			do_wsave(ch,"zone");
			break;
		    case WILD_FOREST_2:
			set_map_data(ch->x, ch->y, WILD_FOREST_1);
			do_wsave(ch,"zone");
			break;
		    case WILD_FOREST_3:
			set_map_data(ch->x, ch->y, WILD_FOREST_2);
			do_wsave(ch,"zone");
			break;
		    case WILD_FOREST_4:
			set_map_data(ch->x, ch->y, WILD_FOREST_3);
			do_wsave(ch,"zone");
			break;
		}
	    }
	    else if (ch->state >= (ch->quality * 0.5))
	    {
		send_to_char("The tree shakes violently under the impact of your blow!\n\r",ch);
		act("The tree shakes violently under the impact of $n's blow!",ch,NULL,NULL,TO_ROOM);
	    }
	    break;
    }
    return;
}

void auto_fishing( CHAR_DATA *ch )
{
    OBJ_DATA *rod;
    OBJ_DATA *obj;

    if ( ( rod = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	rod->item_type != ITEM_TOOL || rod->value[0] != TOOL_FISHING_ROD )
    {
	if ( ( rod = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    rod->item_type != ITEM_TOOL || rod->value[0] != TOOL_FISHING_ROD )
	{
	    send_to_char("You need to hold a fishing rod to catch fish.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    return;
	}
    }

    if (ch->action == WA_FISHING_MENDING)
    {
	act("You deftly tie a line and hook onto $p.",ch,rod,NULL,TO_CHAR);
	act("$n deftly ties a line and hook onto $p.",ch,rod,NULL,TO_ROOM);
	ch->action = WA_FISHING_CASTING;
	return;
    }

    if (ch->action == WA_FISHING_CASTING)
    {
	act("You draw back your arm and cast $p out into the water.",ch,rod,NULL,TO_CHAR);
	act("$n draws back $s arm and casts $p out into the water.",ch,rod,NULL,TO_ROOM);
	ch->action = WA_FISHING_WAITING;
	return;
    }

    if (ch->action == WA_FISHING_WAITING) switch (number_range(1,5))
    {
	default: break;
	case 1:
	    act("You reel $p back in to make another cast.",ch,rod,NULL,TO_CHAR);
	    act("$n reels $p back in.",ch,rod,NULL,TO_ROOM);
	    ch->action = WA_FISHING_CASTING;
	    break;
	case 2:
	    act("You feel a slight tugging on your fishing line.",ch,rod,NULL,TO_CHAR);
	    break;
	case 3:
	    act("You start to reel in $p as you feel a fish bite the hook!",ch,rod,NULL,TO_CHAR);
	    act("$n starts reeling in $p!",ch,rod,NULL,TO_ROOM);
	    ch->action = WA_FISHING_REELING;
	    ch->quality = number_range(3,5);
	    break;
    }
    else switch (number_range(1,10))
    {
	default: break;
	case 1:
	    act("You feel the line go taunt and then snap!",ch,rod,NULL,TO_CHAR);
	    act("$n jerks back $p and the line snaps!",ch,rod,NULL,TO_ROOM);
	    ch->action = WA_FISHING_MENDING;
	    break;
	case 2:
	    act("You feel the line go slack as the fish breaks free.",ch,rod,NULL,TO_CHAR);
	    act("$n's fishing line goes slack.",ch,rod,NULL,TO_ROOM);
	    ch->action = WA_FISHING_CASTING;
	    break;
	case 3:
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	case 10:
	    act("You slowly reel in the line.",ch,rod,NULL,TO_CHAR);
	    act("$n slowly reels in $s fishing line.",ch,rod,NULL,TO_ROOM);
	    ch->state++;
	    if (ch->state >= ch->quality)
	    {
		obj = create_object( get_obj_index( OBJ_VNUM_FISH ), 0 );
		obj_to_char(obj,ch);
		act("You pluck $p off your fishing hook.",ch,obj,NULL,TO_CHAR);
		act("$n plucks $p off $s fishing hook.",ch,obj,NULL,TO_ROOM);
		ch->action = WA_NONE;
		ch->state = 0;
		ch->quality = 0;
	    }
	    break;
    }
}

void auto_digging( CHAR_DATA *ch )
{
    OBJ_DATA *shovel;
    bool in_mine = FALSE;
    int improve_state = 0;

    if (ch->x >= 0 || ch->y >= 0) switch (map_data(ch->x,ch->y))
    {
	default: break;
	case WILD_MINE_STRUCTURE_EMPTY:
	case WILD_MINE_STRUCTURE_STONE:
	case WILD_MINE_STRUCTURE_IRON:
	case WILD_MINE_STRUCTURE_GOLD:
	case WILD_MINE_STRUCTURE_OIL:
	    if (ch->room == 1) in_mine = TRUE;
	    break;
    }

    if (!in_mine)
    {
	send_to_char("You cannot dig here.\n\r",ch);
	ch->action = WA_NONE;
	ch->state = 0;
	ch->quality = 0;
	return;
    }

    if ( ( shovel = get_eq_char(ch, WEAR_WIELD) ) == NULL ||
	shovel->item_type != ITEM_TOOL || shovel->value[0] != TOOL_SHOVEL )
    {
	if ( ( shovel = get_eq_char(ch, WEAR_HOLD) ) == NULL ||
	    shovel->item_type != ITEM_TOOL || shovel->value[0] != TOOL_SHOVEL )
	{
	    send_to_char("You need to hold a shovel to dig.\n\r",ch);
	    ch->action = WA_NONE;
	    ch->state = 0;
	    return;
	}
    }

    switch (ch->action)
    {
	default:
	case WA_DIGGING_SWING:
	    act("You swing back $p, throwing soil behind you.",ch,shovel,NULL,TO_CHAR);
	    act("$n swings back $p, throwing soil behind $m.",ch,shovel,NULL,TO_ROOM);
	    ch->action = WA_DIGGING_CHOP;
	    improve_state = get_curr_str(ch);
	    ch->in_room->wood += improve_state;
	    if (ch->in_room->wood >= 500)
	    {
		ch->in_room->wood = 0;
		send_to_char("The mine is complete!\n\r",ch);
		act("The mine is complete!",ch,NULL,NULL,TO_ROOM);
		ch->action = WA_NONE;
		ch->state = 0;
		ch->quality = 0;
		switch (map_data(ch->x,ch->y))
		{
		    default: break;
		    case WILD_MINE_STRUCTURE_EMPTY:
			set_map_data(ch->x, ch->y, WILD_MINE_EMPTY);
			break;
		    case WILD_MINE_STRUCTURE_STONE:
			set_map_data(ch->x, ch->y, WILD_MINE_STONE_2);
			break;
		    case WILD_MINE_STRUCTURE_IRON:
			set_map_data(ch->x, ch->y, WILD_MINE_IRON_2);
			break;
		    case WILD_MINE_STRUCTURE_GOLD:
			set_map_data(ch->x, ch->y, WILD_MINE_GOLD_2);
			break;
		    case WILD_MINE_STRUCTURE_OIL:
			set_map_data(ch->x, ch->y, WILD_MINE_OIL_2);
			break;
		}
	    }
	    break;
	case WA_DIGGING_CHOP:
	    act("You plunge $p into the ground.",ch,shovel,NULL,TO_CHAR);
	    act("$n plunges $p into the ground.",ch,shovel,NULL,TO_ROOM);
	    ch->action = WA_DIGGING_SWING;
	    break;
    }
    return;
}

/* Creates a resource of the specified type. */
void make_resource( CHAR_DATA *ch, RESOURCE_TYPE resource )
{
    char resource_name  [MAX_INPUT_LENGTH];
    char resource_short [MAX_INPUT_LENGTH];
    char resource_long  [MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    if ( ch->in_room == NULL )
    {
	return;
    }

    switch (resource)
    {
	default:
	case RESOURCE_TREE:
	    strcpy(resource_name,"tree");
	    strcpy(resource_short,"a tree");
	    strcpy(resource_long,"A chopped down tree is lying here.");
	    break;
	case RESOURCE_LOG:
	    strcpy(resource_name,"log");
	    strcpy(resource_short,"a log");
	    strcpy(resource_long,"A log is lying here.");
	    break;
	case RESOURCE_ROCK:
	    strcpy(resource_name,"rock stone");
	    strcpy(resource_short,"a piece of rock");
	    strcpy(resource_long,"A piece of rock is lying here.");
	    break;
	case RESOURCE_IRON:
	    strcpy(resource_name,"iron ore");
	    strcpy(resource_short,"a chunk of iron ore");
	    strcpy(resource_long,"A chunk of iron ore is lying here.");
	    break;
	case RESOURCE_GOLD:
	    strcpy(resource_name,"gold nugget");
	    strcpy(resource_short,"a gold nugget");
	    strcpy(resource_long,"A gold nugget is lying here.");
	    break;
	case RESOURCE_OIL:
	    strcpy(resource_name,"oil");
	    strcpy(resource_short,"a pool of oil");
	    strcpy(resource_long,"A pool of oil is lying here.");
	    break;
	case RESOURCE_WHEAT:
	    strcpy(resource_name,"bundle wheat");
	    strcpy(resource_short,"a bundle of wheat");
	    strcpy(resource_long,"A bundle of wheat is lying here.");
	    break;
    }

    obj = create_object( get_obj_index( OBJ_VNUM_PROTOPLASM ), 0 );
    obj->item_type = ITEM_RESOURCE;
    obj->value[0] = ch->quality;
    obj->value[1] = (sh_int) resource;
    obj->wear_flags = ITEM_TAKE;
    obj->weight = ch->quality;

    free_string(obj->name);
    obj->name = str_dup(resource_name);

    free_string(obj->short_descr);
    obj->short_descr = str_dup(resource_short);

    free_string(obj->description);
    obj->description = str_dup(resource_long);

    if (resource == RESOURCE_OIL)
    {
	obj->item_type = ITEM_FOUNTAIN;
	obj->value[0] = 1;
	obj->value[1] = ch->quality;
	obj->value[2] = 15; /* Oil */
	obj->wear_flags = 0;
    }

    obj_to_room(obj, ch->in_room);

    return;
}

