swrip/bin/
swrip/doc/mudprogs/
swrip/gods/
swrip/player/d/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"

/* Size of the map and depth of recursion to undertake */
#define MAPX     10
#define MAPY      8
#define MAXDEPTH  4

/* Ensure coord is on the map */
#define BOUNDARY(x, y) (((x) < 0) || ((y) < 0) || \
                        ((x) > MAPX) || ((y) > MAPY))

/* Structure for the map itself */
struct map_type
{
    /* Character to print at this map coord */
    char mapch;
    /* Room this coord represents */
    int vnum;
    /* Recursive depth this coord was found at */
    int depth;
    int info;
    bool can_see;
};

/* Chars for each of the four compass direction exits */
char map_chars[5] = "|-|-";
/* The map itself */
struct map_type map[MAPX + 1][MAPY + 1];

/* Take care of some repetitive code for later */
void get_exit_dir( int dir, int *x, int *y, int xorig, int yorig )
{
    /* Get the next coord based on direction */
    switch( dir )
    {
    /* North */
    case 0:
        *x = xorig;
        *y = yorig - 1;
        break;
    /* East */
    case 1:
        *x = xorig + 1;
        *y = yorig;
        break;
    /* South */
    case 2:
        *x = xorig;
        *y = yorig + 1;
        break;
    /* West */
    case 3:
        *x = xorig - 1;
        *y = yorig;
        break;
    case 6:
        *x = xorig + 1;
        *y = yorig - 1;
        break;
    case 7:
        *x = xorig - 1;
        *y = yorig - 1;
        break;
    case 8:
        *x = xorig + 1;
        *y = yorig + 1;
        break;
    case 9:
        *x = xorig - 1;
        *y = yorig + 1;
        break;
        
    default:
        *x = -1;
        *y = -1;
        break;
    }
}

/* Clear one map coord */
void clear_coord( int x, int y )
{
    map[x][y].mapch = ' ';
    map[x][y].vnum = 0;
    map[x][y].depth = 0;
    map[x][y].info = 0;
    map[x][y].can_see = TRUE;
}

/* Clear all exits for one room */
void clear_room( int x, int y )
{
    int dir, exitx, exity;

    /* Cycle through the four directions */
    for( dir = 0; dir < 10; dir++ )
    {
        /* Find next coord in this direction */
        get_exit_dir( dir, &exitx, &exity, x, y );
        /* If coord is valid, clear it */
        if ( !BOUNDARY( exitx, exity ) )
            clear_coord( exitx, exity );
    }
}

/* This function is recursive, ie it calls itself */
void map_exits( CHAR_DATA *ch, ROOM_INDEX_DATA *pRoom,
                int x, int y, int depth )
{
    int door;
    int exitx = 0, exity = 0;
    int roomx = 0, roomy = 0;
    EXIT_DATA *pExit;
/*
    char *buf;
    
    for ( rch = pRoom->first_person; rch; rch = rch->next_in_room )
	count++;
   
    sprintf( buf, "%d", count );
*/
    /* Setup this coord as a room */
    map[x][y].mapch = 'O';
    map[x][y].vnum = pRoom->vnum;
    map[x][y].depth = depth;
    map[x][y].info = pRoom->room_flags;
    map[x][y].can_see = room_is_dark( pRoom );

    /* Limit recursion */
    if ( depth > MAXDEPTH )
        return;

    /* This room is done, deal with it's exits */
    for( door = 0; door < 10; door++ )
    {
        /* Skip if there is no exit in this direction */
/*      for (xit = pRoom->first_exit; xit; xit = xit->next )
        if ( xit->vdir == door )
          break;
      if ( !xit )
        continue;
*/
      if ( ( pExit = get_exit( pRoom, door ) )== NULL )
           continue;

        /* Get the coords for the next exit and room in this direction */
        get_exit_dir( door, &exitx, &exity, x, y );
        get_exit_dir( door, &roomx, &roomy, exitx, exity );

        /* Skip if coords fall outside map */
        if ( BOUNDARY( exitx, exity ) || BOUNDARY( roomx, roomy ) )
            continue;

        /* Skip if there is no room beyond this exit */
        if ( pExit->to_room == NULL )
            continue;

        /* Ensure there are no clashes with previously defined rooms */
        if ( ( map[roomx][roomy].vnum != 0 ) &&
             ( map[roomx][roomy].vnum != pExit->to_room->vnum ) )
        {
            /* Use the new room if the depth is higher */
            if ( map[roomx][roomy].depth <= depth )
                continue;

            /* It is so clear the old room */
            clear_room( roomx, roomy );
        }

        /* No exits at MAXDEPTH */
        if ( depth == MAXDEPTH )
            continue;

        /* No need for exits that are already mapped */
        if ( map[exitx][exity].depth > 0 )
            continue;

        /* Fill in exit */
        map[exitx][exity].depth = depth;
        map[exitx][exity].vnum = pExit->to_room->vnum;
        map[exitx][exity].info = pExit->exit_info;
//      sprintf( buf, "%c", map_chars[door] );
        map[exitx][exity].mapch = map_chars[door];

        /* Place Marker 1 - referred to later */

        /* More to do? If so we recurse */
        if ( ( depth < MAXDEPTH ) &&
             ( ( map[roomx][roomy].vnum == pExit->to_room->vnum ) ||
               ( map[roomx][roomy].vnum == 0 ) ) )
        {
            /* Depth increases by one each time */
            map_exits( ch, pExit->to_room, roomx, roomy, depth + 1 );
        }
    }
}

/* Reformat room descriptions to exclude undesirable characters */
#if 0
void reformat_desc( char *desc )
{
    /* Index variables to keep track of array/pointer elements */
    int i, j;
    char buf[MAX_STRING_LENGTH], *p;

    i = 0;
    j = 0;
    buf[0] = '\0';

    if ( IS_NULLSTR( desc ) )
        return;

    /* Replace all "\n" and "\r" with spaces */
    for( i = 0; i <= strlen( desc ); i++ )
    {
        if ( ( desc[i] == '\n' ) || ( desc[i] == '\r' ) )
            desc[m] = ' ';
    }

    /* Remove multiple spaces */
    for( p = desc; *p != '\0'; p++ )
    {
        buf[j] = *p;
        j++;

        /* Two or more consecutive spaces? */
        if ( ( *p == ' ' ) && ( *( p + 1 ) == ' ' ) )
        {
            do
            {
                p++;
            } while( *p == ' ' );
        }
    }

    buf[j] = '\0';

    /* Copy to desc */
    sprintf( desc, buf );
}

int get_line( char *desc, int max_len )
{
    int i, j;

    /* Return if it's short enough for one line */
    if ( strlen( desc ) <= max_len )
        return 0;

    /* Calculate end point in string without color */
    for( i = 0; i <= strlen( desc ); i++ )
    {
        /* Here you need to skip your color sequences */
      if( (desc[j] == '&' && desc[j+1] != '&') || (desc[j] == '^' && desc[j+1] != '^')
        j--;
      else
        j++;

        if ( j > max_len )
            break;
    }

    /* End point is now in i, find the nearest space */
    for( j = i; j > 0; j-- )
    {
        if ( desc[j] == ' ' )
            break;
    }

    /* There could be a problem if there are no spaces on the line */

    return j + 1;
}
#endif
/* Display the map to the player */
void show_map( CHAR_DATA *ch, char *text )
{
    char buf[MAX_STRING_LENGTH * 2];
    int x, y, pos;
    char *p;

    pos = 0;
    p = text;
    buf[0] = '\0';

    /* Place Marker 2 - referred to later */

    /* Top of map frame */
    sprintf( buf, "+-----------+ " );
    /* First line of text */
    strcat( buf, "\n\r" );

    /* Write out the main map area with text */
    for( y = 0; y <= MAPY; y++ )
    {
        strcat( buf, "|" );

        for( x = 0; x <= MAPX; x++ )
        {
            /* Choose a color based on map contents here */

            /* Write the map character */
            sprintf( buf + strlen( buf ), "%c", map[x][y].mapch );
        }

        strcat( buf, "| \n\r" );
        /* Add the text, if necessary */
    }

    /* Finish off map area */
    strcat( buf, "+-----------+ " );

    /* Deal with any leftover text */

    /* Act can also be used here, as can send_to_char if desired */
    send_to_pager( buf, ch );
}

/* Clear, generate and display the map */
void do_draw( CHAR_DATA *ch, char *desc )
{
    int x, y;
    static char buf[MAX_STRING_LENGTH];
    OBJ_DATA *device;
    //sprintf( buf, desc );
    /* Remove undesirable characters */
    //reformat_desc( buf );

    if ( ( device = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
    {
	send_to_char( "You must have a scanner to draw a map of the surrounding area.\n\r", ch );
	return;
    }

    if ( device->item_type != ITEM_DEVICE )
    {
	send_to_char( "You must have a scanner to draw a map of the surrounding area.\n\r", ch );
	return;
    }

    if (device->value[3] != 52 )
    {
	send_to_char( "You must have a scanner to draw a map of the surrounding area.\n\r", ch );
	return;
    }

    if ( device->value[2] <= 0 )
    {
        send_to_char( "Your scanner has no more charge left.", ch);
        return;
    }

    
    device->value[2]--;

    /* Clear map */
    for( y = 0; y <= MAPY; y++ )
    {
        for( x = 0; x <= MAPX; x++ )
        {
            clear_coord( x, y );
        }
    }

    /* Start with players pos at centre of map */
    x = MAPX / 2;
    y = MAPY / 2;

    map[x][y].vnum = ch->in_room->vnum;
    map[x][y].depth = 0;

    /* Generate the map */
    map_exits( ch, ch->in_room, x, y, 0 );

    /* Current position should be a "X" */
//  sprintf( buf2, "%c", 'X' );
    map[x][y].mapch = 'X';
    /* Send the map */
    show_map( ch, buf );
}