/*
 * movement.c
 *
 * Contains movement and display code
 * for the world map.
 */
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

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

struct sector_type sector_table[] =
    {                       /*#   Red  Grn  Blu */
    {"Mountain",    "#D^",    0,  128, 128, 128, TRUE,  TRUE }, /* 0 */
    {"Grass",       "#g.",    1,  255, 255, 255, TRUE,  TRUE }, /* 1 */
    {"River",       "#C~",    2,  0,   255, 255, TRUE,  TRUE }, /* 2 */
    {"Ocean",       "#b~",    3,  0,   0,   255, TRUE,  TRUE }, /* 3 */
    {"Beach",       "#y.",    4,  0,   0,   0,   TRUE,  TRUE }, /* 4 */
    {"Desert",      "#y^",    5,  255, 255, 0,   TRUE,  TRUE }, /* 5 */
    {"Hills",       "#w^",    6,  192, 192, 192, TRUE,  TRUE }, /* 6 */
    {"Tree",        "#G*",    7,  0,   255, 0,   TRUE,  TRUE }, /* 7 */
    {"Swamp",       "#g&",    8,  0,   128, 128, TRUE,  TRUE }, /* 8 */
    {"Swamp",       "#g&",    9,  0,   128, 128, TRUE,  TRUE }, /* 9 */
    {"Ground",      "#D*",    10, 178, 147, 4,   TRUE,  TRUE }, /* 10 */
    {"CityWall|",   "#D|",    11, 100, 200, 0,   FALSE, FALSE}, /* 11 */
    {"CityWall-",   "#D-",    12, 255,   0, 255, FALSE, FALSE}, /* 12 */
    {"City_Street", "#w.",    13, 200, 0,   0,   TRUE,  TRUE }, /* 13 */
    {"Door",        "#y+",    14, 200, 200, 0,   FALSE, FALSE}, /* 14 */
    {"Fountain",    "#C%",    15, 128, 64,  0,   TRUE,  TRUE }, /* 15 */
    {"Inside",      "#g.",    16, 235, 235, 235, TRUE,  TRUE }, /* 16 */
    {"unused",      "#G*",    17, 0,   128, 0,   TRUE,  TRUE }, /* 17 */
    {"CTree",       "#G*",    18, 0,   128, 0,   TRUE,  TRUE }, /* 18 */
    {"Door-open",   "#y.",    19, 2,   2,   2,   TRUE,  TRUE }, /* 19 */
    {"Nothing",     " ",      20, 3,   4,   5,   FALSE, FALSE}, /* 20 */
    {"Another_Char","#W@",    21, 4,   5,   6,   FALSE, FALSE}, /* 21 */
    {"Test",        "#1 #n",  22, 4,   5,   6,   FALSE, FALSE}, /* 22 */
    {"LetA",        "A",      23, 9,   9,   9,   TRUE,  TRUE},  /* 23 */
    {"LetB",        "B",      24, 9,   9,   9,   TRUE,  TRUE},  /* 24 */
    {"LetC",        "C",      25, 9,   9,   9,   TRUE,  TRUE},  /* 25 */
    {"LetD",        "D",      26, 9,   9,   9,   TRUE,  TRUE},  /* 26 */
    {"LetE",        "E",      27, 9,   9,   9,   TRUE,  TRUE},  /* 27 */
    {"LetF",        "F",      28, 9,   9,   9,   TRUE,  TRUE},  /* 28 */
    {"LetG",        "G",      29, 9,   9,   9,   TRUE,  TRUE},  /* 29 */
    {"LetH",        "H",      30, 9,   9,   9,   TRUE,  TRUE},  /* 30 */
    {"LetI",        "I",      31, 9,   9,   9,   TRUE,  TRUE},  /* 31 */
    {"LetJ",        "J",      32, 9,   9,   9,   TRUE,  TRUE},  /* 32 */
    {"LetK",        "K",      33, 9,   9,   9,   TRUE,  TRUE},  /* 33 */
    {"LetL",        "L",      34, 9,   9,   9,   TRUE,  TRUE},  /* 34 */
    {"LetM",        "M",      35, 9,   9,   9,   TRUE,  TRUE},  /* 35 */
    {"LetN",        "N",      36, 9,   9,   9,   TRUE,  TRUE},  /* 36 */
    {"LetO",        "O",      37, 9,   9,   9,   TRUE,  TRUE},  /* 37 */
    {"LetP",        "P",      38, 9,   9,   9,   TRUE,  TRUE},  /* 38 */
    {"LetQ",        "Q",      39, 9,   9,   9,   TRUE,  TRUE},  /* 39 */
    {"LetR",        "R",      40, 9,   9,   9,   TRUE,  TRUE},  /* 40 */
    {"LetS",        "S",      41, 9,   9,   9,   TRUE,  TRUE},  /* 41 */
    {"LetT",        "T",      42, 9,   9,   9,   TRUE,  TRUE},  /* 42 */
    {"LetU",        "U",      43, 9,   9,   9,   TRUE,  TRUE},  /* 43 */
    {"LetV",        "V",      44, 9,   9,   9,   TRUE,  TRUE},  /* 44 */
    {"LetW",        "W",      45, 9,   9,   9,   TRUE,  TRUE},  /* 45 */
    {"LetX",        "X",      46, 9,   9,   9,   TRUE,  TRUE},  /* 46 */
    {"LetY",        "Y",      47, 9,   9,   9,   TRUE,  TRUE},  /* 47 */
    {"LetZ",        "Z",      48, 9,   9,   9,   TRUE,  TRUE},  /* 48 */
    {"Temp Wall",   "#D-",    49, 128, 128, 128, FALSE, FALSE}, /* 49 */
    {"Temp Wall",   "#D|",    50,  64,   0, 255, FALSE, FALSE}, /* 50 */
    {NULL,"#R+", 17, 1, 2, 3, TRUE, TRUE},                      /* END */
};

/*
 * Display.c
 *
 * Contains Display Commands and Supporting
 * functions.
 */

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

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

/*
 * cmd_look()
 *
 * The look command
 */
void cmd_look(D_MOBILE * ch, char * arg)
{
    int x = 0;
    int y = 0;
    int viewx = ch->view_x;
    int viewy = ch->view_y;
    static int small_map[21][81];
    int start_x = (ch->x - (viewx / 2));
    int start_y = (ch->y - (viewy / 2));
    int sm_x = 0;
    int sm_y = 0;
    D_MOBILE *xMob; 
    D_SOCKET *dsock;
    BUFFER *buf = buffer_new(MAX_BUFFER);

    if (IS_SET(ch->player_flags, PLR_CLEAR_SCREEN))
        stc(CLEAR_SCREEN, ch);

    cmd_where(ch, ""); 
    
    /* Zero Small map array */
    for (y = 0; y < viewy; y++)
    {
        for (x = 0; x < viewx; x++)
        {
            small_map[y][x] = 1;
        }
    }
    /* Build the Terrain */
    for   (y = start_y; y != (start_y + viewy); y++)
    {
        for (x = start_x; x != (start_x + viewx); x++)
        {
            if (y == ch->y && x == ch->x)
                small_map[sm_y][sm_x] = SECTOR_CHAR;
            else
            {
                if (can_see_to(ch, x, y) == FALSE && !IS_SET (ch->immortal_flags, IMMORTAL_OMNI_VIEW))
                    small_map[sm_y][sm_x] = SECTOR_NOTHING;
                else
                    small_map[sm_y][sm_x] = return_number_of_map(map[y][x]);
                
                /* Build other Players && mobs */
                for (dsock = dsock_list; dsock; dsock = dsock->next)
                {
                    if (dsock->state != STATE_PLAYING)
                        continue;       /* Must be playing*/
                    if ((xMob = dsock->player) == NULL)
                        continue;       /* Must be valid */
                    
                    if ((xMob == ch))
                        continue;       /* Must not be CH */
                    
                    /* Ok lets see if this guys in the area.. */
                    if ((xMob->x == x) && (xMob->y == y))
                    {
                        small_map[sm_y][sm_x] = SECTOR_CHAR;
                    }
                    
                }
                
            }
            sm_x++;
            if (sm_x == viewx)
            {
                sm_x = 0;
            }
        }
        sm_y++;
    }
    
    /* Display Final Small map */
    for   (y = 0; y != (viewy); y++)
    {
        for (x = 0; x != (viewx); x++)
        {
            if (y == (ch->y - y) && x == (ch->x - x))
                bprintf(buf, "#R@");
            else
            {
                bprintf(buf, "%s", return_symbol(small_map[y][x]));
            }
            
            if (x == viewx - 1)
                bprintf(buf, "\n\r");
        }
    }
    
    /*
    for   (y = start_y; y != (start_y + viewy); y++)
    {
        for (x = start_x; x != (start_x + viewx); x++)
        {
            if (y == ch->y && x == ch->x && z == ch->z)
                bprintf(buf, "#R@");
            else
            {
                if (can_see_to(ch, x, y) == FALSE &&
                    !IS_SET (ch->immortal_flags, IMMORTAL_OMNI_VIEW))
                    bprintf(buf, " ");
                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);
}

int sector_number   (int number)
{
    int x;
    
    for (x = 0; x != MAX_SECTOR; x++)
    {
        if (sector_table[x].sector == number)
            return number;
    }
    return SECTOR_NOTHING;
}

/*
 * can_see_to()
 *
 * Returns TRUE if the sector is visable
 * Returns FALSE if its blocked anywhere in between
 */
bool can_see_to (D_M * ch, int target_x, int target_y)
{
    int x = ch->x;
    int y = ch->y;
    
    if (y < target_y && x < target_x)
    {
        for (y = ch->y; y != target_y; y++)
        {
            for (x = ch->x; x != target_x; x++)
            {
                if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
            }
        }
    }
    else if (y > target_y && x > target_x)
    {
        for (y = ch->y; y != target_y; y--)
        {
            for (x = ch->x; x != target_x; x--)
            {
                if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
            }
        }
    }
    else if (y < target_y && x > target_x)
    {
        for (y = ch->y; y != target_y; y++)
        {
            for (x = ch->x; x != target_x; x--)
            {
                if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
            }
        }
    }
    else if (y > target_y && x < target_x)
    {
        for (y = ch->y; y != target_y; y--)
        {
            for (x = ch->x; x != target_x; x++)
            {
                if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
            }
        }
    }
    else if (target_y == y && x > target_x)
    {
        for (x = ch->x; x != target_x; x--)
        { 
            if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
        }
    }
    else if (target_y == y && x < target_x)
    {
        for (x = ch->x; x != target_x; x++)
        { 
            if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
        }
    }
    else if (target_x == x && y < target_y)
    {
        for (y = ch->y; y != target_y; y++)
        { 
            if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
        }
    }
    else if (target_x == x && y > target_y)
    {
        for (y = ch->y; y != target_y; y--)
        { 
            if (sector_table[map[y][x]].can_see_through != TRUE)
                    return FALSE;
        }
    }
    
    else
        return TRUE;
        
    return TRUE;

}

/*
 * return_symbol()
 *
 * Returns sector symbol from sector_table
 * used in cmd_look()
 */
char * return_symbol(int location)
{

    int i = 0;
    static char buf[1024];
    
    for (i = 0; i <= MAX_SECTOR; i++)
    {
        if (sector_table[i].sector == location)
        {
            sprintf(buf, "%s", sector_table[i].char_sm);
            break;
        }
        else
            sprintf(buf, "#R+");
    }
    return buf;
}

int return_number_of_map(int location)
{

    int i = 0;
    int bob;
    
    for (i = 0; i <= MAX_SECTOR; i++)
    {
        if (sector_table[i].sector == location)
        {
            bob = sector_table[i].sector;
            break;
        }
    }
    return bob;
}

/* Movement commands */

void cmd_north(D_MOBILE * ch, char *arg)
{
    if (check_move_ok(ch, DIR_NORTH) == TRUE)
        ch->y--;
    else
        stc("You cannot move that direction.\n\r", ch);
    
    cmd_look(ch, "");
}

void cmd_south(D_MOBILE * ch, char *arg)
{
    if (check_move_ok(ch, DIR_SOUTH) == TRUE)
        ch->y++;
    else
        stc("You cannot move that direction.\n\r", ch);
    
    cmd_look(ch, "");
}

void cmd_west(D_MOBILE * ch, char *arg)
{
    if (check_move_ok(ch, DIR_WEST) == TRUE)
        ch->x--;
    else
        stc("You cannot move that direction.\n\r", ch);
    
    cmd_look(ch, "");
}

void cmd_east(D_MOBILE * ch, char *arg)
{
    if (check_move_ok(ch, DIR_EAST) == TRUE)
        ch->x++;
    else
        stc("You cannot move that direction.\n\r", ch);
    
    cmd_look(ch, "");
}

void cmd_up (D_MOBILE * ch, char *arg)
{
    if (check_move_ok(ch, DIR_UP) == TRUE)
        ch->z++;
    else
        stc("You cannot move that direction.\n\r", ch);
    
    cmd_look(ch, "");
}

void cmd_down (D_MOBILE * ch, char *arg)
{
    if (check_move_ok(ch, DIR_DOWN) == TRUE)
        ch->z--;
    else
        stc("You cannot move that direction.\n\r", ch);
    
    cmd_look(ch, "");
}

bool check_move_ok (D_M * ch, int direction)
{
    bool can_move = TRUE;
    int next_x  = (ch->x);
    int next_y  = (ch->y);
    int next_z  = (ch->z);
    
    switch(direction)
    {   default:
            stc("*** BUG *** check_move_ok: Invalid direction\n\r", ch);
            break;
        case DIR_NORTH:
            if (ch->y != 20)
                can_move = FALSE;
            next_y--;
            break;
        case DIR_SOUTH:
            if (ch->y != (MAX_Y - 20))
                can_move = FALSE;
            next_y++;
            break;
        case DIR_WEST:
            if (ch->x != 20)
                can_move = FALSE;
            next_x--;
            break;
        case DIR_EAST:
            if (ch->x != (MAX_X - 20))
                can_move = FALSE;
            next_x++;
            break;
        case DIR_UP:
            if (ch->z != 11)
                can_move = FALSE;
            next_z++;
            break;
        case DIR_DOWN:
            if (ch->z != 0)
                can_move = FALSE;
            next_z--;
            break;
    }
    
    /* Pass door for imms */
    if (!IS_SET (ch->immortal_flags, IMMORTAL_PASS_DOOR))
    {
        if (sector_table[map[next_y][next_x]].passable == FALSE)
        {
            stc("You cannot move that way!\n\r", ch);
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    }
    else
    {
        return TRUE;
    }
    
    return TRUE;
}
        
/*
 * cmd_open()
 *
 * Basic command to open a door in given
 * direction.
 */
void cmd_open (D_MOBILE * ch, char *argument)
{
    char arg[MAX_BUFFER];
    int x   = ch->x;
    int y   = ch->y;
    one_arg (argument, arg);

    if (arg[0] == '\0')
    {
        send_to_char ("Open what direction?\n\r", ch);
        return;
    }
    
    if (!str_prefix(arg, "north"))
    {
        y--;
        if (map[y][x] != 14)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 19;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else if (!str_prefix(arg, "south"))
    {
        y++;
        if (map[y][x] != 14)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 19;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else if (!str_prefix(arg, "west"))
    {
        x--;
        if (map[y][x] != 14)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 19;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else if (!str_prefix(arg, "east"))
    {
        x++;
        if (map[y][x] != 14)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 19;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else
    {
        stc("Open door in what direction?\n\r", ch);
        return;
    }
}
/*
 * cmd_close()
 *
 * Basic command to close a door in given direction
 */
void cmd_close (D_MOBILE * ch, char *argument)
{
    char arg[MAX_BUFFER];
    int x   = ch->x;
    int y   = ch->y;
    one_arg (argument, arg);

    if (arg[0] == '\0')
    {
        send_to_char ("Open what direction?\n\r", ch);
        return;
    }
    
    if (!str_prefix(arg, "north"))
    {
        y--;
        if (map[y][x] != 19)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 14;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else if (!str_prefix(arg, "south"))
    {
        y++;
        if (map[y][x] != 19)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 14;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else if (!str_prefix(arg, "west"))
    {
        x--;
        if (map[y][x] != 19)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 14;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else if (!str_prefix(arg, "east"))
    {
        x++;
        if (map[y][x] != 19)
        {
            stc("There is no door there!\n\r", ch);
            return;
        }
        map[y][x] = 14;
        cmd_look(ch, "");
        stc("Opening door..\n\r", ch);
        return;
    }
    else
    {
        stc("Open door in what direction?\n\r", ch);
        return;
    }
}
    

int return_distance(D_M * ch, D_M * victim)
{
        int x, y;
        x = 0;
        y = 0;
        
        if (  ch->x == victim->x
           && ch->y == victim->y)
        {
                return 0;
        }

        if (ch->x <= victim->x)
                x = (victim->x - ch->x);
        else if (ch->x >= victim->x)
                x = (ch->x - victim->x);
        else if (ch->x == victim->x)
                x = 0;
        else
                x = -200;
        
        if (ch->y <= victim->y)
                y = (victim->y - ch->y);
        else if (ch->y >= victim->y)
                y = (ch->y - victim->y);
        else if (ch->y == victim->y)
                y = 0;
        else
                y = -100;
        
        return (x + y);
        
}