ftp.nice.ch/pub/next/unix/hack/hackkit.2.N.bs.tar.gz#/freebies/source/maze.c

This is maze.c in view mode; [Download] [Up]

/*	maze.c

	Future maze program.  Right now it just generates mazes and
	prints them on VT100 screens in graphics mode.

*/

#include <ansi.h>
#include <sgtty.h>

#define USED 1
#define BOTTOM 2
#define RIGHT 4
#define repeat for (;;)
#define cputs(s) fputs(s,stdout)
#define		movmem(a,b,c)		memmove(b,a,c)
#define		fill(a,b,c)		memset(a,c,b)

int farx,fary,fardist;

char *mazep;
int w,h;
#define maze(x,y) mazep[(w+1)*(y)+(x)]

main(int argc,char **argv) {
    int x,y,n,d,m,straight,sinit;
    struct winsize ws;

    sinit = 3;
    if (argc>1) {
	sinit = atoi(argv[1]);
	if (!sinit) {
	    puts("maze <x>\n"
		 "<x> = \"straightness\" parameter (optional, default=3)");
	    exit(1);
	    }
	}
    ioctl(0,TIOCGWINSZ,&ws);
    if (!ws.ws_row) ws.ws_row = 24;
    if (!ws.ws_col) ws.ws_col = 80;
    w = ws.ws_col/2-1;
    h = ws.ws_row-2;

    randomize();
    mazep = (void *)sbrk((w+1)*(h+1));
    if (!mazep) {puts("Out of memory!"); exit(1);}
    fill(mazep,(w+1)*(h+1),BOTTOM+RIGHT);
    for (x=1; x<=w; x++) maze(x,0) = BOTTOM;
    for (y=1; y<=h; y++) maze(0,y) = RIGHT;
    maze(0,0) = 0;
    x = y = 1;
    straight = d = 0;
/*  cputs("\033[H\033[2J"); drawmaze(); */
    for (n=w*h; maze(x,y) |= USED,--n>0;) {
/*	cputs("\033[H"); drawmaze(mazep,w,h); */
    NP:	if (--straight<=0) {if (random(2)) d++; else d--; straight = sinit;}
	for (m=4; m>0; m--) {
	    switch(d&3) {
	    case 0: /* left */
		if (x>1 && !(maze(x-1,y)&USED))
		    {maze(--x,y) &= ~RIGHT; goto CONTINUE1;}
		break;
	    case 1: /* up */
		if (y>1 && !(maze(x,y-1)&USED))
		    {maze(x,--y) &= ~BOTTOM; goto CONTINUE1;}
		break;
	    case 2: /* right */
		if (x<w && !(maze(x+1,y)&USED))
		    {maze(x++,y) &= ~RIGHT; goto CONTINUE1;}
		break;
	    case 3: /* down */
		if (y<h && !(maze(x,y+1)&USED))
		    {maze(x,y++) &= ~BOTTOM; goto CONTINUE1;}
		break;
		}
	    d++; /* straight = sinit; */
	    }
	x = random(w)+1;	/* seed a new path */
	y = random(h)+1;
	repeat {
	    if (maze(x,y)&USED &&
		(x>1 && !(maze(x-1,y)&USED) ||
		 y>1 && !(maze(x,y-1)&USED) ||
		 x<w && !(maze(x+1,y)&USED) ||
		 y<h && !(maze(x,y+1)&USED))) break;
	    x++; if (x>w) {x=1; y++; if (y>h) y=1;}
	    }
	straight = 0;
	goto NP;
    CONTINUE1:;
	}
    findfar(1,1);
    x = farx; y = fary;
    findfar(x,y);
    if (y<=1) maze(x,0) &= ~BOTTOM;
    else if (x<=1) maze(0,y) &= ~RIGHT;
    else if (x>=w) maze(w,y) &= ~RIGHT;
    else maze(x,h) &= ~BOTTOM;
    x = farx; y = fary;
    if (y<=1) maze(x,0) &= ~BOTTOM;
    else if (x<=1) maze(0,y) &= ~RIGHT;
    else if (x>=w) maze(w,y) &= ~RIGHT;
    else maze(x,h) &= ~BOTTOM;
    drawmaze();
    }

drawmaze() {
    int x,y,n;
    static char table[] = " qjjqqmvkkxulwtn";
    cputs("\033(0");
    for (y=0; y<=h; y++) {
	for (x=0; x<=w; x++) {
	    n = maze(x,y);
	    if (x<w && maze(x+1,y)&BOTTOM) n+=BOTTOM*4;
	    if (y<h && maze(x,y+1)&RIGHT) n+=RIGHT*4;
	    if (x) putchar(n&BOTTOM ? table[5] : ' ');
	    putchar(table[n>>1]);
	    }
	putchar('\n');
	}
    cputs("\033(B");
    }

/* recursive and stack-intensive distance finder: */
ifindfar(x,y,d,r) { /* d is "backwards" direction, don't go there */
    int d1;
    for (d1=0; d1<4; d1++) {
	if (d1==d) continue;
	switch(d1&3) {
	case 0:			/* left */
	    if (x>1 && !(maze(x-1,y)&RIGHT)) ifindfar(x-1,y,2,r+1);
	    break;
	case 1:			/* up */
	    if (y>1 && !(maze(x,y-1)&BOTTOM)) ifindfar(x,y-1,3,r+1);
	    break;
	case 2:			/* right */
	    if (x<w && !(maze(x,y)&RIGHT)) ifindfar(x+1,y,0,r+1);
	    break;
	case 3:			/* down */
	    if (y<h && !(maze(x,y)&BOTTOM)) ifindfar(x,y+1,1,r+1);
	    break;
	    }
	}
    if (x<=1 || x>=w || y<=1 || y>=h)	/* on edge? */
	if (r>=fardist) {farx=x; fary=y; fardist=r;}
    }

findfar(x,y) {
    int d;
    fardist = 0;
    ifindfar(x,y,4,0);
    }

static unsigned rdm;
int random(range)				/* Return a number 0..range-1 */
     int range;
{
    long n;
    n = rdm*0xA7A7L;
    rdm = n+(n>>16)+243;
    return(rdm%range);
    }
randomize()
{
#ifdef MSDOS
    doscall(0x2C00);	/* do "get time" call */
    rdm = _DX;		/* use 1/100ths of a second to randomize */
#else
    rdm = time(0);
#endif
    }

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.