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.