/
area/city/
area/crypts/
area/guilds/
area/psuedowild/
area/religion/
data/documents/MPDocs/
data/html/
data/mobprogs/
data/quest/
data/world/
data/world/_utilities/
data/world/images/
design/html/
notes/
player/
#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>
#include "merc.h"
#include "world.h"
#include "recycle.h"


#define MOVE_AMMOUNT    10
 
/*
 * wilderness_table()
 *
 * Contains all sectors, their internal name, color/symbol, their
 * save number, the RGB colors, if its passable, and if you can
 * see 'through' it.
 */ 
struct wilderness_type wilderness_table[] =
    {                       /*#   Red  Grn  Blu */
    {"Grass",       "{g.",    0,    0, 255,   0, TRUE,  TRUE }, /* 0 */
    {"Mountain",    "{D^",    1,    0,   0,   0, TRUE,  TRUE }, /* 1 */
    {"River",       "{C~",    2,    0, 255, 255, TRUE,  TRUE }, /* 2 */
    {"Ocean",       "{b~",    3,    0,   0, 255, TRUE,  TRUE }, /* 3 */
    {"Beach",       "{y.",    4,    1,   1,   1, TRUE,  TRUE }, /* 4 */
    {"Desert",      "{y^",    5,  255, 255,   0, TRUE,  TRUE }, /* 5 */
    {"Hills",       "{w^",    6,  128, 128, 128, TRUE,  TRUE }, /* 6 */
    {"Tree",        "{G*",    7,    0, 128,   0, TRUE,  TRUE }, /* 7 */
    {"Swamp",       "{g&",    8,  128, 255, 128, TRUE,  TRUE }, /* 8 */
    {"City ",       "{W|",    9,  255, 128,  64, FALSE, TRUE }, /* 9 */
    {"City ",       "{W-",   10,  128,  64,   0, FALSE, TRUE }, /*10 */
    {"Door",        "{y+",   11,    2,   2,   2, TRUE,  TRUE }, /*11 */
    {"V",           "{wV",   12,   10,  10,  10, TRUE,  TRUE }, /*12 */
    {"a",           "{wa",   13,   10,  10,  11, TRUE,  TRUE }, /*13 */
    {"n",           "{wn",   14,   10,  10,  12, TRUE,  TRUE }, /*14 */
    {"d",           "{wd",   15,   10,  10,  13, TRUE,  TRUE }, /*15 */
    {"a",           "{wa",   16,   10,  10,  14, TRUE,  TRUE }, /*16 */
    {"g",           "{wg",   17,   10,  10,  15, TRUE,  TRUE }, /*17 */
    {"a",           "{wa",   18,   10,  10,  16, TRUE,  TRUE }, /*18 */
    {"r",           "{wr",   19,   10,  10,  17, TRUE,  TRUE }, /*19 */
    {"d",           "{wd",   20,   10,  10,  18, TRUE,  TRUE }, /*20 */
    {"empty",       "{x ",   21,  240, 240, 240, TRUE,  TRUE }, /*21 */
    {"T",           "{wT",   22,   10,  10,  19, TRUE,  TRUE }, /*22 */
    {"h",           "{wh",   23,   10,  10,  20, TRUE,  TRUE }, /*23 */
    {"e",           "{we",   24,   10,  10,  21, TRUE,  TRUE }, /*24 */
    {"C",           "{wC",   25,   10,  10,  22, TRUE,  TRUE }, /*25 */
    {"i",           "{wi",   26,   10,  10,  23, TRUE,  TRUE }, /*26 */
    {"t",           "{wt",   27,   10,  10,  24, TRUE,  TRUE }, /*27 */
    {"y",           "{wy",   28,   10,  10,  25, TRUE,  TRUE }, /*28 */
    {"o",           "{wo",   29,   10,  10,  26, TRUE,  TRUE }, /*29 */
    {"f",           "{wf",   30,   10,  10,  27, TRUE,  TRUE }, /*30 */
    
     
    {"nothing",     "{x ",   98,   -1,  -1,  -1, FALSE, FALSE}, /*31 */
    {NULL,          "{R+",   99,   -1,  -1,  -1, TRUE,  TRUE},  /*END*/
};

/* Called in load_muddata
 * Just to load the world on starup/copyover */
void load_world_data()
{
    /*
    save_zworld();
    log_string(" WORLD *** Saved World.\n\r");
    */
    load_zworld();
    log_string("*** WORLD ******* Loaded ZWorld.");
    load_wexit();
    
}

/* cmd to forcefuly save the world */
void cmd_save_world(D_MOBILE * ch, char *arg)
{
    stc("Saving zworld structure...\n\r", ch);
    save_zworld();
    stc("Save zworld complete!\n\r", ch);
}

/* cmd to forcerful reload the world */
void cmd_load_world(D_MOBILE * ch, char *arg)
{ 
    stc("Reverting zworld structure...\n\r", ch);
    load_zworld();
    stc("Revert zworld complete!\n\r", ch);
}

/*
 * save_zworld()
 * 
 * Saves the world!
 */
void save_zworld()
{
    gzFile *fp; 

    fp = gzopen(WORLD_FILE,"wb9");
    gzwrite(fp,map,sizeof(map));
    gzclose(fp);
}

/*
 * load_zworld()
 *
 * Loads the world!
 */
void load_zworld()
{
    gzFile *fp;

    fp = gzopen(WORLD_FILE,"rb9");
    gzread(fp,map,sizeof(map));
    gzclose(fp);
}

/*
 * cmd_wiz_world()
 *
 * Some basic load/save/export functions for the world.
 */
void cmd_wiz_world(D_MOBILE * ch, char *argument)
{
    char arg1[MSL];
    
    argument = one_argument (argument, arg1);
    
    if (arg1[0] == '\0')
    {
        stc("Syntax: wset <function>\n", ch);
        stc("wset loadimage     - Loads default image\n", ch);
        stc("wset save          - Saves the world data file\n", ch);
        stc("wset export        - Exports the world image to a raw image\n", ch);
        stc("wset saveexit      - Saves the exit list\n", ch);
        return;
    }
    if (!str_prefix (arg1, "loadimage"))
    {
        stc("Attempting to load image into the game world..\n", ch);
        cmd_load_image(ch, "");
        stc("Check console for results.\n", ch);
        return;
    }
    if (!str_prefix (arg1, "save"))
    {
        stc("Saving the world image file.\n", ch);
        save_zworld();
        return;
    }
    if (!str_prefix (arg1, "export"))
    {
        stc("Thri is lazy. Export not finished yet.\n", ch);
        return;
    }
    if (!str_prefix (arg1, "saveexit"))
    {
        stc("Forcefuly saving wilderness exit data\n", ch);
        save_wexit();
        return;
    }
    else
    {
        cmd_wiz_world(ch, "");
        return;
    }
    return;
}
    
    

/*
 * cmd_look()
 * 
 * The all purpose display command while on the
 * wilderness. Its simple right now, i need to
 * keep it that way.
 */
void cmd_look(D_MOBILE * ch, char *arg)
{
    int x, y;
    int viewx = 31;
    int viewy = 15;
    int start_x = (ch->x - (viewx / 2));
    int start_y = (ch->y - (viewy / 2));
    BUFFER *output = new_buf ();
    char buf[MSL];

    add_buf(output, "{D.---- {wThe World of {RS{roulblight{D ----.{x\n\r");
    add_buf(output, "{D|                                 |{x\n\r");
    
    for (y = start_y; y != (start_y + viewy); y++)
    {
        add_buf(output, "{D|{x ");
        for (x = start_x; x != (start_x + viewx); x++)
        {
            if (y == ch->y && x == ch->x)
            {
                sprintf(buf, "{R@");
                add_buf (output, buf);
            }
            else
            {

                /* Fixing crashes as a result of edge of map */
                if (x <= 0 || y <= 0)
                {
                    sprintf(buf, " ");
                    add_buf (output, buf);
                }
                else if (x >= MAX_WIDTH || y <= 0)
                {
                    sprintf(buf, " ");
                    add_buf (output, buf);
                }
                else if (x <= 0 || y >= MAX_HEIGHT)
                {
                    sprintf(buf, " ");
                    add_buf (output, buf);
                }
                else if (x >= MAX_WIDTH || y >= MAX_HEIGHT)
                {
                    sprintf(buf, " ");
                    add_buf (output, buf);
                }
                else
                {
                    sprintf(buf, "%s", return_symbol(map[y][x]));
                    add_buf (output, buf);
                }
            }
        }
        sprintf(buf, "{D |{x\n");
        add_buf (output, buf);
    }

    add_buf(output, "{D|                                 |{x\n\r");
    add_buf(output, "{D'---------------------------------'{x\n\r");
    page_to_char (buf_string (output), ch);
    free_buf (output);

    stc("\n{x", ch);
    check_wexit(ch);
    return;
}

/*
 * return_symbol()
 *
 * Returns sector symbol from sector_table
 * used in cmd_look()
 */
char * return_symbol(int location)
{
    int i = 0;
    static char buf[1024];
    
    if (location == -5)
    {
        sprintf(buf, "{x ");
        return buf;
    }
    
    for (i = 0; i <= MAX_WILD_SECTOR; i++)
    {
        if (wilderness_table[i].sector == location)
        {
            sprintf(buf, "%s", wilderness_table[i].char_sm);
            break;
        }
        else
            sprintf(buf, "{R+");
    }
    return buf;
}

/*
 * can_see_to()
 *
 * This ugly piece of code determines if
 * you can 'see' to the given sector, checks
 * for blocking terrain.
 */
int 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 (wilderness_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 (wilderness_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 (wilderness_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 (wilderness_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 (wilderness_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 (wilderness_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 (wilderness_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 (wilderness_table[map[y][x]].can_see_through != TRUE)
                return FALSE;
        }
    }
    
    else
        return TRUE;
        
    return TRUE;
}

/*
 * cmd_north()
 *
 * Moves the player 1 square north
 * on the world map.
 */
void cmd_north (D_MOBILE * ch, char *arg)
{
    if (ch->y <= 0)
    {
        stc("You'll fall off the world if you go any further north!\n\r", ch);
        return;
    }
    ch->y -= MOVE_AMMOUNT;
    cmd_look(ch, "");
    return;
}

/*
 * cmd_south()
 *
 * Moves the player 1 square south
 * on the world map.
 */
void cmd_south (D_MOBILE * ch, char *arg)
{
    if (ch->y >= MAX_HEIGHT)
    {
        stc("You'll fall off the world if you go any further south!\n\r", ch);
        return;
    }
    
    ch->y += MOVE_AMMOUNT;
    cmd_look(ch, "");
    return;
}

/*
 * cmd_west()
 *
 * Moves the player 1 square west
 * on the world map.
 */
void cmd_west (D_MOBILE * ch, char *arg)
{
    if (ch->x <= 0)
    {
        stc("You'll fall off the world if you go any further west!\n\r", ch);
        return;
    }
    ch->x -= MOVE_AMMOUNT;
    cmd_look(ch, "");
    return;
}

/*
 * cmd_east()
 *
 * Moves the player 1 square east
 * on the world map.
 */
void cmd_east (D_MOBILE * ch, char *arg)
{
    if (ch->x >= MAX_WIDTH)
    {
        stc("You'll fall off the world if you go any further east!\n\r", ch);
        return;
    }
    ch->x += MOVE_AMMOUNT;
    cmd_look(ch, "");
    return;
}

/*
 * check_move_ok()
 *
 * Checks to see if the next sector is ok to move to..
 */
bool check_move_ok (D_M * ch, int direction)
{
    bool can_move = TRUE;
    int next_x  = (ch->x);
    int next_y  = (ch->y);
    
    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_HEIGHT - 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_WIDTH - 20))
                can_move = FALSE;
            next_x++;
            break;
    }
    
    /* Pass door for imms 
    if (!IS_SET (ch->immortal_flags, IMMORTAL_PASS_DOOR))
    {
    */
    if (wilderness_table[map[next_y][next_x]].passable == FALSE)
        {
            stc("{xYou cannot move that way!\n\r", ch);
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    
    return TRUE;
}

/*
 * cmd_load_image()
 *
 * Loads the image from file to the world.
 */
void cmd_load_image(D_MOBILE * ch, char *arg) 
{
    FILE * fp; 
    int x, y, graph1, graph2, graph3; 
     
    if( !( fp = fopen( IMAGE_FILE, "rb" ) ) )
    {
        log_string("Error: Cannot open file.");
        return;
    }

    log_string("Loaded file, trying to create map");
    
    for (y = 0; y < MAX_WIDTH; y++)
    {
        for (x = 0; x < MAX_HEIGHT; x++)
        {
            graph1 = fgetc(fp);
            graph2 = fgetc(fp);
            graph3 = fgetc(fp); 
            map[y][x] = return_sector_number(graph1, graph2, graph3);
        }
    }
    log_string("Sucess!");
    fclose( fp );
    return;
}

/*
 * return_sector_number()
 *
 * Returns sector number from wilderness_table
 * based on given RGB values.
 */
int return_sector_number(int r, int g, int b)
{
    int i;
    int final;
    
    for (i = 0; i < MAX_WILD_SECTOR - 1; i++)
    {
        if (wilderness_table[i].red == r && wilderness_table[i].green == g && wilderness_table[i].blue == b)
        {
            final = wilderness_table[i].sector;
            break;
        }
        else
            final = MAX_WILD_SECTOR;
    }
    return final;
}

/*
 * show_wild_chars()
 *
 * Displays all charaters/mobiles within range of the player on
 * the world map. For fun, the size of the player determines how
 * far they can see them away. So a giant can be seen from say, 6 squares
 * away, but a tiny sprite can only be seen on the same square
 */
void show_wild_chars(CHAR_DATA * list, CHAR_DATA * ch)
{
    CHAR_DATA *rch;
    int range;
    
    for (rch = list; rch != NULL; rch = rch->next_in_room)
    {
        if (rch == ch)
            continue;

        if (get_trust (ch) < rch->invis_level)
            continue;

        switch(rch->size)
        {   default:
            case SIZE_TINY:
                range = 10;
                break;
            case SIZE_SMALL:
                range = 20;
                break;
            case SIZE_MEDIUM:
                range = 30;
                break;
            case SIZE_LARGE:
                range = 40;
                break;
            case SIZE_HUGE:
                range = 50;
                break;
            case SIZE_GIANT:
                range = 60;
                break;
        }
        
        if (can_see (ch, rch))
        {
                if (return_distance(ch, rch) <= range)
                show_char_to_char_0 (rch, ch);
        }
    }
    return;
}

void show_wild_objects(CHAR_DATA * ch)
{
    show_list_to_char (ch->in_room->contents, ch, FALSE, FALSE, TRUE);
    return;
}