home *** CD-ROM | disk | FTP | other *** search
- #include <libraries/dosextens.h>
- #include <intuition/intuition.h>
- #include <exec/memory.h>
- #include <graphics/gfxmacros.h>
-
- #define BITMAP
-
- #include "maze.h" /* This is our maze generator */
-
- #define MENUITEMS 6
-
- struct IntuiText item[MENUITEMS*2]=
- { 6,0,JAM2,0,0,NULL,NULL,NULL };
-
- struct IntuiText abouttxt5= /* Yes, this game needs lots of credits */
- { 7,0,JAM2,32,40,NULL,"keys to move",NULL};
- struct IntuiText abouttxt4=
- { 7,0,JAM2,12,30,NULL,"Use keypad cursor",&abouttxt5};
- struct IntuiText abouttxt3=
- { 4,0,JAM2,0,20,NULL,"Freely distributable",&abouttxt4};
- struct IntuiText abouttxt2=
- { 6,0,JAM2,24,10,NULL,"Werner Gunther",&abouttxt3};
- struct IntuiText abouttxt1=
- { 6,0,JAM2,40,0,NULL,"Written by",&abouttxt2};
-
- struct MenuItem mi[MENUITEMS] = /* main menu structures */
- {
- NULL,0,0,70,11,
- ITEMTEXT|ITEMENABLED|HIGHCOMP,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
- struct MenuItem sizemenu[MENUITEMS] = /* sub menu for sizes */
- {
- NULL,60,0,90,11,
- ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
- struct MenuItem about = /* about, credits & help */
- {
- NULL,60,0,160,50,
- ITEMTEXT|ITEMENABLED,
- NULL,(APTR)&abouttxt1,NULL,NULL,NULL,NULL
- };
-
- struct Menu menu=
- {
- NULL,0,0,70,11,
- MENUENABLED,
- "Options",
- mi
- };
-
- struct NewScreen ns= /* screen low-rez, 8 colors */
- {
- 0,0,320,200,3,
- 1,0,
- NULL,
- CUSTOMSCREEN,
- NULL,NULL,NULL,NULL
- };
-
- struct NewWindow nw= /* window for menus & gadgets */
- {
- 0,1,286,199,
- 1,0,
- CLOSEWINDOW|GADGETUP|MENUPICK|MENUVERIFY|VANILLAKEY,
- BORDERLESS|NOCAREREFRESH|WINDOWCLOSE|ACTIVATE,
- NULL, NULL,
- "Maze 3D Demo",
- NULL, NULL, NULL,NULL,NULL,NULL,
- CUSTOMSCREEN
- };
-
- struct Image mazeimage={0,0,0,0,1,0,4,4,0}; /* Image to display the maze */
-
- char mtxt[MENUITEMS][9]= /* menu text */
- {
- "Map","New Maze","Size","Demo","Quit","About"
- };
- char sizetxt[MENUITEMS][11]= /* text for size menu */
- {
- "Trivial","Simple","Normal","Advanced","Difficult","Impossible"
- };
-
- struct GfxBase *GfxBase = NULL;
- struct IntuitionBase *IntuitionBase = NULL;
- struct Screen *screen = NULL;
- struct Window *window = NULL;
- struct BitMap *bm;
- struct IntuiMessage *msg;
- struct AreaInfo areainfo;
- struct TmpRas tmpras;
- struct RastPort *rp;
-
- ULONG class,code;
- BOOL WorkBench=FALSE,demomode=FALSE,forward();
- void right(),left(),demo(),newmaze(),leave(),main(),show3d(),showmaze();
- void statusline();
- short i,j,xsize,ysize,mazesize=2,x,y,wayout,moves;
- char *mymaze=NULL,areapts[7*5],*raster=NULL,buffer[20];
- short dirincs[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
- char heading[][7]={"North"," East ","South"," West "};
-
- void main(argc,argv)
- short argc;
- char argv[];
- {
- if (!argc) WorkBench=TRUE; /* open stuff */
- if (!(IntuitionBase = (struct IntuitonBase*)
- OpenLibrary("intuition.library",0L)))
- leave("No Intuition Library");
- if (!(GfxBase = (struct GfxBase*) OpenLibrary("graphics.library",0L)))
- leave("No Graphics Library");
-
- for(i=0;i<MENUITEMS;i++) /* set menu-strip */
- { /* could have be done on declaration */
- sizemenu[i]=sizemenu[0];
- sizemenu[i].NextItem=&sizemenu[i+1];
- sizemenu[i].ItemFill=(APTR)&item[i+MENUITEMS];
- sizemenu[i].TopEdge=i*11;
- item[i]=item[0];
- item[i+MENUITEMS]=item[0];
- item[i+MENUITEMS].IText=sizetxt[i];
- item[i+MENUITEMS].LeftEdge=11;
- item[i].IText=mtxt[i];
- mi[i]=mi[0];
- mi[i].NextItem=&mi[i+1];
- mi[i].ItemFill=(APTR)&item[i];
- mi[i].TopEdge=i*11;
- }
- mi[MENUITEMS-1].NextItem=NULL;
- sizemenu[MENUITEMS-1].NextItem=NULL;
- mi[2].SubItem=&sizemenu[0];
- mi[5].SubItem=&about;
- sizemenu[mazesize].Flags|=CHECKED;
-
- if (!(screen = (struct Screen*) OpenScreen(&ns))) /* open screen & window */
- leave ("Can't open Screen");
- bm = screen->ViewPort.RasInfo->BitMap;
- rp = &screen->RastPort;
-
- nw.Screen=screen;
- if (!(window = (struct Window*) OpenWindow(&nw))) leave("Can't open Window");
- SetMenuStrip(window,&menu);
-
- SetRGB4(&screen->ViewPort,0,0,0,0); /* set colors, 1-7 is a grey scale */
- for(i=1;i<7;i++) SetRGB4(&screen->ViewPort,i,2+2*i,2+2*i,2+2*i);
- SetRGB4(&screen->ViewPort,7,8,8,15);
-
- /* stuff needed by FloodFill, AreaFill */
- if(!(raster=(char *)AllocRaster(192,188))) leave("Can't allocate TmpRaster");
- InitTmpRas(&tmpras,raster,4512);
- rp->TmpRas=&tmpras;
- InitArea(&areainfo,areapts,7);
- rp->AreaInfo=&areainfo;
- BNDRYOFF(rp);
-
- for(i=0;i<3;i++) /* Draw status-display box */
- {
- SetAPen(rp,i+3);
- AreaMove(rp,190+5*i,12+5*i);
- AreaDraw(rp,319-5*i,12+5*i);
- AreaDraw(rp,319-5*i,125-5*i);
- AreaDraw(rp,319-5*i-5,125-5*i-5);
- AreaDraw(rp,319-5*i-5,12+i*5+5);
- AreaDraw(rp,190+5*i+5,12+i*5+5);
- AreaEnd(rp);
- SetAPen(rp,i+2);
- AreaMove(rp,190+5*i,12+5*i);
- AreaDraw(rp,190+5*i,125-5*i);
- AreaDraw(rp,319-5*i,125-5*i);
- AreaDraw(rp,319-5*i-5,125-5*i-5);
- AreaDraw(rp,319-5*i-5,12+i*5+5);
- AreaDraw(rp,190+5*i+5,12+i*5+5);
- AreaEnd(rp);
- }
-
- newmaze();
-
- for(;;) /* main loop, wait for a message if not in demo-mode */
- {
- if (!demomode) WaitPort(window->UserPort);
- else demo();
- if(msg=(struct IntuiMessage*)GetMsg(window->UserPort))
- {
- demomode=FALSE;
- class=msg->Class;
- code=msg->Code;
- ReplyMsg(msg);
- switch(class)
- {
- case CLOSEWINDOW:
- leave("");
- case VANILLAKEY:
- if(y!=wayout || x!=xsize-3)
- switch(code) /* we check numbers 6/4/8, these are arrows on the */
- { /* num pad keys, so we don't need RawKeyConvert */
- case '8':
- forward();
- break;
- case '4':
- left();
- break;
- case '6':
- right();
- break;
- }
- break;
- case MENUPICK:
- switch(ITEMNUM(code))
- {
- case 0: /* map */
- showmaze();
- moves+=30;
- break; /* New Maze */
- case 1:
- newmaze();
- break;
- case 2:
- if(SUBNUM(code)==mazesize) break;
- sizemenu[mazesize].Flags&=~CHECKED;
- mazesize=SUBNUM(code);
- sizemenu[mazesize].Flags|=CHECKED;
- newmaze();
- break;
- case 3: /* Demo */
- demomode=TRUE;
- break;
- case 4: /* Quit */
- leave("");
- case 5: /* About */
- ; /* Inserted ; to make Aztec happy -- PDS(1) -- 31-jul-88 */
- }
- }
- }
- }
- }
-
- void leave(error)
- char *error;
- {
- BPTR file;
- /* Free Resouces & Exit */
- if(window) CloseWindow(window);
- if(screen) CloseScreen(screen);
- if(IntuitionBase) CloseLibrary(IntuitionBase);
- if(GfxBase) CloseLibrary(GfxBase);
- if (mymaze) FreeMem(mymaze,(xsize>>3)*ysize);
- if (raster) FreeRaster(raster,192,188);
-
- if (*error && WorkBench &&
- (file=Open("con:20/70/400/60/Maze 3D Demo",MODE_OLDFILE)))
- {
- Write(file,error,strlen(error));
- Delay(200L);
- Close(file);
- }
- else if (*error) printf("%s\n",error);
- exit(0);
- }
-
- void newmaze()
- {
- if (mymaze) FreeMem(mymaze,(xsize>>3)*ysize); /* Free old maze */
- xsize=32+mazesize*16; /* get new dimension */
- ysize=12+mazesize*12;
- if (!(mymaze=(char*) AllocMem((xsize>>3)*ysize,MEMF_CHIP|MEMF_CLEAR)))
- leave("Out of chip memory"); /* allocate new one */
- SetAPen(rp,6); /* clear status display */
- RectFill(rp,205,27,304,110);
- SetAPen(rp,1);
- statusline(10,"Moves:");
- statusline(30,"Looking");
- statusline(60,"Size:");
- sprintf(buffer,"%ld*%ld",xsize,ysize);
- statusline(70,buffer);
-
- maze(xsize,ysize,mymaze); /* genarate a new maze */
- seed = FastRand(seed);
- y= ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe; /* random start point */
- x= 2;
- seed = FastRand(seed);
- wayout = ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe; /* random exit */
- MAZESET(xsize-3,wayout,xsize,mymaze); /* open exit */
- direction=1; /* heading right (east) */
- statusline(40,heading[direction]);
- moves=0;
- show3d();
- showmaze();
- }
-
- void statusline(y,text)
- short y;
- char *text;
- { /* Write text, centered, into */
- Move(rp,255-strlen(text)*4,27+y); /* status-display */
- SetAPen(rp,1);
- SetBPen(rp,6);
- Text(rp,text,strlen(text));
- }
-
- void showmaze() /* show the maze */
- {
- mazeimage.Width=xsize; /* we define a Image-structure on our */
- mazeimage.Height=ysize; /* bitmapped maze */
- mazeimage.ImageData=(short*)mymaze;
- DrawImage(rp,&mazeimage,255-(xsize/2),127);
- /* wait for a message */
- while(! window->UserPort->mp_MsgList.lh_Head->ln_Succ)
- {
- SetAPen(rp,++i&7); /* exit and current position */
- WritePixel(rp,255-(xsize/2)+x,127+y); /* are blinking */
- WritePixel(rp,253-(xsize/2)+xsize,127+wayout);
- Delay(6L);
- }
- SetAPen(rp,0);
- RectFill(rp,191,127,319,199);
- }
-
- void show3d()
- {
- register short k,inner,outer,wall;
-
- WaitBOVP(rp); /* doesn't have too much effect in this case */
- for(i=1;i<7;i++) /* get the wall in front */
- if(!(MAZETEST(x+i*dirincs[direction][0],y+i*dirincs[direction][1],
- xsize,mymaze))) break;
- wall=6-i;
-
- for(k=-1;k < 2;k+=2) /* draw a 'sky' and a 'floor' */
- {
- SetAPen(rp,(k+8) % 8);
- AreaMove(rp,1,106+k*94);
- AreaDraw(rp,187,106+k*94);
- AreaDraw(rp,94+(2<<wall),106+k*(2<<wall)+k);
- AreaDraw(rp,94-(2<<wall),106+k*(2<<wall)+k);
- AreaEnd(rp);
- }
-
- if(i!=7)
- {
- if(y==wayout && (x+i*dirincs[direction][0])==xsize-1)
- { /* are we looking at the exit ? */
- SetAPen(rp,7);
- RectFill(rp,94-(2<<(++wall)),106-(2<<wall),94+(2<<wall),106);
- SetAPen(rp,1);
- RectFill(rp,94-(2<<wall),107,94+(2<<wall),106+(2<<wall));
- }
- else
- {
- SetAPen(rp,5); /* draw a light grey wall */
- RectFill(rp,94-(2<<wall),106-(2<<wall),94+(2<<wall),106+(2<<wall));
- }
- }
- else /* the front wall is too far away */
- {
- SetAPen(rp,4);
- AreaMove(rp,92,104);
- AreaDraw(rp,92,108);
- AreaDraw(rp,96,104);
- AreaDraw(rp,96,108);
- AreaEnd(rp);
- }
-
- for(k=-1;k < 2;k+=2) /* draw walls on the left and on the right */
- for(i=5-wall;i>-1;i--) /* starting from the front wall ending at */
- { /* our current position */
- int xx, yy; /* Patch to make Aztec happy -- PDS(1) -- 31-jul-88 */
- inner=(2<<(5-i)); /* inner edges of a wall */
- outer=(inner<<1); /* outer edges */
- if(outer > 94) outer=94; /* 'Clip' if too large */
- /* check if a wall or a passage */
- xx=x+dirincs[(direction+k)&3][0]+i*dirincs[direction][0]; /* PDS(1) */
- yy=y+dirincs[(direction+k)&3][1]+i*dirincs[direction][1]; /* PDS(1) */
- if(!(MAZETEST(xx,yy, xsize,mymaze)))
- { /* it's a wall */
- SetAPen(rp,4);
- AreaMove(rp,94+k*inner,106-inner);
- AreaDraw(rp,94+k*inner,106+inner);
- AreaDraw(rp,94+k*outer,106+outer);
- AreaDraw(rp,94+k*outer,106-outer);
- AreaEnd(rp);
- }
- else /* it's a passage */
- {
- SetAPen(rp,7); /* clear upper and lower corners */
- AreaMove(rp,94+k*outer,106-outer);
- AreaDraw(rp,94+k*inner,106-inner);
- AreaDraw(rp,94+k*outer,106-inner);
- AreaEnd(rp);
- SetAPen(rp,1);
- AreaMove(rp,94+k*outer,106+outer);
- AreaDraw(rp,94+k*inner,106+inner);
- AreaDraw(rp,94+k*outer,106+inner);
- AreaEnd(rp);
- SetAPen(rp,5); /* light grey wall */
- if (k==1) RectFill(rp,94+inner,106-inner,94+outer,106+inner);
- else RectFill(rp,94-outer,106-inner,94-inner,106+inner);
- }
- }
- }
-
- void demo() /* demo mode: follow the left-hand wall until we get to */
- { /* the exit */
- long delay;
- /* be fast if the exit is far away, slow if it gets nearer */
- delay=19-18*(xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)))/
- ((wayout<ysize/2? ysize-wayout:wayout)+xsize-3);
-
- if(y==wayout && x==xsize-3) /* did we reach the exit ?*/
- {
- demomode=FALSE; /* stop if we did */
- return;
- } /* is it possible to turn left ? */
- if(MAZETEST(x+dirincs[(direction-1)&3][0],y+dirincs[(direction-1)&3][1],
- xsize,mymaze))
- {
- left(); /* yes, turn left */
- Delay(delay);
- forward(); /* and one step forward */
- }
- else if(!forward()) right(); /* if not try to move forward, if everything */
- /* fails, turn right */
- Delay(delay);
- }
-
- BOOL forward() /* move one step forward if possible */
- {
- if(!(MAZETEST(x+dirincs[direction][0],
- y+dirincs[direction][1],xsize,mymaze))) return(FALSE);
-
- x+=dirincs[direction][0];
- y+=dirincs[direction][1];
- moves++;
- sprintf(buffer," %ld/%ld ",
- moves,xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)));
- statusline(20,buffer);
- show3d();
-
- if(y==wayout && x==xsize-3) /* has the exit been reached ?*/
- {
- SetAPen(rp,1); /* yes, write some stupid text */
- SetBPen(rp,7);
- Move(rp,58,104);
- Text(rp,"Solved in",9);
- SetAPen(rp,6);
- SetBPen(rp,1);
- sprintf(buffer,"%ld moves.",moves);
- Move(rp,94-strlen(buffer)*4,116);
- Text(rp,buffer,strlen(buffer));
- }
- return(TRUE);
- }
-
- void left() /* turn left */
- {
- direction=(--direction) & 3;
- show3d();
- statusline(40,heading[direction]);
- }
-
- void right() /* turn right */
- {
- direction=(++direction) & 3;
- show3d();
- statusline(40,heading[direction]);
- }
-