/***************************************************************************
 *  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                     *
***************************************************************************/   

/***************************************************************************
*       ROT 1.4 is copyright 1996-1997 by Russ Walsh                       *
*       By using this code, you have agreed to follow the terms of the     *
*       ROT license, in the file doc/rot.license                           *
***************************************************************************/   

#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "tables.h"

bool change_exit  args( ( CHAR_DATA *ch, char *argument, int door ) );
void edit_done (CHAR_DATA *ch, char *argument );
void save_area (AREA_DATA *pArea );
CHAR_DATA *  find_architect     args( ( CHAR_DATA * ch ) );

#define MAX_HORESET	5
#define MAX_HMRESETS	5

DECLARE_DO_FUN( do_asave	);
DECLARE_DO_FUN( do_redit	);
DECLARE_DO_FUN( redit_name	);
DECLARE_DO_FUN( redit_desc	);
DECLARE_DO_FUN( redit_oreset	);
DECLARE_DO_FUN( oedit_create	);
DECLARE_DO_FUN( oedit_copy	);
DECLARE_DO_FUN(	medit_create	);
DECLARE_DO_FUN(	medit_copy	);
DECLARE_DO_FUN(	redit_mreset	);
DECLARE_DO_FUN( do_look		);
DECLARE_DO_FUN( redit_delete    );
DECLARE_DO_FUN( do_recall       );

#define VNUM_START 20701  
#define VNUM_STOP  22699

CHAR_DATA * find_architect ( CHAR_DATA *ch )
{
    CHAR_DATA * architect;

    for ( architect = ch->in_room->people; architect != NULL; architect = architect->next_in_room )
    {
        if (!IS_NPC(architect))
            continue;

        if (architect->spec_fun == spec_lookup( "spec_architect" ) )
            return architect;
    }  

    if ( architect == NULL || architect->spec_fun != spec_lookup( "spec_architect" ))
    {
        send_to_char("You can't do that here, find an Architect.\n\r", ch);
        return NULL;
    }

    if ( architect->fighting != NULL )
    {
        send_to_char("Wait until the fighting stops.\n\r",ch );
        return NULL;
    }

    return NULL;
}        

void do_objbuy(CHAR_DATA *ch, char *argument)
{
    char arg[MSL];
    char arg1[MSL];
    char buf[MSL];
    OBJ_DATA *obj;
    int i;
 
    argument = one_argument( argument, arg );
    argument = one_argument( argument, arg1 );

    if ( !HAS_HOME( ch ) )
    {
        send_to_char("If you only had a home...\n\r",ch);
        return;
    }

    if ( !IS_HOME( ch ) )
    {
	send_to_char("You gotta be in your house.\n\r",ch);
	return;
    }

    if (arg[0] == '\0')
    {
	send_to_char("Syntax: objbuy <list>\n\rSyntax: objbuy buy <name>",ch);
	return;
    }

    if (!str_cmp(arg,"list"))
    {
	send_to_char("The following objects are available for purchase:\n\r",ch);
        send_to_char("{cCost:    Name:{x\n\r", ch );
        for ( i = 0; house_table[i].name != NULL; i++ )
        {
             if ( house_table[i].type != OBJ_VNUM )
                 continue;
             printf_to_char( ch, "%-5d    %-10s\n\r", house_table[i].cost, house_table[i].name );
        }

        return;

    }

    if (!str_cmp(arg, "buy"))
    {
        if (arg1[0] == '\0')
        {
            send_to_char( "To buy an item type objbuy buy <item>.\n\r",ch );
            return;
        }
         
        for (i = 0; house_table[i].name != NULL; i++)           
        {
             if (is_name(arg1, house_table[i].name) && house_table[i].type == OBJ_VNUM)         
             {
                 if (ch->platinum >= house_table[i].cost) 
                 {
                     if ( (obj = create_object(get_obj_index(house_table[i].vnum), ch->level ) )  == NULL ) 
                     {
                         send_to_char( "That object could not be found contact an imm.\n\r", ch );
                         return;
                     }

                     if( ch->pcdata->horesets > MAX_HORESET )
                     {
  	                send_to_char("Sorry you can only have 5 resetting objects.\n\r",ch);
	                return;
                     }

                     ch->pcdata->horesets++;
                     ch->platinum -= house_table[i].cost;  
                     sprintf(buf,"%d", house_table[i].vnum);
                     redit_oreset(ch,buf);
                     sprintf(buf," ");
                     save_area(ch->in_room->area);
          	     return;
                 }

                 else
                 {
                    printf_to_char( ch, "Sorry %s but you need %d platinum for that.\n\r", ch->name, 
house_table[i].cost );
                    return;
                 }
             }
        }
    }

    send_to_char( "To buy an item type objbuy buy <item>.\n\r",ch );
    return;
}

void do_mobbuy(CHAR_DATA *ch, char *argument)
{
    char arg[MSL];
    char arg1[MSL];
    CHAR_DATA *mob;
    char buf[MSL];   
    int i;
 
    argument = one_argument( argument, arg );
    argument = one_argument( argument, arg1 );

    if ( !HAS_HOME( ch ) )
    {
        send_to_char("If you only had a home...\n\r",ch);
        return;
    }

    if ( !IS_HOME( ch ) )
    {
	send_to_char("You gotta be in your house.\n\r",ch);
	return;
    }

    if (arg[0] == '\0')
    {
        send_to_char("Syntax: mobbuy <list>\n\rSyntax: mobbuy buy <name>",ch); 
	return;
    }

    if (!str_cmp(arg,"list"))
    {
	send_to_char("The following mobiles are available for purchase:\n\r",ch);
        send_to_char("{cCost:       Name:{x\n\r\n\r", ch );  
        for ( i = 0; house_table[i].name != NULL; i++ )
        {
             if ( house_table[i].type != MOB_VNUM )
                 continue;
             printf_to_char( ch, "%-5d    %-10s\n\r", house_table[i].cost, house_table[i].name );
        }

        return;

    }

    if (!str_cmp(arg, "buy"))
    {
        if (arg1[0] == '\0')
        {
            send_to_char( "To buy an item type mobbuy buy <item>.\n\r",ch );
            return;
        }           

        for (i = 0; house_table[i].name != NULL; i++)
        {        
             if (is_name(arg1, house_table[i].name) && house_table[i].type == MOB_VNUM)
             {
                 if (ch->platinum >= house_table[i].cost)
                 {                  
                     mob = create_mobile(get_mob_index(house_table[i].vnum) );
                 
                     if ( mob == NULL ) 
                     {
                         send_to_char( "That mob could not be found contact an imm.\n\r", ch );
                         return;
                     }            

                     if( ch->pcdata->hmresets > MAX_HMRESETS )
                     {      
                       	send_to_char("Sorry you can only have 5 resetting mobiles.\n\r",ch);
	                return;
                     }

                     ch->pcdata->hmresets++;
                     ch->platinum -= house_table[i].cost;
                     sprintf(buf,"%d", house_table[i].vnum);  
                     redit_mreset(ch,buf);
                     sprintf(buf," ");
                     save_area(ch->in_room->area);
                     return;                            
                 }

                 else
                 {

                   printf_to_char( ch, "Sorry %s but you need %d platinum for a %s.\n\r", ch->name, 
house_table[i].cost, house_table[i].name );                       
                   return;
                 }
             }
        }
    }
       
    send_to_char("Syntax: mobbuy <list>\n\rSyntax: mobbuy buy <name>",ch); 
    return; 
}

void do_house( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *architect;
    char arg[MIL];
    int osec;
    char buf[MSL];
    int i,i2;
    int cost = 100000;

    architect = find_architect( ch );

    if (!architect)
        return;
 
    argument = one_argument( argument, arg );

    if (IS_NPC(ch))
    {
	send_to_char("Sorry, you'll have to just wander, mobile.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' && HAS_HOME( ch ) )
    {
        send_to_char( "You already bought a house. To sell it type house <sell>.\n\r", ch );
        return;
    }


    if ( HAS_HOME( ch ) )
    {
        send_to_char( "You already own a house. To sell it type house <sell>.\n\r", ch );
        return;
    }

    if (ch->platinum < cost)
    {
        printf_to_char( ch, "I'm sorry but it cost %d platinum to buy a house.\n\r", cost );
	return;
    }

    i = VNUM_START;

    while (get_room_index(i) != NULL)
    {
	i++;

	if (i > VNUM_STOP - 5)
	{
            send_to_char("Sorry all of the house vnums are used up! Tell an immortal.\n\r", ch );
	    return;
	}
    }

    send_to_char("Okay... Attempting creation of your home.\n\r\n\r",ch);
    ch->platinum -= cost;
    osec = ch->pcdata->security;  
    ch->pcdata->security = 5;

    for (i2 = 4;i2 >= 0;i2--)
    {
	sprintf(buf,"create %d",i+i2);
 	do_redit(ch,buf);
	sprintf(buf,"%s's Home",ch->name);
	redit_name(ch,buf);
    }

/*
 *  Link the rooms together
 *      3
 *      |
 *   2--1--4
 *      |
 *	5
 */

    sprintf(buf,"link %d",i+1);
    change_exit(ch,buf,DIR_WEST);
    sprintf(buf,"link %d",i+2);
    change_exit(ch,buf,DIR_NORTH);
    sprintf(buf,"link %d",i+3);
    change_exit(ch,buf,DIR_EAST);
    sprintf(buf,"link %d",i+4);
    change_exit(ch,buf,DIR_SOUTH);
    ch->pcdata->security = osec;
    send_to_char("\n\rHURRAY! Your house was made successfully.\n\r",ch);
    ch->pcdata->h_vnum = i;
    do_asave(ch, "area");
    save_area(ch->in_room->area);
    edit_done(ch,"");
    return;
}

void do_hname( CHAR_DATA *ch, char *argument )
{
    int cost = 500;

    if ( !HAS_HOME( ch ) )
    {
        send_to_char("If you only had a home...\n\r",ch);
        return;
    }

    if ( !IS_HOME( ch ) )
    {
        send_to_char( "You've got to be in your house to do that.\n\r", ch );
	return;

    }

    if (ch->platinum < cost)
    {
        printf_to_char( ch, "It cost %d to change the name of a room in your house.\n\r", cost );
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Change the name to what?\n\r",ch);
	return;
    }

    ch->platinum -= cost;
    send_to_char("Ok.\n\r",ch);
    redit_name(ch,argument);
    save_area(ch->in_room->area);
    edit_done(ch,"");
    return;
}

void do_hdesc( CHAR_DATA *ch, char *argument )
{
    int cost = 500;

    if ( !HAS_HOME( ch ) )
    {
        send_to_char("If you only had a home...\n\r",ch);
        return;
    }

    if ( !IS_HOME( ch ) )
    {
	send_to_char("You gotta be in your house.\n\r",ch);
	return;
    }

    if (ch->platinum < cost)
    {
        printf_to_char( ch, "It cost %d platinum to change a description.\n\r", cost );
	return;
    }

    ch->platinum -= cost;
    send_to_char("Ok.\n\r",ch);
    ch->desc->pEdit     = ch->in_room;
    ch->desc->editor    = 2;
    ch->pcdata->hchange	= TRUE;
    redit_desc(ch,"");
    edit_done(ch,"");
    save_area(ch->in_room->area);
    return;
}

void do_home( CHAR_DATA *ch, char *argument )
{
    char buf[MSL];
    CHAR_DATA *victim;
    ROOM_INDEX_DATA *location;
//    int track;

    if (IS_NPC(ch) && IS_SET(ch->act,ACT_PET))
    {
        send_to_char("Only players can go home.\n\r",ch);
        return;
    }

    if ( !HAS_HOME( ch ) )
    {
	send_to_char("If you only had a home...\n\r",ch);
	return;
    }

    if(IS_NPC(ch))
	location = get_room_index(ch->master->pcdata->h_vnum);
    else
	location = get_room_index(ch->pcdata->h_vnum);

    if (location == NULL)
    {
        send_to_char( "Yikes write a note to immortal and let them know your house is Null.\n\r", ch );
	return;
    }

    act( "$n prays for transportation!", ch, 0, 0, TO_ROOM );

    if ( ch->in_room == location )
        return;

    if ( ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_AFFECTED(ch, AFF_CURSE))
    &&   (ch->level <= HERO) )
    {
        act( "$G has forsaken you.", ch, NULL, NULL, TO_CHAR );
        return;
    }
    

    if ( ( victim = ch->fighting ) != NULL )
    {
        int lose,skill;

        skill = get_skill(ch,gsn_recall);

        if ( number_percent() < 80 * skill / 100 )
        {
            check_improve(ch,gsn_recall,FALSE,6);
            WAIT_STATE( ch, 4 );
            sprintf( buf, "You failed!.\n\r");
            send_to_char( buf, ch );
            return;
        }

        lose = (ch->desc != NULL) ? 50 : 100;
        gain_exp( ch, 0 - lose );
        check_improve(ch,gsn_recall,TRUE,4);
        sprintf( buf, "You flee home from combat!  You lose %d exps.\n\r", lose );
        send_to_char( buf, ch );

        if ( !IS_NPC(ch) )
        {
            if ( !IS_NPC(victim) && ch->attacker == TRUE)
            {
                send_to_char( "You flee from combat and go home.\n\r", ch );
                send_to_char( "You lose some hit points in the process.\n\r", ch );
                ch->hit -= (ch->hit/4);
            }
        }
        stop_fighting( ch, TRUE );
    }

    act( "$n disappears.", ch, NULL, NULL, TO_ROOM );

  /*  if (IS_NPC(ch) || !IS_IMMORTAL(ch))
    {
        for (track = MAX_TRACK-1; track > 0; track--)
        {
            ch->track_to[track] = ch->track_to[track-1];
            ch->track_from[track] = ch->track_from[track-1];
        }
        ch->track_from[0] = ch->in_room->vnum;
        ch->track_to[0] = 0;
    } */

    char_from_room( ch );
    char_to_room( ch, location );
    act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
    do_look( ch, "auto" );

    if (ch->pet != NULL)
        do_home(ch->pet,"");

    return;
}

void do_invite(CHAR_DATA *ch,char *argument)
{
    CHAR_DATA *victim;
    char buf[MSL];

    if (argument[0] == '\0')
    {
	send_to_char("Invite whom to your home?\n\r",ch);
	return;
    }

    if ((victim = get_char_world(ch,argument)) == NULL)
    {
	send_to_char("Who is that?\n\r",ch);
	return;
    }

    if ( !IS_HOME( ch ) )
    {
        send_to_char("Can't invite someone to your house when you aren't in it.\n\r",ch);
	return;
    }

    if (ch == victim)
    {
	send_to_char("Lonely person, huh?\n\r",ch);
	return;
    }

    printf_to_char( victim,"%s has invited you to come to %s house!\n\r",ch->name,  ch->sex == 0 ? "It's" : ch->sex == 
1 ? "His" : "Her" ); 
    send_to_char(buf,victim);
    printf_to_char( ch, "You have invited %s into your house!\n\r", victim->name );
    victim->pcdata->hinvite = ch->pcdata->h_vnum;
}

void do_join(CHAR_DATA *ch,char *argument)
{
    int ohvnum = 0;

    if (ch->pcdata->hinvite == 0)
    {
	send_to_char("You haven't been invited anywhere.\n\r",ch);
	return;
    }


    ohvnum = ch->pcdata->h_vnum;
    ch->pcdata->h_vnum = ch->pcdata->hinvite;
    do_home(ch,"");
    ch->pcdata->h_vnum = ohvnum;
    ch->pcdata->hinvite = 0;
}


void do_boot( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;

    if ( argument[0] == '\0' )
    {     
        send_to_char( "Who would you like to boot out of your house?\n\r", ch );
        return;
    }

    if ((victim = get_char_world(ch,argument)) == NULL)
    {
        send_to_char("Who is that?\n\r",ch);
        return;
    }                  
    
    if ( !IS_HOME( ch ) )
    {
        send_to_char("You can't boot someone if your not in your house!\n\r", ch );
        return;
    }            

    if ((victim->in_room->vnum < ch->pcdata->h_vnum) || (victim->in_room->vnum > ch->pcdata->h_vnum + 4))
    {
        send_to_char("You can't boot someone if their not in your house!\n\r",ch);
        return;
    }       

    printf_to_char( ch, "You get in %s's face and yell at %s to get out of your house!\n\r", victim->name, victim->sex == 0 ? "It" : victim->sex == 1 ? "Him" : "Her" );
    printf_to_char( victim, "%s begins yelling at you, and tells you to get out of %s house!\n\r", ch->name, ch->sex == 0 ? "It's" : ch->sex == 1 ? "His" : "Her" );  
    printf_to_char( victim, "You have been kicked out of %s's house!\n\r", ch->name );  
    do_recall( victim, "" );
    return;
}