#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <zlib.h>

/* including main header file */
#include "mud.h"

/*
 * cmd_goto
 *
 * Immortal command
 * goto <x> <y>
 * Transports the immortal to given cords
 * same z axis only
 */
void cmd_goto (D_MOBILE * ch, char *arg)
{
    char arg1[MAX_BUFFER];
    char arg2[MAX_BUFFER];
    int x;
    int y;
    
    arg = one_arg(arg, arg1);
    arg = one_arg(arg, arg2);
    
    if (arg1[0] == '\0' || arg2[0] == '\0')
    {
        stc("Goto where? (Syntax: goto <x> <y>)\n\r", ch);
        return;
    }
    
    x = atoi (arg1);
    y = atoi (arg2);
    
    ch->x = x;
    ch->y = y;
    cmd_look(ch, "");
}

/*
 * cmd_echo()
 *
 * Echos string to the world
 * Just a fun command =)
 */
void cmd_echo(D_M * ch, char * arg)
{
    D_MOBILE *xMob;
    char message[MAX_BUFFER];
    
    sprintf(message, "%s#n\n\r", arg);
    for (xMob = dmobile_list; xMob; xMob = xMob->next)
    {
        text_to_mobile(xMob, message);
    }
    return;
}

/*
 * Simple command to display what imm flags
 * are on
 */
void cmd_display_bits (D_M * ch, char * arg)
{
    if (IS_SET(ch->immortal_flags, IMMORTAL_OMNI_VIEW))
        stc("You have Omni View on.\n\r", ch);
    if (IS_SET(ch->immortal_flags, IMMORTAL_PASS_DOOR))
        stc("You have Immortal Pass Door on.\n\r", ch);
}

/*
 * Turns on Omni View
 * No terrain block
 */
void cmd_omni_view (D_M * ch, char * arg)
{
    if (!IS_SET(ch->immortal_flags, IMMORTAL_OMNI_VIEW))
    {
        SET_BIT(ch->immortal_flags, IMMORTAL_OMNI_VIEW);
        stc("Omni View on!\n\r", ch);
        return;
    }
    else
    {
        REMOVE_BIT(ch->immortal_flags, IMMORTAL_OMNI_VIEW);
        stc("Omni View off!\n\r", ch);
        return;
    }
}

/*
 * Immortal command to bypass any blocking terrain
 */
void cmd_pass_door (D_M * ch, char * arg)
{
    if (!IS_SET(ch->immortal_flags, IMMORTAL_PASS_DOOR))
    {
        SET_BIT(ch->immortal_flags, IMMORTAL_PASS_DOOR);
        stc("Immortal Pass door on!\n\r", ch);
        return;
    }
    else
    {
        REMOVE_BIT(ch->immortal_flags, IMMORTAL_PASS_DOOR);
        stc("Immortal Pass door off!\n\r", ch);
        return;
    }
}

/*
 * advance()
 *
 * advance a target player to given level.
 * uses get_dmob_world based on name comparison
 * through the socket list.
 * TODO: Security checks
 */
void cmd_advance (D_M * ch, char * arg)
{
    char arg1[MAX_BUFFER];
    char arg2[MAX_BUFFER];
    char buf[MAX_BUFFER];
    int x;
    D_MOBILE * victim;
    
    arg = one_arg(arg, arg1);
    arg = one_arg(arg, arg2);
    
    if (arg1[0] == '\0' || arg2[0] == '\0')
    {
        stc("Syntax: advance <char> <level>\n\r", ch);
        stc("Note: level is 1-4\n\r", ch);
        return;
    }
    
    x = atoi(arg2);
    
    if (x > 4)
    {
        stc("Max_level == 4!\n\r", ch);
        return;
    }
    
    if ((victim = get_dmob_world(ch, arg1)) != NULL)
    {
        victim->level = x;
        sprintf(buf, "You have been advanced to level %d!\n\r", x);
        stc(buf, ch);
        sprintf(buf, "You change %s's level to %d\n\r", victim->name, x);
        stc(buf, ch);
        return;
    }
    else
    {
        stc("Victim not found!\n\r", ch);
        return;
    }
}

/*
 * cmd_pset()
 *
 * Player Set. Sets all various player
 * Statistics.
 */
void cmd_pset (D_M * ch, char * arg)
{
    char arg1[MAX_BUFFER];
    char arg2[MAX_BUFFER];
    char arg3[MAX_BUFFER];
    char buf[MAX_BUFFER];
    int x;
    int temp;
    int i;
    D_MOBILE * victim;
    
    arg = one_arg(arg, arg1);
    arg = one_arg(arg, arg2);
    arg = one_arg(arg, arg3);
    
    if (arg1[0] == '\0' || arg2[0] == '\0')
    {
        stc("Syntax: set <player> <stat> <value>\n", ch);
        stc("Stats:     hp, mana, stamina, fatigue\n", ch);
        stc("           race, class, age, exp\n", ch);
        stc("           force, agility, intuition, speed\n", ch);
        stc("           luck, personality, willpower\n", ch);
        return;
    }
    if ((victim = get_dmob_world(ch, arg1)) != NULL)
    {
        
        if (compares(arg2, "exp"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> exp <value>\n", ch);
                stc("value between 1-500\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 501 || x <= 1)
            {
                stc("Max/Min value for Experience is 1-500!\n", ch);
                return;
            }
            victim->xp += x;
            stc("Done\n", ch);
            return;
        }
        if (compares(arg2, "skills"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> skills <value>\n", ch);
                stc("value between 0-5\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 6 || x <= 0)
            {
                stc("Max/Min value for Skills is 0 to 5!\n", ch);
                return;
            }
            for (i = 0;i != MAX_SKILLS; i++)
                ch->skills[i] = x;
            stc("Done!\n", ch);
            return;
        }
        if (compares(arg2, "talents"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> talents <value>\n", ch);
                stc("value between 0-5\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 6 || x <= 0)
            {
                stc("Max/Min value for Talents is 0 to 5!\n", ch);
                return;
            }
            for (i = 0;i != MAX_TALENTS; i++)
                ch->talents[i] = x;
            stc("Done!\n", ch);
            return;
        }
        if (compares(arg2, "knowledge"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> knowledge <value>\n", ch);
                stc("value between 0-5\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 6 || x <= 0)
            {
                stc("Max/Min value for Knowledges is 0 to 5!\n", ch);
                return;
            }
            for (i = 0;i != MAX_KNOW; i++)
                ch->knowledge[i] = x;
            stc("Done!\n", ch);
            return;
        }
            
        /* Lets take care of Level */
        if (compares(arg2, "level"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> level <value>\n", ch);
                stc("value between 1-36\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 37 || x <= 1)
            {
                stc("Max/Min value for Level is 1 to 36!\n", ch);
                return;
            }
            victim->p_level = x;
            sprintf(buf, "You have set %s's Level to %d!\n", victim->name, victim->p_level);
            stc(buf, ch);
            return;
        }
        /* Lets take care of Age */
        if (compares(arg2, "age"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> age <value>\n", ch);
                stc("value between 18-5000\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 5001 || x <= 17)
            {
                stc("Max/Min value for Level is 17 to 5000!\n", ch);
                return;
            }
            victim->age = x;
            sprintf(buf, "You have set %s's age to %d!\n", victim->name, victim->age);
            stc(buf, ch);
            return;
        }

        /* Lets take care of Race */
        if (compares(arg2, "race"))
        {
            if (arg3[0] == '\0') 
            {
                stc("Syntax: set <player> race <race>\n", ch);
                stc("Must use the Race Name!\n", ch);
                return;
            }
            temp = find_race(arg3);
            victim->race = temp;
            sprintf(buf, "You have set %s's race to %s!\n", victim->name, race_table[temp].name);
            stc(buf, ch);
            return;
        }
        
        /* Lets take care of Class */
        if (compares(arg2, "class"))
        {
            if (arg3[0] == '\0') 
            {
                stc("Syntax: set <player> class <race>\n", ch);
                stc("Must use the Class Name!\n", ch);
                return;
            }
            temp = find_class(arg3);
            victim->class = temp;
            sprintf(buf, "You have set %s's Class to %s!\n", victim->name, class_table[temp].name);
            stc(buf, ch);
            return;
        }
        
        /* Lets take care of Hitpoints */
        if (compares(arg2, "hp"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> hp <value>\n", ch);
                stc("value between 1-250\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 251 || x <= 1)
            {
                stc("Max/Min value for Hitpoints is 1-250!\n", ch);
                return;
            }
            victim->stats[STAT_HP_MAX] = x;
            victim->stats[STAT_HP] = x;
            sprintf(buf, "You have set %s's Hitpoints to %d!\n", victim->name, victim->stats[STAT_HP_MAX]);
            stc(buf, ch);
            return;
        }
        /* Lets take care of Mana */
        if (compares(arg2, "mana"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> mana <value>\n", ch);
                stc("value between 1-450\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 451 || x <= 1)
            {
                stc("Max/Min value for Mana is 1-450!\n", ch);
                return;
            }
            victim->stats[STAT_MANA_MAX] = x;
            victim->stats[STAT_MANA] = x;
            sprintf(buf, "You have set %s's Mana to %d!\n", victim->name, victim->stats[STAT_MANA_MAX]);
            stc(buf, ch);
            return;
        }
        /* Lets take care of Stamina */
        if (compares(arg2, "stamina"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> stamina <value>\n", ch);
                stc("value between 1-450\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 451 || x <= 1)
            {
                stc("Max/Min value for stamina is 1-450!\n", ch);
                return;
            }
            victim->stats[STAT_STAMINA_MAX] = x;
            victim->stats[STAT_STAMINA] = x;
            sprintf(buf, "You have set %s's Stamina to %d!\n", victim->name, victim->stats[STAT_STAMINA_MAX]);
            stc(buf, ch);
            return;
        }
        /* Lets take care of Fagtigue */
        if (compares(arg2, "fatigue"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> fatigue <value>\n", ch);
                stc("value between 1-400\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 401 || x <= 1)
            {
                stc("Max/Min value for Mana is 1-400!\n", ch);
                return;
            }
            victim->stats[STAT_FATIGUE_MAX] = x;
            victim->stats[STAT_FATIGUE] = x;
            sprintf(buf, "You have set %s's Fatigue to %d!\n", victim->name, victim->stats[STAT_FATIGUE_MAX]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "force"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> force <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Force is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_FORCE] = x;
            victim->attribs_max[ATTR_FORCE] = x;
            sprintf(buf, "You have set %s's Force to %d!\n", victim->name, victim->attribs_max[ATTR_FORCE]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "intui"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> intui <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Intuition is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_INTUI] = x;
            victim->attribs_max[ATTR_INTUI] = x;
            sprintf(buf, "You have set %s's Inutuition to %d!\n", victim->name, victim->attribs_max[ATTR_INTUI]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "agility"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> agility <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Agility is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_AGILI] = x;
            victim->attribs_max[ATTR_AGILI] = x;
            sprintf(buf, "You have set %s's Agility to %d!\n", victim->name, victim->attribs_max[ATTR_AGILI]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "resil"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> resil <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Resilience is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_RESIL] = x;
            victim->attribs_max[ATTR_RESIL] = x;
            sprintf(buf, "You have set %s's Resilience to %d!\n", victim->name, victim->attribs_max[ATTR_RESIL]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "speed"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> speed <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Speed is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_SPEED] = x;
            victim->attribs_max[ATTR_SPEED] = x;
            sprintf(buf, "You have set %s's Speed to %d!\n", victim->name, victim->attribs_max[ATTR_SPEED]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "luck"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> luck <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Luck is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_LUCK] = x;
            victim->attribs_max[ATTR_LUCK] = x;
            sprintf(buf, "You have set %s's Luck to %d!\n", victim->name, victim->attribs_max[ATTR_LUCK]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "person"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> person <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Personality is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_PERSON] = x;
            victim->attribs_max[ATTR_PERSON] = x;
            sprintf(buf, "You have set %s's Personality to %d!\n", victim->name, victim->attribs_max[ATTR_PERSON]);
            stc(buf, ch);
            return;
        }
        if (compares(arg2, "willpower"))
        {
            if (arg3[0] == '\0')
            {
                stc("Syntax: set <player> willpower <value>\n", ch);
                stc("value between 1-100\n", ch);
                return;
            }
            x = atoi(arg3);
            if (x >= 101 || x <= 1)
            {
                stc("Max/Min value for Willpower is 1-100!\n", ch);
                return;
            }
            victim->attribs[ATTR_WILLP] = x;
            victim->attribs_max[ATTR_WILLP] = x;
            sprintf(buf, "You have set %s's Willpower to %d!\n", victim->name, victim->attribs_max[ATTR_WILLP]);
            stc(buf, ch);
            return;
        }
        
        /* No matching arg2? */
        stc("Invalid Stat to modify!\n\r", ch);
        return;
    }
    else
    {
        stc("Victim not found!\n\r", ch);
        return;
    }
}

/*
 * cmd_scrye()
 *
 * Immortal Utility to see location for a large
 * area of the map.
 */
void cmd_scrye (D_MOBILE * ch, char *arg)
{
    int x = 0;
    int y = 0;
    int viewx = ch->view_x;
    int viewy = ch->view_y;
    int start_x = 200;
    int start_y = 100;
    BUFFER *buf = buffer_new(MAX_BUFFER);

    if (IS_SET(ch->player_flags, PLR_CLEAR_SCREEN))
        stc(CLEAR_SCREEN, ch);
    
    for   (y = start_y; y != (start_y + viewy); y += 5)
    {
        for (x = start_x; x != (start_x + viewx); x += 5)
        {
            if (y == ch->y && x == ch->x)
                bprintf(buf, "#R@");
            else
            {
                    bprintf(buf, "%s", return_symbol(map[y][x]));
            }
            
            if (x == start_x + viewx - 1)
                bprintf(buf, "\n\r");
        }
    }
    text_to_mobile(ch, buf->data);
    buffer_free(buf);
}