home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d01xx
/
d0171.lha
/
Maze
/
3DDemo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-22
|
13KB
|
468 lines
#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]);
}