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