/******************************************************************************
 Snippet: Wilderness system (v1.0).
 Author:  Richard Woolcock (aka KaVir).
 Date:    2nd September 1998.
 ******************************************************************************
 File:    wild_spec.c
 Purpose: Deals with special wilderness mobs.
 ******************************************************************************
 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
 ******************************************************************************/

int	close_room	args( ( CHAR_DATA *ch, int x, int y ) );
int	walk_room	args( ( CHAR_DATA *ch, int x, int y ) );
bool	check_forest	args( ( int x, int y ) );

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

/* Wild animal special procedures. */
bool spec_wildmob( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    bool del_char = TRUE;

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

    for ( victim = ch->in_room->people; victim; victim = victim->next_in_room )
    {
	if (victim == ch) continue;
	if (!IS_NPC(victim) || victim->pIndexData->vnum >= 100 ) 
	{
	    del_char = FALSE;
	    break;
	}
    }

    if (del_char)
    {
	extract_char(ch,TRUE);
	return ( TRUE );
    }

    if ( !IS_AWAKE(ch) ||
	number_range(1,3) > 1 ||
	ch->position == POS_FIGHTING )
    {
	return ( FALSE );
    }

    switch (ch->pIndexData->vnum)
    {
	default: break;
	case MOB_VNUM_SHARK:
	    switch (number_range(1,3))
	    {
		default:
		case 1:
		    act("$n lashes $s tail.",ch,NULL,NULL,TO_ROOM);
		    break;
		case 2:
		    act("$n glances hungrilly around.",ch,NULL,NULL,TO_ROOM);
		    break;
		case 3:
		    act("$n snaps its huge teeth.",ch,NULL,NULL,TO_ROOM);
		    break;
	    }
	    break;
	case MOB_VNUM_BEAR:
	    switch (number_range(1,3))
	    {
		default:
		case 1:
		    act("$n snarls at you.",ch,NULL,NULL,TO_ROOM);
		    break;
		case 2:
		    act("$n growls to $mself.",ch,NULL,NULL,TO_ROOM);
		    break;
		case 3:
		    act("$n licks $s paw.",ch,NULL,NULL,TO_ROOM);
		    break;
	    }
	    break;
	case MOB_VNUM_WOLF:
	    switch (number_range(1,3))
	    {
		default:
		case 1:
		    act("$n snarls at you.",ch,NULL,NULL,TO_ROOM);
		    break;
		case 2:
		    act("$n growls to $mself.",ch,NULL,NULL,TO_ROOM);
		    break;
		case 3:
		    act("$n throws back $s head and howls.",ch,NULL,NULL,TO_ROOM);
		    break;
	    }
	    break;
    }

    return ( FALSE );
}

/* Lumberjack, goes around chopping down trees. */
bool spec_lumberjack( CHAR_DATA *ch )
{
    OBJ_DATA  *axe;
    int x,y;

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

    if ( !IS_AWAKE(ch) )
	return ( spec_wildmob(ch) );

    if (ch->quality > 0)
	return ( TRUE );

    if (ch->home_x < 0 || ch->home_y < 0)
    {
	for ( x = ch->x - 50; x <= ch->x + 50; x++ )
	{
	    for ( y = ch->y - 50; y <= ch->y + 50; y++ )
	    {
		if (check_forest(x,y))
		{
		    if (ch->home_x < 0 || ch->home_y < 0 || close_room(ch,x,y) <=
			close_room(ch,ch->home_x, ch->home_y))
		    {
			if (close_room(ch,x,y) < close_room(ch,ch->home_x, ch->home_y)
			    || number_range(1,2) == 1)
			{
			    ch->home_x = x;
			    ch->home_y = y;
			}
		    }
		}
	    }
	}
	if (ch->home_x < 0 && ch->home_y < 0)
	{
	    do_say(ch,"Bah...there are no tree's to cut down...I'm taking a nap...");
	    do_sleep(ch,"");
	    return ( TRUE );
        }
    }
    else if (ch->home_x == ch->x && ch->home_y == ch->y && 
	!check_forest(ch->x,ch->y))
    {
	do_say(ch,"Time to find some more trees!");
	ch->home_x = -1;
	ch->home_y = -1;
	return ( TRUE );
    }

    if (get_obj_wear(ch,"axe") == NULL)
    {
	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 )
	    {
		if ( ( axe = create_object(get_obj_index(OBJ_VNUM_AXE),0) )
		    != NULL )
		{
		    obj_to_char(axe,ch);
		    do_wear(ch,"axe");
		    do_say(ch,"Time to chop down some trees!");
		    return ( TRUE );
		}
	    }
	}
    }

    if ( ch->position <= POS_RESTING )
    {
	do_stand(ch,"");
	return ( TRUE );
    }

    if (ch->x != ch->home_x || ch->y != ch->home_y)
    {
	switch (walk_room(ch,ch->home_x,ch->home_y))
	{
	    default:
		ch->home_x = -1;
		ch->home_y = -1;
		break;
	    case DIR_NORTH:
		do_north(ch,"");
		break;
	    case DIR_SOUTH:
		do_south(ch,"");
		break;
	    case DIR_EAST:
		do_east(ch,"");
		break;
	    case DIR_WEST:
		do_west(ch,"");
		break;
	}
    }
    else if (check_forest(ch->x,ch->y) && ch->quality <= 0 && 
	ch->home_x >= 0 && ch->home_y >= 0)
    {
	do_say(ch,"Just what I was after!");
	do_chop(ch,"");
    }
    return ( TRUE );
}

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

/* Returns the number of rooms away the specified location is. */
int close_room( CHAR_DATA *ch, int x, int y )
{
    while (x < 0) x += 1000;
    while (y < 0) y += 1000;
    while (x >= 1000) x -= 1000;
    while (y >= 1000) y -= 1000;

    x = ch->x > x ? ch->x - x : x - ch->x;
    y = ch->y > y ? ch->y - y : y - ch->y;

    if      (x >= 500) x -= 1000;
    else if (x < -500) x += 1000;

    if      (y >= 500) y -= 1000;
    else if (y < -500) y += 1000;

    return ( x + y );
}

/* Returns the direction that should be walked to get to the specified room.
 * If you are there already, it returns -1.
 */
int walk_room( CHAR_DATA *ch, int x, int y )
{
    int xx, yy;

    while (x < 0) x += 1000;
    while (y < 0) y += 1000;
    while (x >= 1000) x -= 1000;
    while (y >= 1000) y -= 1000;

    xx = ch->x - x;
    yy = ch->y - y;

    if (xx > 500) xx -= 1000;
    else if (xx <= -500) xx += 1000;

    if (yy > 500) yy -= 1000;
    else if (yy <= -500) yy += 1000;

    if (xx == 0 && yy == 0)
    {
	return ( -1 );
    }
    else if (xx == 0)
    {
	if (yy < 0)
	{
	    return ( DIR_NORTH );
	}
	else
	{
	    return ( DIR_SOUTH );
	}
    }
    else if (yy == 0)
    {
	if (xx < 0)
	{
	    return ( DIR_EAST );
	}
	else
	{
	    return ( DIR_WEST );
	}
    }
    else
    {
	switch (number_range(1,2))
	{
	    default: case 1:
		if (xx < 0) return ( DIR_EAST );
		else        return ( DIR_WEST );
		break;
	    case 2:
		if (yy < 0) return ( DIR_NORTH );
		else        return ( DIR_SOUTH );
		break;
	}
    }

    return ( -1 );
}

/* Returns TRUE if the specified location is a forest. */
bool check_forest( int x, int y )
{
    bool is_forest;

    while (x < 0) x += 1000;
    while (y < 0) y += 1000;
    while (x >= 1000) x -= 1000;
    while (y >= 1000) y -= 1000;

    switch (map_data(x,y))
    {
	default:
	    is_forest = FALSE;
	    break;
	case WILD_FOREST_1:
	case WILD_FOREST_2:
	case WILD_FOREST_3:
	case WILD_FOREST_4:
	    is_forest = TRUE;
	    break;
    }
    return ( is_forest );
}
