[alt.sources.amiga] Maze -- Maze generator program -- Guenther Werner

amiga-sources@sugar.uu.net (alt.sources.amiga) (07/31/88)

Archive: uunet!~uucp/amiga-sources/maze.shar.Z

    "I send you a small routiene to create mazes and two long demos for this
    code. I doubt it is usefull, but I hope the demos are funny enougth to
    keep this posting interesting. Everything is ZOO'd and uuencoded to keep
    the files together.

    "Werner G35@DHDURZ1.BITNET"

Well, it looks useful enough to publish. I've taken the liberty of removing
the binaries, manxifying the sources, and adding a Makefile. I presume
you use Lattice, since Manx didn't like this sucker.

						-- Peter da Silva.

: This archive contains the following files...
: 'README'
: 'SpeedDemo.c'
: 'Makefile'
: 'maze.h'
: '3ddemo.c'
: To extract them, run the following through /bin/sh
echo x - README
sed 's/^X//' > README << '//END'
X[ Editors note -- I made some changes to make Aztec accept this program.
X  The changes I made are marked with "PDS(n)":
X
X  	PDS(1)    Expression was too complex.
X	PDS(2,3)  Aztec requires a statement after a label. This is legit
X		according to K&R, by the way.
X
X  Peter da Silva, 31 July 1988 ]
X
XThis is a small, everything but useful routine to create mazes. The
Xresulting maze is unique, i.e. there is only one way from one point of the
Xmaze to another. The logic is quite simple: first a border of passages is
Xdrawn around the maze (just to prevent your 8 meg. memory expansion being
Xmapped out), then a random starting point is selected. The maze is divided
Xinto 2*2 squares. From the current position we pick up a  random direction
Xand draw a line (well, 2 points actually) to the next 2*2 square, if it is
Xfree (i.e. if there is no passage, only walls). If it is not, we check the
Xremaining directions. If everything fails ( we got into a dead end), we
Xmove one step back and check if we can continue from there. If we reach our
Xstarting point while moving back, the maze is finished.
X
XSyntax:
X maze( width, height, area)
X
X short width,height
X char *area
X
X width  = width  of your maze.
X height = height of your maze
X *area  = pointer to the buffer where the maze should be generated.
X          The buffer should be clear,i.e zeroed.
X
XNormally the program assumes your buffer being a matrix of [width][height]
Xchars. In return you will get your buffer filled with 1's (passage) and 0's
X(walls).
XIf you define 'bitmap' (#define bitmap at the start of your program) the
Xresult will be an area of bits. Bit clear means passage,bit set means wall.
X
XTo make life easy, there are two macros defined:
X
XOne to check if a x,y position is passage or wall:
XMAZETEST (xpos,ypos,mazewidth,pointer to buffer)
Xresult: 0 if passage, anything else if wall.
X
XAnother to set a position to passage:
XMAZESET (xpos,ypos,mazewidth,pointer to buffer)
X
XIncluded are two demo programs: SpeedDemo - Draws a maze into a
Xlow resolution screen, press any key to get a new one, and 3Ddemo, a simple
X3D maze featuring: No double buffering, no smooth animation and no sound.
XUse the arrow keys on the num-pad to move.
X
XIf you use this code in your own program, I would be pleased if you send me
Xa copy.
X
XHappy wandering (or wondering)
XWerner Gunther
XG35@DHDURZ2.BITNET
X
XP.S. This code is freely distibutable, deleteable etc.,etc...
X
//END
echo x - SpeedDemo.c
sed 's/^X//' > SpeedDemo.c << '//END'
X#include <libraries/dosextens.h>
X#include <intuition/intuition.h>
X#include <intuition/screens.h>
X
X#define BITMAP
X
X#include "maze.h"
X
X/* Just change these defines for a new resolution */
X#define SCREENWIDTH  320
X#define SCREENHEIGHT 212
X#define VIEWMODE     NULL
X
Xstruct NewScreen ns=
X{
X 0,0,SCREENWIDTH,SCREENHEIGHT,1,
X 1,0,
X VIEWMODE,
X CUSTOMSCREEN|SHOWTITLE,
X NULL,
X NULL,
X NULL,
X NULL
X};
Xstruct NewWindow nw=
X{
X 0,0,SCREENWIDTH,SCREENHEIGHT,
X 1,0,
X VANILLAKEY|CLOSEWINDOW|GADGETUP,
X BORDERLESS|NOCAREREFRESH|WINDOWCLOSE|ACTIVATE,
X NULL, NULL,
X "Maze Demo",/*NULL,*/
X NULL, NULL, NULL,NULL,NULL,NULL,
X CUSTOMSCREEN
X};
X
Xstruct Library *GfxBase = NULL,*IntuitionBase = NULL;
Xstruct Screen *screen = NULL;
Xstruct Window *window = NULL;
Xstruct BitMap *bm;
Xstruct IntuiMessage *msg;
XULONG  class;
XBOOL   WorkBench=NULL;
Xvoid newmaze(),leave(),main();
X
Xvoid main(argc,argv)
Xshort argc;
Xchar argv[];
X{
X if (!argc) WorkBench=TRUE;
X if (!(IntuitionBase = (struct Library*) OpenLibrary("intuition.library",0L)))
X    leave("No Intuition Library");
X if (!(GfxBase = (struct Library*) OpenLibrary("graphics.library",0L)))
X    leave("No Graphics Library");
X
X if (!(screen = (struct Screen*) OpenScreen(&ns)))
X    leave ("Can't open Screen");
X
X nw.Screen=screen;
X if (!(window = (struct Window*) OpenWindow(&nw)))
X    leave("Can't open Window");
X
X SetRGB4(&screen->ViewPort,0,0,0,0);
X SetRGB4(&screen->ViewPort,1,12,12,12);
X bm = screen->ViewPort.RasInfo->BitMap;
X
X newmaze();
X
X for(;;)
X {
X  WaitPort(window->UserPort);
X  if(msg=(struct IntuiMessage*)GetMsg(window->UserPort))
X  {
X   class=msg->Class;
X   ReplyMsg(msg);
X   switch(class)
X   {
X    case CLOSEWINDOW:
X     leave("");
X    case VANILLAKEY:
X     newmaze();
X   }
X  }
X }
X}
Xvoid leave(error)
Xchar *error;
X{
X BPTR file;
X
X if(window)        CloseWindow(window);
X if(screen)        CloseScreen(screen);
X if(IntuitionBase) CloseLibrary(IntuitionBase);
X if(GfxBase)       CloseLibrary(GfxBase);
X
X if (*error && WorkBench &&
X     (file=Open("con:20/70/400/60/Maze Demo",MODE_OLDFILE)))
X {
X  Write(file,error,strlen(error));
X  Delay(200L);
X  Close(file);
X }
X else if (*error) printf("%s\n",error);
X exit(0);
X}
X
Xvoid newmaze()
X{
X BltClear (bm->Planes[0]+12*bm->BytesPerRow,  /*skip gadgets & title */
X           (bm->Rows-12)*bm->BytesPerRow,NULL);
X
X /* Get parameters from our BitMap,so we don't have to change them on
X    different resolutions */
X if(!(maze(bm->BytesPerRow*8,bm->Rows-12,
X           bm->Planes[0]+12*bm->BytesPerRow)))
X   leave("Couldn't allocate Maze-Stack");
X}
X
//END
echo x - Makefile
sed 's/^X//' > Makefile << '//END'
X.SUFFIXES: .c .o .h .x
X
X.c.o:
X	-delete $*.o
X	cc +P -B -DAMIGA $*.c
X
Xall: 3Ddemo SpeedDemo
X
X3ddemo: 3ddemo.o
X	-delete 3ddemo
X	ln -o t:3ddemo 3ddemo.o -lcl32
X	copy t:3ddemo 3ddemo
X	-delete t:3ddemo
X
Xspeeddemo: speeddemo.o
X	-delete speeddemo
X	ln -o t:speeddemo speeddemo.o -lcl32
X	copy t:speeddemo speeddemo
X	-delete t:speeddemo
//END
echo x - maze.h
sed 's/^X//' > maze.h << '//END'
X#define StackX (short) *(stack+(stackptr<<1))
X#define StackY (short) *(stack+(stackptr<<1)+1)
X
X/* MAZETEST (xpos,ypos,mazewidth,pointer to buffer) */
X#ifdef BITMAP
X#define MAZETEST(a,b,c,d) (*((d)+((short)(b)*(short)((c)>>3))+((a)>>3)) & 0x80 >> ((a) & 7))
X#else
X#define MAZETEST(a,b,c,d) (*(d)+(a)+((b)*(c))))
X#endif
X
X/* MAZESET (xpos,ypos,mazewidth,pointer to buffer */
X#ifdef BITMAP
X#define MAZESET(a,b,c,d) *((d)+((short)(b)*(short)((c)>>3))+((a)>>3))|= 0x80 >> ((a) & 7)
X#else
X#define MAZESET(a,b,c,d) *((d)+(a)+((b)*(c)))=1
X#endif
X
Xlong seed;                     /* FastRand() stuff */
Xshort testpoint[4][2]=
X {{-1,0},{1,0},{0,1},{0,-1}};  /* = left,right,down,up */
Xshort stackptr,direction,newpos(),maze();
Xlong *vposr = (long*)0xdff004; /* Beam position */
X
Xshort maze(width,height,area)
Xregister short width;
Xregister char  *area;
Xshort height;
X{
X register short x,y;
X register short *stack;
X short i,j;
X
X seed=*vposr;           /* new Seed for FastRand() */
X x=2;                   /* starting position */
X y=(FastRand(seed) % (height-4) + 2) & 0xfffe;
X
X  /* we need a 'stack' to store those positions, from where we can */
X  /* continue if we get into a dead end */
X if(!(stack=(short*) AllocMem(width*height,NULL))) return(NULL);
X
X stackptr=1;
X StackX=x;StackY=y;
X
X j= width & 1 ? width-1:width-2;
X for(i=0;i<height;i++)          /* surround the 'maze' with 'passages' */
X {
X   MAZESET(0,i,width,area);
X   MAZESET(j,i,width,area);
X }
X j= height & 1 ? height-1:height-2;
X for(i=0;i<width;i++)
X {
X   MAZESET(i,0,width,area);
X   MAZESET(i,j,width,area);
X }
X
X MAZESET(x,y,width,area);         /* set the first position to 'passage' */
X
X while(stackptr)                  /* do we have a untested position left ? */
X {
X  direction=seed=FastRand(seed);  /* pick up a random direction */
X
X  for (i=0;i<4;i++,direction++)   /* test all 4 directions */
X  {
X   direction &= 3;                /* = %4 */
X   /* test if the position we are moving to is already a 'passage' */
X   if(! MAZETEST(x+2*testpoint[direction][0],2*testpoint[direction][1]+y,width,area))
X   {
X    /* if not move to the new position */
X    MAZESET(x+testpoint[direction][0],testpoint[direction][1]+y,width,area);
X    x+=2*testpoint[direction][0];
X    y+=2*testpoint[direction][1];
X    MAZESET(x,y,width,area);
X    StackX=x;                     /* stack current position because */
X    StackY=y;                     /* there may be more than one direction */
X    stackptr++;                   /* we can move to */
X    goto endtest;                 /* GOTO ?!? */
X   }
X  }
X  stackptr--;                   /* dead-end, delete this point from stack */
X  x=StackX;                     /* test last position again */
X  y=StackY;
X  endtest:
X  	; /* Inserted ; to make Aztec happy -- PDS(3) -- 31-jul-88 */
X }
X FreeMem(stack,width*height);
X return(1);
X}
X
X
//END
echo x - 3ddemo.c
sed 's/^X//' > 3ddemo.c << '//END'
X#include <libraries/dosextens.h>
X#include <intuition/intuition.h>
X#include <exec/memory.h>
X#include <graphics/gfxmacros.h>
X
X#define BITMAP
X
X#include "maze.h"         /* This is our maze generator */
X
X#define MENUITEMS 6
X
Xstruct IntuiText item[MENUITEMS*2]=
X{ 6,0,JAM2,0,0,NULL,NULL,NULL };
X
Xstruct IntuiText abouttxt5=   /* Yes, this game needs lots of credits */
X{ 7,0,JAM2,32,40,NULL,"keys to move",NULL};
Xstruct IntuiText abouttxt4=
X{ 7,0,JAM2,12,30,NULL,"Use keypad cursor",&abouttxt5};
Xstruct IntuiText abouttxt3=
X{ 4,0,JAM2,0,20,NULL,"Freely distributable",&abouttxt4};
Xstruct IntuiText abouttxt2=
X{ 6,0,JAM2,24,10,NULL,"Werner Gunther",&abouttxt3};
Xstruct IntuiText abouttxt1=
X{ 6,0,JAM2,40,0,NULL,"Written by",&abouttxt2};
X
Xstruct MenuItem mi[MENUITEMS] =          /* main menu structures */
X{
X NULL,0,0,70,11,
X ITEMTEXT|ITEMENABLED|HIGHCOMP,
X NULL,NULL,NULL,NULL,NULL,NULL
X};
Xstruct MenuItem sizemenu[MENUITEMS] =    /* sub menu for sizes */
X{
X NULL,60,0,90,11,
X ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT,
X NULL,NULL,NULL,NULL,NULL,NULL
X};
Xstruct MenuItem about =                  /* about, credits & help */
X{
X NULL,60,0,160,50,
X ITEMTEXT|ITEMENABLED,
X NULL,(APTR)&abouttxt1,NULL,NULL,NULL,NULL
X};
X
Xstruct Menu menu=
X{
X NULL,0,0,70,11,
X MENUENABLED,
X "Options",
X mi
X};
X
Xstruct NewScreen ns=                     /* screen low-rez, 8 colors */
X{
X 0,0,320,200,3,
X 1,0,
X NULL,
X CUSTOMSCREEN,
X NULL,NULL,NULL,NULL
X};
X
Xstruct NewWindow nw=                     /* window for menus & gadgets */
X{
X 0,1,286,199,
X 1,0,
X CLOSEWINDOW|GADGETUP|MENUPICK|MENUVERIFY|VANILLAKEY,
X BORDERLESS|NOCAREREFRESH|WINDOWCLOSE|ACTIVATE,
X NULL, NULL,
X "Maze 3D Demo",
X NULL, NULL, NULL,NULL,NULL,NULL,
X CUSTOMSCREEN
X};
X
Xstruct Image mazeimage={0,0,0,0,1,0,4,4,0}; /* Image to display the maze */
X
Xchar mtxt[MENUITEMS][9]=                    /* menu text */
X{
X "Map","New Maze","Size","Demo","Quit","About"
X};
Xchar sizetxt[MENUITEMS][11]=                /* text for size menu */
X{
X "Trivial","Simple","Normal","Advanced","Difficult","Impossible"
X};
X
Xstruct GfxBase *GfxBase = NULL;
Xstruct IntuitionBase *IntuitionBase = NULL;
Xstruct Screen *screen = NULL;
Xstruct Window *window = NULL;
Xstruct BitMap *bm;
Xstruct IntuiMessage *msg;
Xstruct AreaInfo  areainfo;
Xstruct TmpRas tmpras;
Xstruct RastPort *rp;
X
XULONG  class,code;
XBOOL   WorkBench=FALSE,demomode=FALSE,forward();
Xvoid   right(),left(),demo(),newmaze(),leave(),main(),show3d(),showmaze();
Xvoid   statusline();
Xshort  i,j,xsize,ysize,mazesize=2,x,y,wayout,moves;
Xchar   *mymaze=NULL,areapts[7*5],*raster=NULL,buffer[20];
Xshort  dirincs[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
Xchar   heading[][7]={"North"," East ","South"," West "};
X
Xvoid main(argc,argv)
Xshort argc;
Xchar argv[];
X{
X if (!argc) WorkBench=TRUE;      /* open stuff */
X if (!(IntuitionBase = (struct IntuitonBase*)
X  OpenLibrary("intuition.library",0L)))
X    leave("No Intuition Library");
X if (!(GfxBase = (struct GfxBase*) OpenLibrary("graphics.library",0L)))
X    leave("No Graphics Library");
X
X for(i=0;i<MENUITEMS;i++)        /* set menu-strip */
X {                               /* could have be done on declaration */
X  sizemenu[i]=sizemenu[0];
X  sizemenu[i].NextItem=&sizemenu[i+1];
X  sizemenu[i].ItemFill=(APTR)&item[i+MENUITEMS];
X  sizemenu[i].TopEdge=i*11;
X  item[i]=item[0];
X  item[i+MENUITEMS]=item[0];
X  item[i+MENUITEMS].IText=sizetxt[i];
X  item[i+MENUITEMS].LeftEdge=11;
X  item[i].IText=mtxt[i];
X  mi[i]=mi[0];
X  mi[i].NextItem=&mi[i+1];
X  mi[i].ItemFill=(APTR)&item[i];
X  mi[i].TopEdge=i*11;
X }
X mi[MENUITEMS-1].NextItem=NULL;
X sizemenu[MENUITEMS-1].NextItem=NULL;
X mi[2].SubItem=&sizemenu[0];
X mi[5].SubItem=&about;
X sizemenu[mazesize].Flags|=CHECKED;
X
X if (!(screen = (struct Screen*) OpenScreen(&ns))) /* open screen & window */
X    leave ("Can't open Screen");
X bm = screen->ViewPort.RasInfo->BitMap;
X rp = &screen->RastPort;
X
X nw.Screen=screen;
X if (!(window = (struct Window*) OpenWindow(&nw))) leave("Can't open Window");
X SetMenuStrip(window,&menu);
X
X SetRGB4(&screen->ViewPort,0,0,0,0); /* set colors, 1-7 is a grey scale */
X for(i=1;i<7;i++) SetRGB4(&screen->ViewPort,i,2+2*i,2+2*i,2+2*i);
X SetRGB4(&screen->ViewPort,7,8,8,15);
X
X /* stuff needed by FloodFill, AreaFill */
X if(!(raster=(char *)AllocRaster(192,188))) leave("Can't allocate TmpRaster");
X InitTmpRas(&tmpras,raster,4512);
X rp->TmpRas=&tmpras;
X InitArea(&areainfo,areapts,7);
X rp->AreaInfo=&areainfo;
X BNDRYOFF(rp);
X
X for(i=0;i<3;i++) /* Draw status-display box */
X {
X  SetAPen(rp,i+3);
X  AreaMove(rp,190+5*i,12+5*i);
X  AreaDraw(rp,319-5*i,12+5*i);
X  AreaDraw(rp,319-5*i,125-5*i);
X  AreaDraw(rp,319-5*i-5,125-5*i-5);
X  AreaDraw(rp,319-5*i-5,12+i*5+5);
X  AreaDraw(rp,190+5*i+5,12+i*5+5);
X  AreaEnd(rp);
X  SetAPen(rp,i+2);
X  AreaMove(rp,190+5*i,12+5*i);
X  AreaDraw(rp,190+5*i,125-5*i);
X  AreaDraw(rp,319-5*i,125-5*i);
X  AreaDraw(rp,319-5*i-5,125-5*i-5);
X  AreaDraw(rp,319-5*i-5,12+i*5+5);
X  AreaDraw(rp,190+5*i+5,12+i*5+5);
X  AreaEnd(rp);
X }
X
X newmaze();
X
X for(;;)           /* main loop, wait for a message if not in demo-mode */
X {
X  if (!demomode) WaitPort(window->UserPort);
X  else demo();
X  if(msg=(struct IntuiMessage*)GetMsg(window->UserPort))
X  {
X   demomode=FALSE;
X   class=msg->Class;
X   code=msg->Code;
X   ReplyMsg(msg);
X   switch(class)
X   {
X    case CLOSEWINDOW:
X     leave("");
X    case VANILLAKEY:
X     if(y!=wayout || x!=xsize-3)
X      switch(code) /* we check numbers 6/4/8, these are arrows on the */
X      {            /* num pad keys, so we don't need RawKeyConvert */
X       case '8':
X        forward();
X        break;
X       case '4':
X        left();
X        break;
X       case '6':
X        right();
X        break;
X      }
X     break;
X    case MENUPICK:
X      switch(ITEMNUM(code))
X      {
X       case 0:         /* map */
X        showmaze();
X        moves+=30;
X        break;         /* New Maze */
X       case 1:
X        newmaze();
X        break;
X       case 2:
X        if(SUBNUM(code)==mazesize) break;
X        sizemenu[mazesize].Flags&=~CHECKED;
X        mazesize=SUBNUM(code);
X        sizemenu[mazesize].Flags|=CHECKED;
X        newmaze();
X        break;
X       case 3:         /* Demo  */
X        demomode=TRUE;
X        break;
X       case 4:         /* Quit  */
X        leave("");
X       case 5:         /* About */
X	   	; /* Inserted ; to make Aztec happy -- PDS(1) -- 31-jul-88 */
X      }
X   }
X  }
X }
X}
X
Xvoid leave(error)
Xchar *error;
X{
X BPTR file;
X                   /* Free Resouces & Exit */
X if(window)        CloseWindow(window);
X if(screen)        CloseScreen(screen);
X if(IntuitionBase) CloseLibrary(IntuitionBase);
X if(GfxBase)       CloseLibrary(GfxBase);
X if (mymaze)       FreeMem(mymaze,(xsize>>3)*ysize);
X if (raster)       FreeRaster(raster,192,188);
X
X if (*error && WorkBench &&
X     (file=Open("con:20/70/400/60/Maze 3D Demo",MODE_OLDFILE)))
X {
X  Write(file,error,strlen(error));
X  Delay(200L);
X  Close(file);
X }
X else if (*error) printf("%s\n",error);
X exit(0);
X}
X
Xvoid newmaze()
X{
X if (mymaze) FreeMem(mymaze,(xsize>>3)*ysize); /* Free old maze */
X xsize=32+mazesize*16;                         /* get new dimension */
X ysize=12+mazesize*12;
X if (!(mymaze=(char*) AllocMem((xsize>>3)*ysize,MEMF_CHIP|MEMF_CLEAR)))
X     leave("Out of chip memory");              /* allocate new one */
X SetAPen(rp,6);                                /* clear status display */
X RectFill(rp,205,27,304,110);
X SetAPen(rp,1);
X statusline(10,"Moves:");
X statusline(30,"Looking");
X statusline(60,"Size:");
X sprintf(buffer,"%ld*%ld",xsize,ysize);
X statusline(70,buffer);
X
X maze(xsize,ysize,mymaze);                     /* genarate a new maze */
X seed = FastRand(seed);
X y= ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe;  /* random start point */
X x= 2;
X seed = FastRand(seed);
X wayout = ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe;  /* random exit */
X MAZESET(xsize-3,wayout,xsize,mymaze);               /* open exit */
X direction=1;                                    /* heading right (east) */
X statusline(40,heading[direction]);
X moves=0;
X show3d();
X showmaze();
X}
X
Xvoid statusline(y,text)
Xshort y;
Xchar *text;
X{                                  /* Write text, centered, into */
X Move(rp,255-strlen(text)*4,27+y); /* status-display */
X SetAPen(rp,1);
X SetBPen(rp,6);
X Text(rp,text,strlen(text));
X}
X
Xvoid showmaze()                   /* show the maze */
X{
X mazeimage.Width=xsize;           /* we define a Image-structure on our */
X mazeimage.Height=ysize;          /* bitmapped maze */
X mazeimage.ImageData=(short*)mymaze;
X DrawImage(rp,&mazeimage,255-(xsize/2),127);
X                                               /* wait for a message */
X while(! window->UserPort->mp_MsgList.lh_Head->ln_Succ)
X {
X  SetAPen(rp,++i&7);                        /* exit and current position */
X  WritePixel(rp,255-(xsize/2)+x,127+y);     /* are blinking */
X  WritePixel(rp,253-(xsize/2)+xsize,127+wayout);
X  Delay(6L);
X }
X SetAPen(rp,0);
X RectFill(rp,191,127,319,199);
X}
X
Xvoid show3d()
X{
X register short k,inner,outer,wall;
X
X WaitBOVP(rp);          /* doesn't have too much effect in this case */
X for(i=1;i<7;i++)       /* get the wall in front */
X  if(!(MAZETEST(x+i*dirincs[direction][0],y+i*dirincs[direction][1],
X              xsize,mymaze))) break;
X wall=6-i;
X
X for(k=-1;k < 2;k+=2)   /* draw a 'sky' and a 'floor' */
X {
X  SetAPen(rp,(k+8) % 8);
X  AreaMove(rp,1,106+k*94);
X  AreaDraw(rp,187,106+k*94);
X  AreaDraw(rp,94+(2<<wall),106+k*(2<<wall)+k);
X  AreaDraw(rp,94-(2<<wall),106+k*(2<<wall)+k);
X  AreaEnd(rp);
X }
X
X if(i!=7)
X {
X  if(y==wayout && (x+i*dirincs[direction][0])==xsize-1)
X  {                        /* are we looking at the exit ? */
X   SetAPen(rp,7);
X   RectFill(rp,94-(2<<(++wall)),106-(2<<wall),94+(2<<wall),106);
X   SetAPen(rp,1);
X   RectFill(rp,94-(2<<wall),107,94+(2<<wall),106+(2<<wall));
X  }
X  else
X  {
X   SetAPen(rp,5);   /* draw a light grey wall */
X   RectFill(rp,94-(2<<wall),106-(2<<wall),94+(2<<wall),106+(2<<wall));
X  }
X }
X else        /* the front wall is too far away */
X {
X  SetAPen(rp,4);
X  AreaMove(rp,92,104);
X  AreaDraw(rp,92,108);
X  AreaDraw(rp,96,104);
X  AreaDraw(rp,96,108);
X  AreaEnd(rp);
X }
X
X for(k=-1;k < 2;k+=2)      /* draw walls on the left and on the right */
X  for(i=5-wall;i>-1;i--)   /* starting from the front wall ending at */
X  {                        /* our current position */
X   int xx, yy;		/* Patch to make Aztec happy -- PDS(1) -- 31-jul-88 */
X   inner=(2<<(5-i));       /* inner edges of a wall */
X   outer=(inner<<1);       /* outer edges */
X   if(outer > 94) outer=94;  /* 'Clip' if too large */
X                           /* check if a wall or a passage */
X   xx=x+dirincs[(direction+k)&3][0]+i*dirincs[direction][0]; /* PDS(1) */
X   yy=y+dirincs[(direction+k)&3][1]+i*dirincs[direction][1]; /* PDS(1) */
X   if(!(MAZETEST(xx,yy, xsize,mymaze)))
X   {                             /* it's a wall */
X    SetAPen(rp,4);
X    AreaMove(rp,94+k*inner,106-inner);
X    AreaDraw(rp,94+k*inner,106+inner);
X    AreaDraw(rp,94+k*outer,106+outer);
X    AreaDraw(rp,94+k*outer,106-outer);
X    AreaEnd(rp);
X   }
X   else                         /* it's a passage */
X   {
X    SetAPen(rp,7);              /* clear upper and lower corners */
X    AreaMove(rp,94+k*outer,106-outer);
X    AreaDraw(rp,94+k*inner,106-inner);
X    AreaDraw(rp,94+k*outer,106-inner);
X    AreaEnd(rp);
X    SetAPen(rp,1);
X    AreaMove(rp,94+k*outer,106+outer);
X    AreaDraw(rp,94+k*inner,106+inner);
X    AreaDraw(rp,94+k*outer,106+inner);
X    AreaEnd(rp);
X    SetAPen(rp,5);              /* light grey wall */
X    if (k==1) RectFill(rp,94+inner,106-inner,94+outer,106+inner);
X    else      RectFill(rp,94-outer,106-inner,94-inner,106+inner);
X   }
X  }
X}
X
Xvoid demo()    /* demo mode: follow the left-hand wall until we get to */
X{              /* the exit */
X long delay;
X               /* be fast if the exit is far away, slow if it gets nearer */
X delay=19-18*(xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)))/
X          ((wayout<ysize/2? ysize-wayout:wayout)+xsize-3);
X
X if(y==wayout && x==xsize-3) /* did we reach the exit ?*/
X {
X  demomode=FALSE;            /* stop if we did */
X  return;
X }                           /* is it possible to turn left ? */
X if(MAZETEST(x+dirincs[(direction-1)&3][0],y+dirincs[(direction-1)&3][1],
X             xsize,mymaze))
X {
X  left();                    /* yes, turn left */
X  Delay(delay);
X  forward();                 /* and one step forward */
X }
X else if(!forward()) right(); /* if not try to move forward, if everything */
X                              /* fails, turn right */
X Delay(delay);
X}
X
XBOOL forward()                /* move one step forward if possible */
X{
X if(!(MAZETEST(x+dirincs[direction][0],
X             y+dirincs[direction][1],xsize,mymaze))) return(FALSE);
X
X x+=dirincs[direction][0];
X y+=dirincs[direction][1];
X moves++;
X sprintf(buffer," %ld/%ld ",
X         moves,xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)));
X statusline(20,buffer);
X show3d();
X
X if(y==wayout && x==xsize-3)  /* has the exit been reached ?*/
X {
X  SetAPen(rp,1);              /* yes, write some stupid text */
X  SetBPen(rp,7);
X  Move(rp,58,104);
X  Text(rp,"Solved in",9);
X  SetAPen(rp,6);
X  SetBPen(rp,1);
X  sprintf(buffer,"%ld moves.",moves);
X  Move(rp,94-strlen(buffer)*4,116);
X  Text(rp,buffer,strlen(buffer));
X }
X return(TRUE);
X}
X
Xvoid left()                 /* turn left */
X{
X direction=(--direction) & 3;
X show3d();
X statusline(40,heading[direction]);
X}
X
Xvoid right()                /* turn right */
X{
X direction=(++direction) & 3;
X show3d();
X statusline(40,heading[direction]);
X}
//END
: end of archive.
exit 0