/
mudtem/
mudtem/area/scripts/
mudtem/bin/
mudtem/log/
mudtem/player/
mudtem/slang/autoconf/
mudtem/slang/doc/
mudtem/slang/doc/OLD/help/
mudtem/slang/doc/internal/
mudtem/slang/doc/text/
mudtem/slang/doc/tm/tools/
mudtem/slang/examples/
mudtem/slang/modules/
mudtem/slang/slsh/
mudtem/slang/slsh/lib/
mudtem/slang/slsh/scripts/
mudtem/slang/src/mkfiles/
mudtem/slang/src/util/
mudtem/src/CVS/
mudtem/src/include/
mudtem/src/include/CVS/
mudtem/src/var/CVS/
/*
 * MazeGen.c -- Mark Howell -- 8 May 1991
 *
 * Usage: MazeGen vnum [width [height [seed]]]
 */
#include "include.h"
#include <time.h>

char *fwrite_flag( long flags, char buf[] );

#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3

#define cell_empty(a) (!(a)->up && !(a)->right && !(a)->down && !(a)->left)

typedef struct {
    unsigned int up      : 1;
    unsigned int right   : 1;
    unsigned int down    : 1;
    unsigned int left    : 1;
    unsigned int path    : 1;
    unsigned int visited : 1;
} cell_t;
typedef cell_t *maze_t;

void CreateMaze (maze_t maze, int width, int height)
{
    maze_t mp, maze_top;
    char paths [4];
    int visits, directions;

    visits = width * height - 1;
    mp = maze;
    maze_top = mp + (width * height) - 1;

    while (visits) {
        directions = 0;

        if ((mp - width) >= maze && cell_empty (mp - width))
            paths [directions++] = UP;
        if (mp < maze_top && ((mp - maze + 1) % width) && cell_empty (mp + 1))
            paths [directions++] = RIGHT;
        if ((mp + width) <= maze_top && cell_empty (mp + width))
            paths [directions++] = DOWN;
        if (mp > maze && ((mp - maze) % width) && cell_empty (mp - 1))
            paths [directions++] = LEFT;

        if (directions) {
            visits--;
            directions = ((unsigned) rand () % directions);

            switch (paths [directions]) {
                case UP:
                    mp->up = TRUE;
                    (mp -= width)->down = TRUE;
                    break;
                case RIGHT:
                    mp->right = TRUE;
                    (++mp)->left = TRUE;
                    break;
                case DOWN:
                    mp->down = TRUE;
                    (mp += width)->up = TRUE;
                    break;
                case LEFT:
                    mp->left = TRUE;
                    (--mp)->right = TRUE;
                    break;
                default:
                    break;
            }
        } else {
            do {
                if (++mp > maze_top)
                    mp = maze;
            } while (cell_empty (mp));
        }
    }
}/* CreateMaze */


void SolveMaze (maze_t maze, int width, int height)
{
    maze_t *stack, mp = maze;
    int sp = 0;

    stack = (maze_t *) mud_calloc (width * height, sizeof (maze_t));
    if (stack == NULL) {
        (void) fprintf (stderr, "Cannot allocate memory!\n");
        exit (EXIT_FAILURE);
    }
    (stack [sp++] = mp)->visited = TRUE;

    while (mp != (maze + (width * height) - 1)) {

        if (mp->up && !(mp - width)->visited)
            stack [sp++] = mp - width;
        if (mp->right && !(mp + 1)->visited)
            stack [sp++] = mp + 1;
        if (mp->down && !(mp + width)->visited)
            stack [sp++] = mp + width;
        if (mp->left && !(mp - 1)->visited)
            stack [sp++] = mp - 1;

        if (stack [sp - 1] == mp)
            --sp;

        (mp = stack [sp - 1])->visited = TRUE;
    }
    while (sp--)
        if (stack [sp]->visited)
            stack [sp]->path = TRUE;

    free (stack);

}/* SolveMaze */


void PrintMaze (FILE *fp, maze_t maze, int width, int height)
{
    int w, h;
    char *line, *lp;

    line = (char *) mud_calloc ((width + 1) * 2, sizeof (char));
    if (line == NULL) {
        (void) fprintf (stderr, "Cannot allocate memory!\n");
        exit (EXIT_FAILURE);
    }
    maze->up = TRUE;
    (maze + (width * height) - 1)->down = TRUE;

    for (lp = line, w = 0; w < width; w++) {
        *lp++ = '+';
        if ((maze + w)->up)
            *lp++ = ((maze + w)->path) ? '.' : ' ';
        else
            *lp++ = '-';
    }
    *lp++ = '+';
    (void) fputs (line, fp);
    (void) fputs ("\n", fp);
    for (h = 0; h < height; h++) {
        for (lp = line, w = 0; w < width; w++) {
            if ((maze + w)->left)
                *lp++ = ((maze + w)->path && (maze + w - 1)->path) ? '.' : ' ';
            else
                *lp++ = '|';
            *lp++ = ((maze + w)->path) ? '.' : ' ';
        }
        *lp++ = '|';
        (void) fputs (line, fp);
	(void) fputs ("\n", fp);
        for (lp = line, w = 0; w < width; w++) {
            *lp++ = '+';
            if ((maze + w)->down)
                *lp++ = ((maze + w)->path && (h == height - 1 ||
                         (maze + w + width)->path)) ? '.' : ' ';
            else

                *lp++ = '-';
        }
        *lp++ = '+';
        (void) fputs (line, fp);
        (void) fputs ("\n", fp);
        maze += width;
    }
    free (line);

}/* PrintMaze */

void Maze2Area (FILE *fp, maze_t maze, int width, int height, int startvnum)
{
    int w, h;
	int vnum=0;
	int num_exit;

	fprintf(fp, "#ROOMS\n");

    maze->up = 0;
    (maze + (width * height) - 1)->down = 0;

    for (h = 0; h < height; h++) 
	{
        for (w = 0; w < width; w++) 
		{
			num_exit = 0;
			if ((maze + w)->up)
				++num_exit;
			if ((maze + w)->right)
				++num_exit;
			if ((maze + w)->down)
				++num_exit;
			if ((maze + w)->left)
				++num_exit;
			fprintf(fp, "#%d\n", startvnum+vnum);
			switch (num_exit)
			{
				case 0 :
					fprintf(fp, "Perdido en el Laberinto~\n");
					fprintf(fp, "Estas perdido en el laberinto de retorcidos pasajes sin tener donde ir.\n~\n");
					break;
				case 1 :
					fprintf(fp, "Sin salida~\n");
					fprintf(fp, "#B#FJAJAJAJAJA#b#f!.  Ahora tienes que volver!\n~\n");
					break;
				case 2 :
					fprintf(fp, "Tunel oscuro~\n");
					fprintf(fp, "Estas en un laberinto de pasajes oscuros, todos parecidos.\n~\n");
					break;
				case 3:
					fprintf(fp, "Pasaje oscuro~\n");
					fprintf(fp, "Estas en un laberinto de pasajes oscuros, todos parecidos.\n~\n");
					break;
				case 4 :
					fprintf(fp, "Cuarto oscuro~\n");
					fprintf(fp, "Estas en un laberinto de pasajes oscuros, todos parecidos.\n~\n");
					break;
			}
			fprintf(fp, "0 %d 0\n", ROOM_NO_RECALL|ROOM_NOWHERE|ROOM_INDOORS);
			if ((maze + w)->up)
				fprintf(fp, "D0\n~\n~\n0 0 %d\n", startvnum + vnum - width );
			if ((maze + w)->right)
				fprintf(fp, "D1\n~\n~\n0 0 %d\n", startvnum + vnum + 1 );
			if ((maze + w)->down)
				fprintf(fp, "D2\n~\n~\n0 0 %d\n", startvnum + vnum + width );
			if ((maze + w)->left)
				fprintf(fp, "D3\n~\n~\n0 0 %d\n", startvnum + vnum - 1 );
			fprintf(fp, "S\n");
			++vnum;
        }
        maze += width;
    }
	fprintf(fp, "#0\n\n");
	fprintf(fp, "#RESETS\n");

	fprintf(fp, "S\n\n");
}/* Maze2Area */

void crear_laberinto (FILE *fp, int startvnum, int width, int height)
{
	maze_t maze;
	char buf[MIL];

	srand ((int) time ((time_t *) NULL));

	if (width <= 0 || height <= 0)
	{
		bug( "Crear_laberinto : Ancho o largo ilegal!", 0 );
	        exit (EXIT_FAILURE);
	}

	maze = (maze_t) mud_calloc (width * height, sizeof (cell_t));
	if (maze == NULL)
	{
		bug( "Crear_laberinto : no se pudo asignar memoria!", 0 );
        	exit (EXIT_FAILURE);
	}

	fprintf(fp, "#AREADATA\n");
	fprintf(fp, "Name Laberinto~\n");
	fprintf(fp, "Builders None~\n");
	fprintf(fp, "Security 9\n");
	fprintf(fp, "VNUMs %d %d\n", startvnum, startvnum+(width*height) );
	fprintf(fp, "Prototipo 0\n");
	fprintf(fp, "Low 5\n");
	fprintf(fp, "High 60\n");
	fprintf(fp, "Credits { 50+ } Birdie  Laberinto~\n");
	fprintf(fp, "Recalc 1\n");
	fprintf(fp, "End\n\n");

	CreateMaze (maze, width, height);

	fprintf(fp, "#OBJECTS\n");
	fprintf(fp, "#%d\n", startvnum );
	fprintf(fp, "mapa laberinto~\n");
	fprintf(fp, "mapa del laberinto~\n");
	fprintf(fp, "Un mapa del laberinto.~\n");
	fprintf(fp, "paper~\n");
	fprintf(fp, "map 0 A\n");
	fprintf(fp, "0 0 0 0 0\n");
	fprintf(fp, "0 1500 0 P\n");
	fprintf(fp, "E\n");
	fprintf(fp, "mapa~\n");
	PrintMaze (fp, maze, width, height);
	fprintf(fp, "~\n");

	SolveMaze (maze, width, height);

	fprintf(fp, "E\n");
	fprintf(fp, "solucion~\n");
	PrintMaze (fp, maze, width, height);
	fprintf(fp, "~\n");
	fprintf(fp, "#0\n\n");

	/* Make the mob 	*/

	fprintf(fp, "#MOBILES\n");
	fprintf(fp, "#%d\n", startvnum );
	fprintf(fp, "guerrero laberinto~\n");
	fprintf(fp, "~\n");
	fprintf(fp, "Un guerrero da vueltas por el lugar, con los ojos desorbitados.\n~\n");
	fprintf(fp, "Parece llevar anos tratando de salir de aqui.\n~\n");

	fprintf(fp, "human~\n");
	fprintf(fp, "%s 40 0 1000 0\n", fwrite_flag( ACT_IS_NPC|ACT_SENTINEL|ACT_STAY_AREA|ACT_SCAVENGER|ACT_AGGRESSIVE, buf ) );
	fprintf(fp, "50 40 4d175+1400 3d3+33 5d5+10 bite\n");
	fprintf(fp, "0 0 0 0\n");
	fprintf(fp, "0 0 0 0\n");
	fprintf(fp, "stand stand male 0\n");
	fprintf(fp, "0 0 large carne\n");
	fprintf(fp, "#0\n\n");

	/* now generate the rooms */
	Maze2Area (fp, maze, width, height, startvnum);

	fprintf(fp, "#SPECIALS\n" );
	fprintf(fp, "M %d spec_rat\n", startvnum );
	fprintf(fp, "S\n\n" );

	/* And the trailer		*/
	fprintf(fp, "#$\n");

	free (maze);
/*	exit (EXIT_SUCCESS); */

	return;
}/* main */