#include #include #include #include #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;iViewPort.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<-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